题目:https://www.luogu.org/problemnew/show/P1443
简单的BFS模板题——因为我写出来了。
分析过程:
n*m矩阵,用二维数组
数据不大,二维数组稳了
先把二维数组初始化为-1,马的坐标,即起点的坐标再设为0
接着开始遍历——8个方向(下过中国象棋的大牛应该不陌生)
设一个结构,储存落点的位置与所走的步数,每走一次就记录一次
此时,还要判断落点是否还是-1,这样就可以避免重复
本来这样就可以AC了,但此题有个陷阱就是:
输出格式:
一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)
所以,要在输出上花点心思......(其实是要注意审题)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #define MAXN 402 6 using namespace std; 7 8 int ans[MAXN][MAXN]; 9 int n, m, n_b, m_b; 10 int run_x[] = { 1, 1, 2, 2, -1, -1, -2, -2 }; 11 int run_y[] = { 2, -2, 1, -1, 2, -2, 1, -1 }; 12 13 struct node{ 14 int x, y; 15 int step; 16 }; 17 18 queue<node> q; 19 20 void bfs(){ 21 node a; 22 a.x = n_b; 23 a.y = m_b; 24 a.step = 0; 25 ans[a.x][a.y] = a.step; 26 q.push(a); 27 28 while(!q.empty()){ 29 node b = q.front(); 30 node c; 31 q.pop(); 32 for(int i = 0; i < 8; i++){ 33 c.x = b.x + run_x[i]; 34 c.y = b.y + run_y[i]; 35 if(0 < c.x && c.x <= n && 0 < c.y && c.y <= m 36 && ans[c.x][c.y] == -1){ 37 c.step = b.step + 1; 38 ans[c.x][c.y] = c.step; 39 q.push(c); 40 } 41 } 42 } 43 } 44 45 int main() 46 { 47 while(cin >> n >> m >> n_b >> m_b){ 48 memset(ans, -1, sizeof(ans)); 49 bfs(); 50 for(int i = 1; i <= n; i++){ 51 for(int j = 1; j <= m; j++){ 52 printf("%-5d", ans[i][j]); 53 } 54 cout << endl; 55 } 56 } 57 return 0; 58 }
下面说说我对BFS的理解
BFS与DFS有个很相似的地方:对于所有情况,它们都做着相同的行为来遍历完所有情况。
所以,BFS里肯定有一个“核心循环”(这里指对于每个方法路径的遍历),然后再判断下一位置是否还满足条件。
如:
for(int i = 0; i < 8; i++){ c.x = b.x + run_x[i]; c.y = b.y + run_y[i]; if(0 < c.x && c.x <= n && 0 < c.y && c.y <= m
&& ans[c.x][c.y] == -1){ c.step = b.step + 1; ans[c.x][c.y] = c.step; q.push(c); } }
这里的循环是对马的8个方向的遍历,接着if语句是判断马跳下一步后是否还在棋盘上或者是否已经来过。
虽然我做过的题不多,但做过的题都有这种“核心循环”,所以就特意画出来做了个笔记。
嘻嘻,说了这么多好像还云里雾里的感觉。
不知是不是,感觉学习算法还是要抓住那类算法的特性去理解,这样学起来就会更轻松。
有点理解师兄所说的:只要思维理解了,代码的实现就不是问题了。