青岛建设英文网站建设seo外包团队
青岛建设英文网站建设,seo外包团队,网站建设网络拓扑,网站设计教学搜索专题 目录 MT2238 数的增殖MT2239 二维矩阵中的最长下降序列MT2240 传染病MT2241 循环空间BD202303 第五维度 MT2238 数的增殖 难度#xff1a;黄金 时间限制#xff1a;1秒 占用内存#xff1a;128M 题目描述 给定一个数 n ( n 1000 ) n (n1000) n…搜索专题 目录 MT2238 数的增殖MT2239 二维矩阵中的最长下降序列MT2240 传染病MT2241 循环空间BD202303 第五维度 MT2238 数的增殖 难度黄金 时间限制1秒 占用内存128M 题目描述 给定一个数 n ( n 1000 ) n (n1000) n(n1000)可以按以下方法进行增殖 取原数最高位在左边加上不大于最高位一半的数不做处理。 现在问最多能生成多少个不同的数。 格式 输入格式第一行输入一个正整数 n n n。 输出格式一个正整数表示最多能生成的数的个数。 样例 1 输入 5 输出 4 备注 其中 n ≤ 10 3 n\le{10}^3 n≤103。 测试数据中生成了 5→15 5→25→125 共4个数字不计算重复数字。 相关知识点深度优先搜索 题解 这道题按其意思进行模拟即可。定义两个函数
函数一取出当前数的最高位循环取模实现。
// 获取数的最高位值
int getHighestOrder(int n)
{int highestOrder;while(n){highestOrder n%10;n / 10;}return highestOrder;
}函数二对最高位的数 n n n 按要求进行处理即在当前数 n n n 的前面添加一个数 m ( m ∈ [ 1 ∼ ⌊ n 2 ⌋ ] ) m\ (m\in\left[1\sim\left\lfloor\frac{n}{2}\right\rfloor\right]) m (m∈[1∼⌊2n⌋])。显然函数二是一个递归调用的过程。一旦最高位数 n n n 的一半小于1时整个过程就停止了注这种情况下这个数本身应该要被算进去因此要返回 1。
// 获取数的增值
int getAddedValue(int n)
{int addedValue 1;int halfHighestValue getHighestOrder(n) / 2;for(int i1; ihalfHighestValue; i)addedValue getAddedValue(i);return addedValue;
}基于此可得到求解本题的完整代码
/*MT2238 数的增值 搜索
*/
#includebits/stdc.h
using namespace std;// 获取数的最高位值
int getHighestOrder(int n)
{int highestOrder;while(n){highestOrder n%10;n / 10;}return highestOrder;
}
// 获取数的增值
int getAddedValue(int n)
{int addedValue 1;int halfHighestValue getHighestOrder(n) / 2;for(int i1; ihalfHighestValue; i)addedValue getAddedValue(i);return addedValue;
}int main( )
{// 录入数据 int n;cinn;// 输出数的增值coutgetAddedValue(n)endl;return 0;
}MT2239 二维矩阵中的最长下降序列 难度钻石 时间限制1秒 占用内存128M 题目描述 给定一个 n × m n\times m n×m 的矩阵然后可以随机选取一个点作为起始点每次可以选择该点的上下左右四个相邻点中的一个并且保证相邻点的值小于当前点的值。问最长下降序列的长度是多少 格式 输入格式第一行输入两个正整数 n , m ( 1 ≤ n , m ≤ 100 ) n,\ m\ \left(1\le n,\ m\le100\right) n, m (1≤n, m≤100) 接下来 n n n 行每行 m m m 个数字 a [ i ] [ j ] ( ( 1 ≤ a [ i ] [ j ] ≤ 4 × 10 4 ) ) a\left[i\right]\left[j\right]\ (\left(1\le a\left[i\right]\left[j\right]\le4{\times10}^4\right)) a[i][j] ((1≤a[i][j]≤4×104))。 输出格式输出最长下降序列的长度。 样例 1 输入 5 4 1 2 3 4 16 17 18 19 15 24 25 20 14 23 22 21 13 12 11 10 输出 16 备注 样例中选取起始点 25然后 25→24→23→……→11→10长度为 16。 相关知识点深度优先搜索、记忆化搜索 题解 题目的意思是在一个 n × m n\times m n×m 的矩阵中找一个位置使得从该位置出发只能往上、下、左、右四个方向行走且下一个位置上的值必须小于当前位置上的值能得到最长的路径长度。这是一道非常典型的DFS走迷宫问题。最简单粗暴的方式就是遍历整个矩阵中的全部位置算出从该位置出发得到的最长路径长度。但遗憾的是在题目给出的最广可达 100 × 100 100\times100 100×100 的数据范围下这种办法肯定不能拿到满分。
注意到一个事该办法超时的原因在于每次基于某个位置进行深度优先搜索时都有可能会出现重复计算。例如下图中当从值为 14 的位置出发时它会找到一条长度为 9 的路径如左图所示。而当从值为13的位置出发时它会找那条长度为 8 的路径如右图所示。 若假设顺序为 14、13、……。则在从 14 出发进行深度优先搜索时它肯定会先计算从 13 出发得到的最长下降子序列而从 13 出发时它又会先计算从12出发得到的最长下降子序列……直到该过程结束并在最后通过回溯得到从 14 出发得到的最长下降子序列长度。此时当我们再计算 13 的最长子序列时它也会重复上述过程这便是大量重复计算的地方。试想如果我们在求某个点的最长下降子序列时对其搜索到的所有点的最长子序列长度进行存储即 这样一来以 14 所在位置为起点涉及到的最长下降序列中的任何点都将在递归过程中找到其自身的最长下降子序列并且形成记录。这就避免了后续重复寻找 13、12、……、2、1 等值所在位置的最长下降子序列。另一方面假设现在要求值为 15 的位置处的最长下降子序列则其只需要做一件事判断当前这个点是否有更长的下降子序列如果不是则当前位置存储的值即为其最大值否则就对当前位置继续进行深搜。即对值为 15 的位置 ( 1 , 1 ) \left(1,\ 1\right) (1, 1) 而言它只需做一件事 p a t h ( 1 , 1 ) max { p a t h ( 1 , 1 ) , D F S ( n e x t P o i n t ) 1 } path(1,1)\text{max}\{path(1,1) ,DFS(nextPoint)1\} path(1,1)max{path(1,1),DFS(nextPoint)1}
其中 nextPoint 表示从点 ( 1 , 1 ) \left(1,\ 1\right) (1, 1) 出发能走的下一个点在给出的例子中 ( 1 , 1 ) \left(1,\ 1\right) (1, 1) 的下一个可行点只有 ( 1 , 2 ) \left(1,\ 2\right) (1, 2)而根据矩阵中存储的值可知从点 ( 1 , 2 ) \left(1,\ 2\right) (1, 2) 出发能得到的最长下降子序列长度为 9 于是有 p a t h ( 1 , 1 ) max { p a t h ( 1 , 1 ) , 10 } path(1,1)\text{max}\{path(1,1) ,10\} path(1,1)max{path(1,1),10}
显然对位置 ( 1 , 1 ) \left(1,\ 1\right) (1, 1) 而言其默认最长下降子序列长度为 p a t h ( 1 , 1 ) 1 path(1,1)1 path(1,1)1即仅含自身一个点。因此基于以上式子可以直接得到从 ( 1 , 1 ) \left(1,\ 1\right) (1, 1) 出发的最长下降子序列长度为 10。
我们将以上这种记录前面搜索过程相关结果的搜索称为 “记忆化搜索”。在这种需要计算一个矩阵的最长或最短路径问题时记忆化搜索可以大大降低计算成本。
下面直接给出基于以上思路得到的求解本题的完整代码
/*MT2239 二维矩阵中的最长下降序列 深度优先搜索、记忆化搜索
*/ #includebits/stdc.h
using namespace std;const int N 105;
// 存放矩阵的二维表对应的访问标记表记录该位置的最长下降序列长度
int matrix[N][N], vis[N][N];
// 矩阵规格
int n, m;
// 四种行走方式上、下、左、右
int forwardX[] {0, 0, -1, 1};
int forwardY[] {-1, 1, 0, 0};// 录入矩阵信息
void getMatrix()
{for(int i1; in; i)for(int j1; jm; j)cinmatrix[i][j];
}// 获取指定位置的最长下降序列长度带记忆化搜索
int DFS(int x, int y)
{// 如果已经被访问过则直接返回该点记录的最长下降序列长度 if(vis[x][y]) return vis[x][y];// 否则初始化该点的最长下降序列长度为 1 即自身 vis[x][y] 1;// 向各方向发散寻找最长下降序列for(int i0; i4; i){int nextx x forwardX[i];int nexty y forwardY[i];// 越界或所处位置的数值更大则直接跳过 if(nextx 1 || nextx n || nexty 1 || nexty m || matrix[nextx][nexty] matrix[x][y])continue;// 否则将当前的最大下降子序列进行更新vis[x][y] max(vis[x][y], DFS(nextx, nexty) 1); } return vis[x][y];
}// 获取最长下降序列
int getLongestDesSeq()
{int tmp, longestDesSeq 0;for(int i1; in; i)for(int j1; jm; j){tmp DFS(i, j);if(tmp longestDesSeq)longestDesSeq tmp;}return longestDesSeq;
}int main( )
{// 录入数据 cinnm;getMatrix();// 寻找最长下降序列 coutgetLongestDesSeq()endl;return 0;
}MT2240 传染病 难度钻石 时间限制1秒 占用内存128M 题目描述 小码哥正在研究传染病的相关知识现在遇到了这么一个问题有一个长为 n n n 宽为 m m m 高为 k k k 层数的的长方体它可以看成 n × m × k n\times m\times k n×m×k 个 1 × 1 × 1 1\times1\times1 1×1×1 大小的单位正方体。每个单位正方体都有一个字符。.表示该位置防疫措施不好如果被传染了就会感染病毒。# 表示该区人民防疫措施良好永远不会感染病毒甚至都不会成为病毒的携带者。 现在在长方体的最顶层层号为 1某个位置因实验室泄露爆发了病毒。每过一个单位时间病毒将扩散至周围 6 个方向的地区。如果某个地区为 #那么一定不会被感染并且不会携带病毒同时也不会传播病毒。但如果这个地方存在泄露的实验室那么哪怕防疫措施再好也会被感染以及传播病毒。 现在小码哥需要知道假如第一层坐标为 ( x , y ) \left(x,\ y\right) (x, y) 的实验室泄露了病毒那么最多会有多少区域被感染。 格式 输入格式第一行三个正整数 k , n , m ( k , n , m ≤ 10 ) k,\ n,\ m\ (k,\ n,\ m\le10) k, n, m (k, n, m≤10) 接下来 k k k 层每层 n n n 行每行 m m m 个字符表示长方体每个单位的状态 最后一行两个正整数 x , y ( x ≤ n , y ≤ m ) x,\ y\ \left(x\le n,\ y\le m\right) x, y (x≤n, y≤m) 表示发生泄漏的实验室的坐标这个实验室在第一层。 输出格式按题目要求输出一行一个整数表示答案。 样例 1 输入 3 3 3.#.
###
##..##
###
##....
...
...1 1输出 13 相关知识点广度优先搜索 题解 这道题实际上就是基于广度优先搜索的走格子问题不同的是这道题里的空间是一个三维空间。为此我们只需要在BFS中再额外地添加两种行走方式然后从题目给出的起点进行行走并逐个统计感染的实验室个数即可。另外由于广度优先搜索需要用到队列这一数据结构故为了方便使用我们单独定义了一个类似“三元组”形式的数据结构结构体用于表示三维空间中的一个点。
下面直接给出求解本题的完整代码
/*MT2240 传染病 广度优先搜索
*/ #includebits/stdc.h
using namespace std;const int N 13;
// 存放矩阵的二维表对应的访问标记表
char cube[N][N][N];
int vis[N][N][N];
// 立方体规格
int k, n, m;
// 六种行走方式上、下、左、右、前、后
int forwardX[] {0, 0, -1, 1, 0, 0};
int forwardY[] {0, 0, 0, 0, -1, 1};
int forwardZ[] {-1, 1, 0, 0, 0, 0};
// 封装三维空间中一个点的数据结构
struct Site{int x, y, z;Site(){}Site(int x, int y ,int z):x(x),y(y),z(z){}
};
Site curSite, nextSite;// 录入立方体信息
void getCube()
{for(int l1; lk; l)for(int i1; in; i)for(int j1; jm; j)cincube[i][j][l];
}// 检测下个区域是否可达
bool check(Site site){int x site.x, y site.y, z site.z;// 测下个区域是否合法if(x1 || xn || y1 || ym || z1 || zk) return false;// 测下个区域能否继续传播病毒if(vis[x][y][z] || cube[x][y][z] #)return false;return true;
} // 计被感染的区块个数广度优先搜索
int getInfectedBlocks(int x, int y)
{int infectedBlocks 0;// 初始化队列 queueSite q;q.push(Site(x,y,1));vis[x][y][1] true;// 广度优先搜索while(!q.empty()){// 取出当前队头元素 curSite q.front();// 队头元素出队列q.pop();// 统计被感染数 infectedBlocks;// 病毒扩散 for(int i0; i6; i){// 扩散后的新位置 nextSite.x curSite.x forwardX[i];nextSite.y curSite.y forwardY[i];nextSite.z curSite.z forwardZ[i];// 若新扩散成立if(check(nextSite)) {// 则入队列 q.push(nextSite);// 置访问标记为真vis[nextSite.x][nextSite.y][nextSite.z] true;}}}return infectedBlocks;
}int main( )
{// 录入数据 int x, y; cinknm;getCube();cinxy;// 统计被感染的区块个数 coutgetInfectedBlocks(x, y)endl;return 0;
}MT2241 循环空间 难度钻石 时间限制1秒 占用内存256M 题目描述 给出一个二维的由0、1、2组成的 n × n n\times n n×n 空间0 表示障碍物1 表示可行走2 表示起点这个空间是循环的如走到左边界再往左走你会出现在右边界对应位置我们每次能向上、下、左、右中的一个方向行走一格。 请输出从起点到每个点的最短路径长度。 格式 输入格式第一行一个正整数 n n n 表示地图的边长 接下来 n n n 行每行 n n n 个整数0 表示障碍物1 表示可行走2 表示起点。 输出格式输出 n n n 行每行 n n n 个整数。0 表示起点或无法到达的点其他数字表示从起点到此处的最短路径长度。 样例 1 输入 5 0 1 2 1 0 0 0 1 0 1 1 1 0 0 1 1 0 0 1 0 1 1 1 0 0 输出 0 1 0 1 0 0 0 1 0 7 5 6 0 0 6 4 0 0 0 0 3 2 1 0 0 备注 对于30%的数据 1 ≤ n ≤ 30 1\le n\le30 1≤n≤30 对于60%的数据 1 ≤ n ≤ 300 1\le n\le300 1≤n≤300 对于100%的数据 1 ≤ n ≤ 2000 1\le n\le2000 1≤n≤2000。 相关知识点广度优先搜索 题解 求二维矩阵中指定点到其余所有点的最短距离一道典型的广度优先搜索题。不过需要注意的是本题给出的二维矩阵是 “循环” 的即处于边界位置并继续往边界方向行走时会直接走到另一个相对的边界。这相当于是对“行走方式”添加了一种新的准则。我们的处理办法也很简单将新位置在各维度上的值加上整个二维矩阵的规格避免了向索引降低的方向行走时出现负的索引并对该规格取余避免出现索引出现超过矩阵规格的情况。
由于本题涉及到的是一个二维空间因此我们直接利用 STL 提供的模板数据结构 pair 作为 BFS 中队列的基本数据类型。下面直接给出求解本题的完整代码
/*MT2241 循环空间 广度优先搜索必须快读输入数据否则会超时 3/10 的数据
*/ #includebits/stdc.h
using namespace std;const int N 2005;
// 存放矩阵的二维表对应的访问标记表到该点的最短路径
int matrix[N][N], vis[N][N];
// 矩阵规格起始点坐标
int n, startX, startY;
// 当前位置和下一个状态所处位置
pairint, int curPoint, nextPoint;
// 四种行走方式上、下、左、右
int forwardX[] {0, 0, -1, 1};
int forwardY[] {-1, 1, 0, 0};// 录入矩阵信息
void getMatrix()
{for(int i0; in; i)for(int j0; jn; j){cinmatrix[i][j];if(matrix[i][j] 2){startX i;startY j; }}
}// 获取从指定位置出发到各点的最短路径长度
void BFS(int x, int y)
{// 初始化访问标记表memset(vis, -1, sizeof(vis));// 初始化队列 queuepairint,int q;// 创建当前的点位置curPoint make_pair(x,y); // 入队列 q.push(curPoint);// 重置访问标记 vis[x][y] 0;// 广度优先搜索while(!q.empty()){// 取出当前队头元素 curPoint q.front();// 队头元素出队列q.pop();// 向四个方向行走 for(int i0; i4; i){// 新位置 nextPoint make_pair((curPoint.firstforwardX[i]n) % n, (curPoint.secondforwardY[i]n) % n);// 如果新位置未被访问过且可行走则更新其值if(vis[nextPoint.first][nextPoint.second] 0 matrix[nextPoint.first][nextPoint.second] 1){vis[nextPoint.first][nextPoint.second] vis[curPoint.first][curPoint.second] 1; // 入队列q.push(nextPoint);}}}// 整个广度优先搜索结束后剩余所有尚未被访问的位置将无法到达for(int i0; in; i)for(int j0; jn; j)if(vis[i][j] 0)vis[i][j] 0;
}// 输出最短路径长度矩阵
void printPathLength()
{for(int i0; in; i){for(int j0; jn; j)coutvis[i][j] ;coutendl;}
} int main( )
{// 快读输入数据 ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);// 录入数据 cinn;getMatrix();// 寻找从指定点出发的最短路径 BFS(startX, startY);// 输出指定点到所有点的最短路径长度printPathLength(); return 0;
}BD202303 第五维度 难度星耀 时间限制1秒 占用内存64M 题目描述 零维是点点动成线 一维是线线动成面 二维是面面动成体 三维是体体动成史 四维是史史动??? 现在人类企图理解第五维度。 小度是第五维度的一位智者。一天小度发现人类的许多科学家在试图理解第五维度人类是四维生物若是他们理解了第五维度很可能也会到来第五维度的空间这显然是小度不愿意看到的毕竟哪里都有人口数量的问题….所以小度希望他们尽可能晚的理解第五维度因此小度用更高维度的视角把所有人类中在理解第五维的科学家都看到了而这些科学家的智商会不一样所以他们的理解速度 V i V_i Vi 也会不一样并且他们开始理解的时间点 S i S_i Si 也不一样。理解速度 V i V_i Vi 描述为每过单位时间可获得 V i V_i Vi 个单位理解力也就是说在 S i 1 S_i1 Si1 的时间点该科学家会第一次贡献 V i V_i Vi 的理解力。我们定义理解力总数超过 m m m 时理解了第五维度。 小度因为维度更高可以使用时间悖论来给人类一次重大的打击小度可以让任意一位科学家在任意一个时间点消失所以他接下来的理解不会继续而且人类不会记得他所以他之前的贡献会消失。因为小度能力有限所以小度只能使用一次暂时悖论。 现在求在尽可能晚的情况下人类理解第五维度的最早时间点。时间点初始为 0但显然没有科学家能够在 0 时刻有贡献。 格式 输入格式第一行给出一个整数 n n n 和一个整数 m m m表示有 n n n 个科学家在理解力总数超过 m m m 时理解了第五维度 第二行至第 n 1 n1 n1 行每行两个整数 S i S_i Si 和 V i V_i Vi 。 对于 100% 的数据 1 ≤ n ≤ 10 5 m ≤ 2 × 10 9 0 ≤ S i ≤ 2 × 10 9 0 ≤ V i ≤ 10 3 1\le n\le{10}^5m\le2\times{10}^90\le S_i\le2\times{10}^90\le V_i\le{10}^3 1≤n≤105m≤2×1090≤Si≤2×1090≤Vi≤103。 输出格式一行包含一个整数 T T T 表示在尽可能晚的情况下人类理解第五维度的最早时间点。若人类永远无法理解第五维度则输出 -1。 样例 1 输入 3 10 0 1 4 6 5 1 输出 8 样例 2 输入 3 10 0 0 4 0 5 1 输出 -1 备注 对于第一个样例使得 S i 4 V i 6 {\ S}_i4V_i6 Si4Vi6 的科学家消失则每个时刻总共理解力为0 1 2 3 4 5 7 9 11在时刻 8 超过 m 10 m10 m10因此输出 8对于第二个样例人类永远无法理解第五维度因此输出 -1 。 相关知识点贪心 题解 首先对本题的意思进行一个简化输入 n n n 个科学家开始理解第五维度的时间点 S i {\ S}_i Si 以及其单位时间能得到的理解力 V i V_i Vi 均为非负整数那么随着时间的推移全部科学家的总理解力肯定是不断增加的。一旦总理解力达到了 m m m 则认为人类能理解第五维度。但是现在有一个具有上帝视角的人他总能找到在这些科学家中具有最高理解力的那位并将其从抹除则他的理解力也将消失那么这时候人类还能理解第五维度么如果能则输出在这样的前提下人类理解第五维度的最早时间否则输出 -1。
本题中 m m m 的最大取值为 2 × 10 9 2\times{10}^9 2×109 那么在极限情况下只有一个科学家且 S i 0 , V i 1 {\ S}_i0,\ V_i1 Si0, Vi1的最长时间也是 2 × 10 9 2\times{10}^9 2×109 。可以看出如果直接枚举时间线算出人类的总理解力并在抹除具有最高理解力的人后判断与 m m m 的大小关系是极易超时的。在这种情况下一定要敏锐地想到二分法查找。
对于每一次查找的时间 T T T可采取下式求解全部人类的总理解力
for(int i0; in; i){if(T S[i]){// 累加sum_comp ((long long)T - S[i]) * V[i];}
}注意题目要求在尽可能晚的情况下人类理解第五维度的最早时间点。而尽可能晚就意味着每次都要抹除此刻对人类理解力共享最大的科学家。为此我们可以在求全部人类总理解力的同时记录其中的最大理解力并在最后减去该值即可于是有
// 判断在指定时间下人类能否理解第五维度
bool check(int T)
{// 在指定时间下人类的理解力总和、这些理解力中的最大值 long long sum_comp 0, max_comp 0, tmp;// 计算所有人的理解力总和并找到其中的最大值for(int i0; in; i){if(T S[i]){// 计算当前第 i 个人的获取的理解力 tmp ((long long)T - S[i]) * V[i];// 累加sum_comp tmp;// 找出具有最大贡献的理解力 max_comp max(max_comp, tmp);}}// 要求尽可能晚的情况下那就把具有最大共享的理解力去除即可 return (sum_comp - max_comp m);
}下面给出基于以上思路得到的求解本题的完整代码
/*BD202303 第五维度 贪心、二分法
*/ #includebits/stdc.h
using namespace std;const int N 1e55;
// 各科学家的理解力起始数组、单位时间增长数组
int S[N], V[N];
// 科学家数量和需要理解五维空间的总理解力
int n, m; // 判断在指定时间下人类能否理解第五维度
bool check(int T)
{// 在指定时间下人类的理解力总和、这些理解力中的最大值 long long sum_comp 0, max_comp 0, tmp;// 计算所有人的理解力总和并找到其中的最大值for(int i0; in; i){if(T S[i]){// 计算当前第 i 个人的获取的理解力 tmp ((long long)T - S[i]) * V[i];// 累加sum_comp tmp;// 找出具有最大贡献的理解力 max_comp max(max_comp, tmp);}}// 要求尽可能晚的情况下那就把具有最大共享的理解力去除即可 return (sum_comp - max_comp m);
}// 二分查找使科学家能理解的最早时间
int BinarySearch()
{// 能理解的极限情况下只有 1 个科学家理解力最小为 1则最长的时间为 2e9long long l 1, r 2e9;int ans -1;// 二分查找 while(l r){int mid lr 1;// 判断该时间下尽可能晚人类能否理解第五维度if(check(mid)){r mid;ans mid; }else{l mid 1;} }return ans;
}int main( )
{// 录入数据 cinnm;for(int i0; in; i)cinS[i]V[i];// 输出使科学家能理解的最早时间coutBinarySearch()endl;return 0;
}END
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/92273.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!