搜索2

  • 一、马的遍历
  • 二、 求细胞数量
  • 三、01迷宫
  • 四、奇怪的电梯
  • 五、海战
  • 六、路障

一、马的遍历

题目描述
有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步
输入
一行四个数据,棋盘的大小和马的坐标

输出
一个n*m的矩阵,同一行元素之间用空格分离。代表马到达某个点最少要走几步。不能到达则输出-1。
样例输入
3 3 1 1
样例输出
0 3 2
3 -1 1
2 1 4
题目分析
本题思路在于bfs,找出马的八个可以走的下一个位置,使用cnt数组记录步数,每次的循环里都使用cnt[tx][ty] = cnt[sx][sy] + 1;来更新到达某一位置的步数。注意使用队列的思想,先把初始位置入队,之后在循环内把初始位置出队并且记录,之后在走到下一位置之后,把下一元素的坐标入队,以此类推,最后就能得到到每个位置的cnt了。

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int m, n, a, b;
int s[8][2] = {1, 2, 2, 1, 1, -2, 2, -1, -1, 2, -2, 1, -1, -2, -2, -1};//马可以到达的八个位置int visit[500][500], cnt[500][500];
queue<int> q;
void bfs(int sx, int sy)
{q.push(sx);q.push(sy);//sx,sy也就是现在的坐标,入队int tx, ty;//代表下一步的位置visit[sx][sy] = 1;//记录已经走过sx,sywhile (!q.empty()) {//当队列不空的时候sx = q.front();//sx等于队首元素q.pop();//队首元素出队sy = q.front();//sy等于队首元素q.pop();//队首元素出队for (int k = 0; k < 8; k++) {//马可以到达的八个位置遍历tx = sx + s[k][0];ty = sy + s[k][1];//更新马下一步要到达的位置if (tx >= 1 && tx <= m && ty >= 1 && ty <= n && visit[tx][ty] == 0) {//如果在棋盘上而且没走过visit[tx][ty] = 1;//走这个位置cnt[tx][ty] = cnt[sx][sy] + 1;//走过的步数++q.push(tx);//队中元素出队q.push(ty);}}}
}
int main()
{cin >> m >> n;int ar[m + 1][n + 1];cin >> a >> b;memset(cnt, -1, sizeof(cnt));
memset(visit, 0, sizeof(visit));
memset(ar, 0, sizeof(ar));//初始化三个数组cnt[a][b] = 0;//代表开始的位置到开始的位置步数是0bfs(a, b);//搜索for(int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++)cout << cnt[i][j] << " ";//输出到达每一个位置的步数cout << endl;}return 0;
}

二、 求细胞数量

题目描述
一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。

输入
第一行两个整数代表矩阵大小 n 和 m。 接下来 n 行,每行一个长度为 m 的只含字符 0 到 9 的字符串,代表这个n×m 的矩阵。
输出
一行一个整数代表细胞个数。

