广度优先搜索算法带图详解_不怕困难的博客的博客-CSDN博客
问题 A: 【一本通基础广度优先搜索】 最少步数 [题目描述]在各种棋中,一种棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将更加增加趣味性,因此,他规定马既能按“日”飞,也能各象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就和他玩一种新游戏,在围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A,B两点的坐标,想知道两个位置到(1,1)点的可能最少步数。
输入每行的两个整数,第一行为A点坐标
第二行为B点坐标
(* 注意:棋盘大小规模为100*100以内 *)
输出两行第一行为A点到(1,1)的步数
第二行为B点到(1,1)的步数
样例输入12 16 18 10样例输出
8 9
代码:
#includeusing namespace std; int dx[12] = {-2, -2, -1, 1, 2, 2, 2, 2, 1, -1, -2, -2}; int dy[12] = {-1, -2, -2, -2, -2, -1, 1, 2, 2, 2, 2, 1}; int main() { int s[101][101], que[10000][4] = {0}, x1, x2, y1, y2; memset(s, 0xff, sizeof((s)));//s数组的初始化 int head = 1, tail = 1;//初始位置入队列 que[1][1] = 1; que[1][2] = 1; que[1][3] = 0; cin >> x1 >> y1 >> x2 >> y2;//读入黑马和白马的位置 while(head <= tail)//如果队列为空, 则拓展队首结点 { for(int i = 0; i <= 11; i++)//枚举12个拓展方向 { int x = que[head][1] + dx[i]; int y = que[head][2] + dy[i]; if(x > 0 && y > 0 && x <= 100 && y <= 100) { if(s[x][y] == -1) { s[x][y] = que[head][3] + 1; tail++;//(1, 1)到(x,y)的最小步数入队 que[tail][1] = x; que[tail][2] = y; que[tail][3] = s[x][y]; if(s[x1][y1] > 0 && s[x2][y2] > 0)//输出答案 { cout << s[x1][y1] << endl; cout << s[x2][y2] << endl; return 0; } } } } head++; } return 0; }
问题 B: 【一本通基础广度优先搜索】The Castle
【题目描述】
一座城堡被分成m*n个方块(m≤50,n≤50),每个方块可有0~4堵墙(0表示无墙)。下面示出了建筑平面图:
图中的加粗黑线代表墙。几个连通的方块组成房间,房间与房间之间一定是用黑线(墙)隔开的。
现在要求你编一个程序,解决以下2个问题:
1、该城堡中有多少个房间?
2、最大的房间有多大?
【输入】
平面图用一个数字表示一个方块(第1个房间用二进制1011表示,0表示无东墙,用十进制11表示)。
第一行一个整数m(m≤50),表示房子南北方向的长度。
第二行一个整数n(n≤50),表示房子东西方向的长度。
后面的m行,每行有n个整数,每个整数都表示平面图对应位置的方块的特征。每个方块中墙的特征由数字P来描述(0≤P≤15)。数字P是下面的可能取的数字之和:
1(西墙 west)
2(北墙 north)
4(东墙 east)
8(南墙 south)
室内的墙被定义两次: 例如方块(1,1)中的南墙也被位于其南面的方块(2,1)定义了一次。
建筑中至少有两个房间。
【输出】
第1行:一个整数,表示房间总数;
第2行:一个整数,表示最大房间的面积(方块数)。
【输入样例】
4
7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
【输出样例】
5
9
5 9
#include问题 C: 【一本通基础广度优先搜索】Lake Counting 数池塘 [题目描述]using namespace std; int dx[4] = {-1, 1, 0, 0}; int dy[4] = {0, 0, -1, 1}; int a[51][51][4], q[5001][3]; int tot, i, j, p, n, m, maxx = -1; bool b[51][51]; void bfs(int x, int y) { memset(q, 0, sizeof(q)); tot++; int head = 0, tail = 1, xx, yy; q[1][1] = x; q[1][2] = y; b[x][y] = false; int cnt = 1; while(head < tail) { head++; for(int i = 0; i <= 3; i++) { xx = q[head][1] + dx[i]; yy = q[head][2] + dy[i]; if((xx > 0) && (xx <= m) && (yy > 0) && (yy <= n) && (b[xx][yy]) && a[q[head][1]][q[head][2]][i] == 0) { tail++; cnt++; b[xx][yy] = false; q[tail][1] = xx; q[tail][2] = yy; } } } maxx = max(cnt, maxx); } int main() { memset(b, true, sizeof(b)); scanf("%d %d", &m, &n); for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &p); if(p >= 8) { p -= 8; a[i][j][1] = 1; } if(p >= 4) { p -= 4; a[i][j][3] = 1; } if(p >= 2) { p -= 2; a[i][j][0] = 1; } if(p >= 1) { p -= 1; a[i][j][2] = 1; } } } for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(b[i][j]) { bfs(i, j); } } } printf("%dn%dn", tot, maxx); return 0; }
农夫约翰的农场可以表示成N×M(1≤N,M≤100)个方格组成的矩形.由于近日的降雨,
在约翰农场上的不同地方形成了池塘.每一个方格或者有积水(’W’)或者没有积水(’.’).农夫约翰打算数出他的农场上共形成了多少池塘.一个池塘是一系列相连的有积水的方格,每一个方格周围的八个方格都被认为是与这个方格相连的.
现给出约翰农场的图样,要求输出农场上的池塘数.
输入第1行:由空格隔开的两个整数N和M.
第2到N+1行:每行M个字符代表约翰农场的一排方格的状态.每个字符或者是’W’或者
是’.’,字符之间没有空格.
输出约翰农场上的池塘数.
样例输入10 12 W ........ WW. . WWW ..... WWW .... WW ... WW. ......... WW. ......... W.. ..W ...... W.. .W.W ..... WW. W.W.W ..... W. .W.W ...... W. ..W ....... W.样例输出
3
#include问题 D: 【一本通基础广度优先搜索】走迷宫 [题目描述]using namespace std; int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1}; int n, m; int ans = 0; int h[10001][3]; char map1[101][101]; void js(int p, int q) { memset(h, 0, sizeof(h)); int x, y, head = 0, tail = 1; ans++; h[1][1] = p; h[1][2] = q; map1[p][q] = '.'; do { head++; for(int i = 0; i < 8; i++) { x = h[head][1] + dx[i]; y = h[head][2] + dy[i]; if(x > 0 && x <= n && y > 0 && y <= m && map1[x][y] == 'W') { map1[x][y] = '.'; tail++; h[tail][1] = x; h[tail][2] = y; } } }while(head < tail); } int main() { cin >> n >> m; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { cin >> map1[i][j]; } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(map1[i][j] == 'W') { js(i, j); } } } cout << ans << endl; return 0; }
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入第一行是两个整数,R和C,代表迷宫的长和宽。( 1≤ R,C ≤ 40)
接下来是R行,每行C个字符,代表整个迷宫。
空地格子用‘.’表示,有障碍物的格子用‘#’表示。
迷宫左上角和右下角都是‘.’。
输出输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。
样例输入5 5 ..### #.... #.#.# #.#.# #.#..样例输出
9
#include问题 E: 【一本通基础广度优先搜索】走出迷宫 [题目描述]using namespace std; int xx[4] = {-1, 1, 0, 0}; int yy[4] = {0, 0, -1, 1}; int h[1001][5]; bool a[41][41]; int r, c, x, y; char k; int head, tail, i; int main() { cin >> r >> c; for(int i = 1; i <= r; i++) { for(int j = 1; j <= c; j++) { cin >> k; if(k == '.') a[i][j] = true; else a[i][j] = false; } } // for(int i = 1; i <= r; i++) // { // for(int j = 1; j <= c; j++) // cout << a[i][j] << " "; // cout << endl; // } head = 0; tail = 1; h[1][1] = 1; h[1][2] = 1; h[1][3] = 1; while(head < tail) { head++; for(int i = 0; i < 4; i++) { x = h[head][1] + xx[i]; y = h[head][2] + yy[i]; if((x > 0) && (x <= r) && (y > 0) && (y <= c) && (a[x][y] == true)) { tail++; h[tail][1] = x; h[tail][2] = y; h[tail][3] = h[head][3] + 1; a[x][y] = false; if(x == r && y == c) { cout << h[tail][3] << endl; return 0; } } } } return 0; }
当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。
假设你已经得到了一个n*m的迷宫的图纸,请你找出从起点到出口的最短路。
输入第一行是两个整数n和m(1≤n,m≤100),表示迷宫的行数和列数。
接下来n行,每行一个长为m的字符串,表示整个迷宫的布局。字符‘.’表示空地,‘#’表示墙,‘S’表示起点,‘T’表示出口。
输出输出从起点到出口最少需要走的步数。
样例输入3 3 S#T .#. ...样例输出
6
#includeusing namespace std; int h[1004][4]; int xx[4] = {-1, 1, 0, 0}, yy[4] = {0, 0, -1, 1}; bool a[101][101]; int main() { int n, m, fx, fy, x, y, t, w; char c; memset(a, true, sizeof(a)); cin >> n >> m; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { cin >> c; if(c == 'S') { h[1][1] = i; h[1][2] = j; h[1][3] = 0; a[i][j] = false; } else if(c == 'T') { fx = i; fy = j; } else if(c == '#') a[i][j] = false; } } t = 0, w = 1; do { t++; for(int i = 0; i < 4; i++) { x = h[t][1] + xx[i]; y = h[t][2] + yy[i]; if(x > 0 && x <= n && y > 0 && y <= m &&a[x][y]) { a[x][y] = false; w++; h[w][1] = x; h[w][2] = y; h[w][3] = h[t][3] + 1; if(x == fx && y == fy) { cout << h[w][3] << endl; return 0; } } } }while(t < w); }