样例输入
4 10
0234500067
1034560500
2045600671
0000000089
样例输出
4
提示
0 < m, n <= 400
题目分析
本题思路bfs,但是这个不是记录到每个位置的步数,而是连通域的个数,这就需要在bfs内部加cnt记录,同时在main函数里对每一个等于一的元素进行搜索,遍历他周围的细胞,直到遍历结束。

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int m, n, cnt = 0;
int s[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};//八个不同的下一步的遍历方式
char ar[500][500];//由于输入的数据中间没有空格,所以需要设置为char类型
int arr[500][500];//用来储存是否有细胞
queue<int> q;
void bfs(int sx, int sy) {q.push(sx), q.push(sy);//初始位置入队cnt++;//细胞数目++int tx, ty;//下一步位置arr[sx][sy] = 0;//表示已经遍历过这个位置while (!q.empty()) {//当队列不空时sx = q.front();//sx,sy分别为现在所处位置的坐标q.pop();sy = q.front();q.pop();//出队for (int k = 0; k < 4; k++) {//四个可能的遍历方式tx = sx + s[k][0];ty = sy + s[k][1];//更新下一步位置if (tx >= 1 && tx <= m && ty >= 1 && ty <= n && arr[tx][ty] == 1) {//位置符合条件arr[tx][ty] = 0;//走这个位置q.push(tx), q.push(ty);//现在的坐标入队}       }    }}
int main() {cin >> m >> n;memset(arr, 1, sizeof(arr));//初始化arr数组(设为每个位置都有细胞)for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++) {cin >> ar[i][j];if (ar[i][j] == '0')   arr[i][j] = 0;//输入为‘0’时代表这个地方没有细胞,更新arr[i][j]}for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++) {if(arr[i][j] == 1)   bfs(i, j);}//当这个位置有细胞时,搜索    cout << cnt << endl;//输出细胞数return 0;}

三、01迷宫

题目描述
有一个仅由数字0与1组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。 你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
输入
第1行为两个正整数n,m。 下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。
接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。
输出
m行,对于每个询问输出相应答案。

样例输入
2 2
01
10
1 1
2 2
样例输出
4
4
提示
n <= 400
题目分析
本题思路仍然为bfs,但需要当前位置和下一位置的值不同,也就是ar[tx][ty] != ar[sx][sy],同时在while循环下输入询问坐标并搜索,使用cn代表能到的格子数,在bfs里面到达下一位置时cn增加1即可。

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int m, n, a, b, cn;
int s[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1}, visit[500][500], ar[500][500];
char car[500][500];
queue<int> q;
void bfs(int sx, int sy) {memset(visit, 0, sizeof(visit));q.push(sx), q.push(sy);//初始位置入队int tx, ty;//定义下一步位置的坐标visit[sx][sy] = 1;//走过这一位置while (!q.empty()) {//当队列不空的时候sx = q.front();   q.pop();sy = q.front();   q.pop();//队首元素就是现在的位置,sx,sy记录现在的位置for (int k = 0; k < 4; k++) {//遍历四个方向tx = sx + s[k][0];ty = sy + s[k][1];//更新下一步的位置if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && (visit[tx][ty] == 0) && (ar[tx][ty] != ar[sx][sy])) {//如果在迷宫里而且没被访问过而且和上一步的值不一样visit[tx][ty] = 1;//访问这个位置cn += 1;//能移动到的格子数加1q.push(tx), q.push(ty);//当前位置的坐标入队}        }    }}
int main() {cin >> m >> n;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++) {cin >> car[i][j];//输入字符串ar[i][j] = car[i][j] - '0';//转化为int类型的数字}while (m --) {cin >> a >> b;//输入想要询问的位置cn = 1;//一定可以到现在的格子,所以先赋值为1bfs(a, b);//搜索cout << cn << endl;}//输出可以到达的格子数return 0;}

四、奇怪的电梯

题目描述
有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)上有一个数字Ki(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3,3,1,2,5代表了Ki(K1=3,K2=3,…),从1楼开始。在1楼,按“上”可以到4楼,按“下”是不起作用的,因为没有−2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入
共二行。
第一行为3个用空格隔开的正整数,表示N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为N个用空格隔开的非负整数,表示Ki。
输出
输出一行,即最少按键次数,若无法到达,则输出−1。
样例输入
5 1 5
3 3 1 2 5
样例输出
3
题目分析
本题不需要设坐标,只有一个坐标轴,但是需要分情况讨论,注意向上向下两种情况都需要考虑而且都入队,之后对两种情况分别分析,如果向上向下都在范围内,就都入队,之后总会有pop出去的时候,但是注意cnt[i]只能更新一次,所以第一次到达b位置会对cnt[b]进行更新,不用担心最后结果不正确。

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int n, a, b;
int cnt[500], ar[500];
queue<int> q;
void bfs(int s)
{q.push(a);//a入队,也就是当前楼层int e;while (!q.empty()) {//当队不空的时候e = q.front();//e等于队首元素if (e + ar[e] > 0 && e + ar[e] <= n && cnt[e + ar[e]] == -1) {//如果向上走符合要求且没到过第e+ar[e]层楼的时候cnt[e + ar[e]] = cnt[e] + 1;//a到e+ar[e]需要按的按钮数等于a到e需要按的按钮数加1q.push(e + ar[e]);//当前楼层入队}if (e - ar[e] > 0 && e - ar[e] <= n && cnt[e - ar[e]] == -1) {//思路同上,向下走cnt[e - ar[e]] = cnt[e] + 1;q.push(e - ar[e]);}q.pop();//弹出队首元素(也就是最开始在队里的元素)}//本题把两种情况都入队,之后对每一种情况都分别分析
}
int main()
{cin >> n >> a >> b;//一共n层楼,从a到bfor (int i = 1; i <= n; i++)cin >> ar[i];//输入每层楼可以上下移动的楼层数memset(cnt, -1, sizeof(cnt));//初始化(都不能到达)cnt[a] = 0;//a到a需要按按钮的次数是0bfs(a);//搜索cout << cnt[b] << endl;//输出a到b需要按按钮的次数return 0;
}

五、海战

题目描述
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们考虑培养一些新的海军指挥官,他们选择了“海战”游戏来帮助学习。
在这个著名的游戏中,在一个方形的盘上放置了固定数量和形状的船只,每只船却不能碰到其它的船。在这个题中,我们仅考虑船是方形的,所有的船只都是由图形组成的方形。编写程序求出该棋盘上放置的船只的总数。
输入
输入文件头一行由用空格隔开的两个整数R和C组成,1<=R,C<=1000,这两个数分别表示游戏棋盘的行数和列数。接下来的R行每行包含C个字符,每个字符可以为“#”,也可为“.”,“#”表示船只的一部分,“.”表示水。
输出
为每一个段落输出一行解。如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个“#”号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出一段话“There are S ships.”,S表示船只的数量。否则输出“Bad placement.”。
样例输入
6 8
…#.#
##…#
##…#
…#
#…#
#…#…#
样例输出
There are 5 ships.
题目分析
本题思路为bfs,但是需要再加一个函数判断两个方形是否接触,可以发现,如果在上左原地以及右上四个位置组成的菱形区域内有且仅有三个是#时,两个方形接触。判断完毕之后,注意需要输出船的数量,这个和计算细胞数目那道题有相似的地方,先更新数组为01数组,1代表船。在main函数里写for循环,如果某一位置的元素是1,就进行搜索,并且遍历他周围的元素,注意使用visit数组记录是否已经遍历过这个位置的船。注意cnt只在bfs函数最外面加(因为要计算的是船的数目)

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int m, n, cnt = 0;
int s[6][2] = {-1, 0, 0, -1, 0, 1, 1, 0, 0, 0, 1, 1}, arr[500][500];//左上右下及原地右上
char ar[500][500];
queue<int> q;
bool fang(int sx, int sy) {//判断是不是两条船接触int count = 0;for (int i = 2; i < 6; i++) {//如果四个位置中有三个是#,那么接触了(上 左 原地 右上)if (arr[sx + s[i][0]][sy + s[i][1]] == '#')count++;}if (count == 3)  return 0;return 1;
}
void bfs(int sx, int sy) {q.push(sx), q.push(sy);//当前位置入队cnt++;//船只数量++int tx, ty;//定义下一个位置arr[sx][sy] = 0;//标记已经走过这个位置while (!q.empty()) {//当队列不空的时候sx = q.front();   q.pop();//取队头元素作为当前位置,并且队头元素出队sy = q.front();   q.pop();for (int k = 0; k < 4; k++) {//在四个方向上遍历tx = sx + s[k][0];ty = sy + s[k][1];//更新下一步的位置if (tx >= 1 && tx <= m && ty >= 1 && ty <= n && arr[tx][ty] == 1) {//如果下一步符合条件arr[tx][ty] = 0;//走这个位置q.push(tx), q.push(ty);//这个位置入队}}}
}
int main()
{cin >> m >> n;memset(arr, 1, sizeof(arr));//初始化arr(代表都有船)for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++) {cin >> ar[i][j];if (ar[i][j] == '.')  arr[i][j] = 0;//更新,没有船的位置arr更新为0}for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++) {if(i <= m && j <= n && fang(i, j) == 0) {//当船在区域内但是接触cout << "Bad placement." << endl;return 0;}}//那么剩下的情况都是船在区域内而且没有接触for (int i = 1; i <= m; i++)for (int j = 1; j <= n; j++) {if(arr[i][j] == 1)//当某一位置有船bfs(i, j);//搜索}cout << "There are " << cnt << " ships." << endl;//输出船的数量return 0;
}

六、路障

题目描述
B君站在一个n×n的棋盘上。最开始,B君站在(1,1)这个点,他要走到(n,n)这个点。 B君每秒可以向上下左右的某个方向移动一格,但是很不妙,C君打算阻止B君的计划。
每秒结束的时刻,C君会在(x,y)上摆一个路障。B君不能走在路障上。
B君拿到了C君准备在哪些点放置路障。所以现在你需要判断,B君能否成功走到(n,n)。
保证数据足够弱:也就是说,无需考虑“走到某处然后被一个路障砸死”的情况,因为答案不会出现此类情况。

输入
首先是一个正整数T,表示数据组数。
对于每一组数据:
第一行,一个正整数n。
接下来2n-2行,每行两个正整数x和y,意义是在那一秒结束后,(x,y)将被摆上路障。
输出
对于每一组数据,输出Yes或No,回答B君能否走到(n,n)。

样例输入
2

2
1 1
2 2

5
3 3
3 2
3 1
1 2
1 3
1 4
1 5
2 2
样例输出
Yes
Yes
题目分析
本题需要记录走的步数,以及在第多少秒在什么位置放路障,可以使用ar[a][b] = j;非常巧妙地得到在第j秒在(a, b)位置当一个路障。同时在判断能不能走下一步时,需要再加上time[tx][ty]和ar[tx][ty]的比较,最后注意在visit一个位置之后,更新时间数组tim[tx][ty] = tim[sx][sy]+1。

#include <bits/stdc++.h>
#include <queue>
using namespace std;
int m, n;
int s[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};//四个方向
int ar[1010][1010], tim[1010][1010];//ar记录在第多少秒会在(i,就)放路障,tim记录时间(走了多少步)
bool visit[1010][1010];
bool bfs(int sx, int sy) {queue<int> q;memset(visit, 0, sizeof visit);memset(tim, 0, sizeof tim);//初始化数组q.push(sx), q.push(sy);//初始位置入队int tx, ty;//定义下一步位置visit[sx][sy] = 1;//标记已经走过初始位置while (!q.empty()) {//当队列不空的时候sx = q.front();   q.pop();sy = q.front();   q.pop();//sx,sy等于队首元素,队首元素出队for (int k = 0; k < 4; k++) {//遍历四个方向tx = sx + s[k][0];ty = sy + s[k][1];//更新下一步的位置if (tx > 0 && tx <= m && ty > 0 && ty <= n && visit[tx][ty] == 0)continue;//当下一步的位置在范围内而且没有被访问过就继续if ((ar[tx][ty] == 0) || (ar[tx][ty] > tim[tx][ty])) {//如果这个地方不放路障或者放路障的时间大于到达这个位置所用的时间visit[tx][ty] = 1;//走这个位置q.push(tx), q.push(ty);//这个位置入队tim[tx][ty] = tim[sx][sy] + 1;//时间更新,加1if (tx == n && ty == n) {//如果已经到达了终点if ((ar[n][n] == 0) || (ar[n][n] >= tim[n][n]))return 1;//如果(n,n)处不放路障或者在(n,n)处放路障的时间大于走到的时间,返回1else return 0;//否则返回0}}}}return 0;//需要再加一个return 0,意思就是到不了终点,需要返回0
}
int main()
{int k;cin >> k;while (k --) {cin >> n;if (n == 1) {//当他要到的位置是1,1;也就是说不用动,直接输出yescout << "Yes" << endl;return 0;}memset(ar, 0, sizeof ar);//初始化数组arfor(int i = 1; i <= 2 * n - 2; i++) {//将要在第i秒的时候在(a,b)位置上放路障int a, b;cin >> a >> b;//输入位置ar[a][b] = i;}if (bfs(1, 1)) {//从(1,1)开始遍历搜索,如果能到达就输出yescout << "Yes" << endl;}else cout << "No" << endl;//不能到达就输出no}return 0;
}

搜索2(一、马的遍历 二、 求细胞数量 三、01迷宫 四、奇怪的电梯 五、海战 六、路障)相关推荐

  1. java锁一次交互二次握手_Java后台开发面试实战(二):TCP三次握手四次挥手

    感谢牛客网网友提供的面试经验! 1. 解释一下TCP三次握手四次挥手 图片来源于微信公众号:码农求职小助手 答: 嗯(稍作思考)- 三次握手简单来说,在数据传输开始前: 第一次握手:客户端向服务端发送 ...

  2. OpenCV学习笔记(十一)(十二)(十三)(十四)(十五)

    OpenCV学习笔记(十一)--谈谈像素的类型和对Templates的限制使用 Templates是c++的一个很强大的特征,可以是数据结构更加安全高效.但也会增加编译时间和代码的长度,当函数被频繁调 ...

  3. 求细胞数量pascal题解

    这题我是用广度优先搜索来做的 一开始先一个一个点找,如果这个点是细胞,那么就搜索. 注意:可以把数组开大点 const dx:array[1..4]of longint=(0,-1,0,1); dy: ...

  4. [LUOGU]P1451 求细胞数量

    题目描述 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数.(1<=m,n<=100)? 输入输出格式 输 ...

  5. 求细胞数量:一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。

    题目描述 一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数. 输入 第一行两个整数代表矩阵大小 n 和 ...

  6. 华为畅玩5A 移动增强版cam-tl00四步走 一步BL解锁 二步刷recovery 三步root 四步安装框架Xposed

    荣耀5A解bl锁教程 https://cn.club.vmall.com/thread-26655260-1-1.html 荣耀5A 移动/双4G TWRP3.0.2 一键ROOT  https:// ...

  7. 【日常水题-bfs】马的遍历

    这几天日常一搜索qaq P1443 马的遍历 1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 ...

  8. 广度优先搜索(BFS)——马的遍历(洛谷 P1443)

    来看一道经典的搜索问题--马的遍历 大致题目,给定棋盘规模,以及马的初始位置,输出马到棋盘的最短距离,若不能到达则输出-1 很简单的一个搜索问题,用经典算法BFS就可以了,唯一需要注意判断的就是马有8 ...

  9. 马的遍历(棋盘游戏)

    广度优先搜索(Breadth First Search, BFS)类似树的按层次遍历. 原则是:尽可能地先横向搜索:特点是:先访问的顶点其邻接点亦先被访问. ①从顶点v出发,置visited[v]=t ...

最新文章

  1. 洛谷 3519 bzoj 2213 Difference
  2. 我们也可以从学习中获得快乐 ------稻盛和夫
  3. 5.9 程序示例--非线性分类-机器学习笔记-斯坦福吴恩达教授
  4. php四种基础排序算法的运行时间比较
  5. 【数据结构与算法】之深入解析“寻找峰值”的求解思路与算法示例
  6. 大数据_Spark框架_快速上手_word count 案例分析---Spark工作笔记0005
  7. 大学计算机基础试题第一套,大学计算机基础试题及答案(完整版)
  8. oracle12c集群安装—grid安装
  9. tomcat内存溢出的解决方法
  10. linux系统查看usb转串口驱动,Linux下使用USB转串口驱动的方法
  11. c++ 获取外网ip地址
  12. 三星手机开发游戏工具 提升游戏体验
  13. 一文读懂随机森林的解释和实现(附python代码)
  14. python抓包检测入侵_如果你喜欢python爬虫,不妨看看这篇验证码的抓包技巧与识别!...
  15. 《TCPIP网络编程》课后练习答案第一部分1~5章 尹圣雨
  16. 政务行业云平台安全防护建设思路
  17. 图形学笔记(二)——线画图元
  18. oracle练习题-emp表
  19. [译] 用于 iOS 的 ML Kit 教程:识别图像中的文字
  20. 使用 工具john 解密

热门文章

  1. 神级 idea 插件,让你代码飞起来~
  2. web网页设计实例作业 ——自适应绿色茶叶公司(12页) HTML+CSS+JS网页设计期末课程大作业
  3. Java之四大元注解@Target、@Retention、@Documented、@Inherited
  4. 《JVM调优》- Jstack指令详解
  5. 饥荒机器人怎么解锁_饥荒机器人吃不了齿轮怎么办_饥荒机器人解决方法介绍_玩游戏网...
  6. 搞笑类短视频素材怎么找?有哪些好用的网站?
  7. 挂载raw格式镜像方法
  8. Mac已联网,但是WIFI图标一直在闪的解决办法
  9. 做个懂生活的精致女生!
  10. 酷狗小试页面和简写代码