[关闭]
@sensitive-cs 2017-03-11T03:11:11.000000Z 字数 12302 阅读 843

[kuangbin带我飞]专题一 简单搜索

题解


poj1321 棋盘问题
题意:
给你一个棋盘,n*n,k个棋子,其中,棋子放置的时候不能在同一列或者同一排,问有多少种方案可以放置这k个棋子。
思路:
dfs,搜索与回溯,这题我做的时候忽略了一个地方,就是一行不放棋子都可以的,并不是每一行都要放棋子,以后要注意类似的问题。
代码(看注释的地方:

  1. #include <stdio.h>
  2. #include <string.h>
  3. char mp[10][10];
  4. int mmp[10][10];
  5. int ans = 0;
  6. int n,k;
  7. bool judge(int x,int y)
  8. {
  9. for (int i = 0;i < n;i++)
  10. if (mmp[i][y] == 1)
  11. return true;
  12. return false;
  13. }
  14. void dfs(int l,int num)
  15. {
  16. if (num == k)
  17. {
  18. ans++;
  19. return;
  20. }
  21. if (l >= n) return;
  22. for (int i = 0;i < n;i++)
  23. {
  24. if(mp[l][i] == '#')
  25. {
  26. if (!judge(l,i))
  27. {
  28. mmp[l][i] = 1;
  29. dfs(l+1,num+1);
  30. mmp[l][i] = 0;
  31. }
  32. }
  33. }
  34. dfs(l+1,num);//不放棋子也可以,注意!!!
  35. return;
  36. }
  37. int main()
  38. {
  39. while (scanf("%d%d",&n,&k) != EOF)
  40. {
  41. memset(mp,0,sizeof(mp));
  42. memset(mmp,0,sizeof(mmp));
  43. if (n == -1 && k == -1) break;
  44. for (int i = 0;i < n;i++)
  45. scanf(" %s",mp[i]);
  46. ans = 0;
  47. if (k == 1)
  48. {
  49. for (int i = 0;i < n;i++)
  50. for (int j = 0;j < n;j++)
  51. if (mp[i][j] == '#') ans++;
  52. }
  53. else
  54. dfs(0,0);
  55. printf("%d\n",ans);
  56. }
  57. return 0;
  58. }

poj2251 degon master
题意:
给出一个三维的迷宫,人可以走空房子,问有无可能走出,如果有,输出最短时间。
思路:
广度优先搜索,无fuck可说。
注意:
有很多地方未思考到。比如0 0 0的退出条件。还有就是判断可走的点时,忘记了坐标的限制,还有就是可行的点的判断应该是!#,我却直接写成了=='.',太不应该了。仔细审题,在写程序之前最好思考一下如何减少bug。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. const int inf = 1000000000;
  6. char maze[35][35][35];
  7. int dis[35][35][35];
  8. int dx[6] = {0,1,0,-1,0,0};
  9. int dy[6] = {1,0,-1,0,0,0};
  10. int dz[6] = {0,0,0,0,1,-1};
  11. struct cor
  12. {
  13. int x,y,z;
  14. };
  15. typedef cor mp;
  16. queue<mp> mmp;
  17. int main()
  18. {
  19. int l,r,c;
  20. while (scanf("%d%d%d",&l,&r,&c) != EOF)
  21. {
  22. if (l == 0 && r == 0 && c == 0) break;
  23. memset(maze,0,sizeof(maze));
  24. while (mmp.size()) mmp.pop();
  25. int si,sj,sk,ei,ej,ek;
  26. for (int i = 0;i < 35;i++)
  27. for (int j = 0;j < 35;j++)
  28. for (int k = 0;k < 35;k++)
  29. dis[i][j][k] = inf;
  30. for (int i = 0;i < l;i++)
  31. for (int j = 0;j < r;j++)
  32. scanf(" %s",maze[i][j]);
  33. for (int i = 0;i < l;i++)
  34. for (int j = 0;j < r;j++)
  35. for (int k = 0;k < c;k++)
  36. {
  37. if (maze[i][j][k] == 'S')
  38. {
  39. si = i;sj = j;sk = k;
  40. }
  41. if (maze[i][j][k] == 'E')
  42. {
  43. ei = i;ej = j;ek = k;
  44. }
  45. }
  46. dis[si][sj][sk] = 0;
  47. mp sta;
  48. sta.x = si;sta.y = sj;sta.z = sk;
  49. mmp.push(sta);
  50. while (mmp.size())
  51. {
  52. mp t = mmp.front();
  53. mmp.pop();
  54. int a = t.x,b = t.y,p = t.z;
  55. if (a == ei && b == ej && p == ek) break;
  56. for (int i = 0;i < 6;i++)
  57. {
  58. int a1 = a+dx[i],b1 = b+dy[i],c1 = p+dz[i];
  59. if (a1 >= l || a1 < 0 || b1 >= r || b1 < 0 || c1 >= c || c1 < 0) continue;
  60. if (dis[a1][b1][c1] == inf && maze[a1][b1][c1] != '#')
  61. {
  62. dis[a1][b1][c1] = dis[a][b][p] + 1;
  63. mp tt;
  64. tt.x = a1,tt.y = b1,tt.z = c1;
  65. mmp.push(tt);
  66. }
  67. }
  68. }
  69. if (dis[ei][ej][ek] == inf)
  70. printf("Trapped!\n");
  71. else
  72. printf("Escaped in %d minute(s).\n",dis[ei][ej][ek]);
  73. }
  74. return 0;
  75. }

poj3278 catch tha cow
题意:
在一条坐标轴上,农夫在n点,羊在k点,羊不动,农夫每次花一分钟可以移动到n+1,n-1,2*n,问农夫到羊的位置,所花最短的时间。
思路:
宽搜。注意当vis[k] != inf,并且vis[t]+1 < vis[k]也是有可能的,因为走得路线可能重复。注意审题!!!!
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. int vis[100005];
  6. const int inf = 100000000;
  7. int ti = 0;
  8. int main()
  9. {
  10. int n,k;
  11. scanf("%d%d",&n,&k);
  12. for (int i = 0;i < 100005;i++) vis[i] = inf;
  13. vis[n] = 0;
  14. queue<int> s;
  15. s.push(n);
  16. if (n == k) printf("0\n");
  17. else
  18. {
  19. while (s.size())
  20. {
  21. int t = s.front();
  22. s.pop();
  23. if (t == k) break;
  24. int x = t * 2,y = t-1,z = t+1;
  25. if (x >= 0 && x <= 100000&&vis[x] == inf ) {vis[x] = vis[t] + 1;s.push(x);}
  26. else if (x >= 0 && x <= 100000 &&vis[x] != inf && vis[t]+1 < vis[x]) {vis[x] = vis[t]+1;s.push(x);}
  27. if (y >= 0 && y <= 100000 &&vis[y] == inf ) {vis[y] = vis[t] + 1;s.push(y);}
  28. else if (y >= 0 && y <= 100000 && vis[y] != inf && vis[t]+1 < vis[y]) {vis[y] = vis[t]+1;s.push(y);}
  29. if (z >= 0 && z <= 100000 && vis[z] == inf) {vis[z] = vis[t]+1;s.push(z);}
  30. else if (z >= 0 && z <= 100000 && vis[z] != inf && vis[t]+1 < vis[z]) {vis[z] = vis[t]+1;s.push(z);}
  31. }
  32. printf("%d\n",vis[k]);
  33. }
  34. return 0;
  35. }

poj3984:迷宫问题
题意:
中文题。
思路:
宽搜。用类似于指针的方法,记录当前节点的每一个前节点,用到了map,因为除了开始节点的每一个节点,只可能有一个father。最后用栈将坐标倒一下。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <map>
  4. #include <queue>
  5. #include <stack>
  6. using namespace std;
  7. typedef pair<int,int> p;
  8. map<p,p> mmp;
  9. queue<p> ro;
  10. stack<p> out;
  11. int dx[4] = {0,1,0,-1};
  12. int dy[4] = {-1,0,1,0};
  13. int mp[5][5];
  14. bool vis[5][5];
  15. int main()
  16. {
  17. for (int i = 0;i < 5;i++)
  18. for (int j = 0;j < 5;j++)
  19. scanf("%d",&mp[i][j]);
  20. vis[0][0] = 1;
  21. ro.push(p(0,0));
  22. while (ro.size())
  23. {
  24. p t = ro.front();
  25. ro.pop();
  26. if (t.first == 4 && t.second == 4) break;
  27. for (int i = 0;i < 4;i++)
  28. {
  29. int x = t.first + dx[i],y = t.second + dy[i];
  30. if (x >= 0 && x < 5 && y >= 0 && y < 5 && !vis[x][y] && mp[x][y] == 0)
  31. {
  32. vis[x][y] = 1;
  33. mmp[p(x,y)] = p(t.first,t.second);
  34. ro.push(p(x,y));
  35. }
  36. }
  37. }
  38. int x = 4,y = 4;
  39. out.push(p(x,y));
  40. while (1)
  41. {
  42. int tx = x,ty = y;
  43. x = mmp[p(tx,ty)].first;
  44. y = mmp[p(tx,ty)].second;
  45. out.push(p(x,y));
  46. if (x == 0 && y == 0) break;
  47. }
  48. while (out.size())
  49. {
  50. p tc = out.top();
  51. out.pop();
  52. printf("(%d, %d)\n",tc.first,tc.second);
  53. }
  54. return 0;
  55. }

hdu2612:find a way
题意:
有两人要在肯德基相遇,kfc有很多家,问两人到达同一家kfc所需的最少时间。
思路:
宽搜。开始是找出每一个肯德基,然后每一个肯德基进行宽搜,结果t了还是rt了。后来去看了题解,直接对两个人的家进行bfs就行了,开始没想到,后来就想通了,还是题做得太少啊。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. int n,m;
  6. int dx[4] = {0,-1,1,0};
  7. int dy[4] = {1,0,0,-1};
  8. char mp[205][205];
  9. int dist1[205][205];
  10. int dist2[205][205];
  11. typedef pair<int,int> p;
  12. queue<p> mmp;
  13. void bfs1(int sx,int sy)
  14. {
  15. dist1[sx][sy] = 0;
  16. mmp.push(p(sx,sy));
  17. while (mmp.size())
  18. {
  19. p t = mmp.front();
  20. mmp.pop();
  21. int tx = t.first,ty = t.second;
  22. for (int i = 0;i < 4;i++)
  23. {
  24. int x = tx + dx[i],y = ty + dy[i];
  25. if (x >= 0 && x < n && y >= 0 && y < m && dist1[x][y] == -1 && mp[x][y] != '#')
  26. {
  27. dist1[x][y] = dist1[tx][ty] + 11;
  28. mmp.push(p(x,y));
  29. }
  30. }
  31. }
  32. }
  33. void bfs2(int sx,int sy)
  34. {
  35. dist2[sx][sy] = 0;
  36. mmp.push(p(sx,sy));
  37. while (mmp.size())
  38. {
  39. p t = mmp.front();
  40. mmp.pop();
  41. int tx = t.first,ty = t.second;
  42. for (int i = 0;i < 4;i++)
  43. {
  44. int x = tx + dx[i],y = ty + dy[i];
  45. if (x >= 0 && x < n && y >= 0 && y < m && dist2[x][y] == -1 && mp[x][y] != '#')
  46. {
  47. dist2[x][y] = dist2[tx][ty] + 11;
  48. mmp.push(p(x,y));
  49. }
  50. }
  51. }
  52. }
  53. int main()
  54. {
  55. while (scanf("%d%d",&n,&m) != EOF)
  56. {
  57. memset(mp,0,sizeof(mp));
  58. memset(dist1,-1,sizeof(dist1));
  59. memset(dist2,-1,sizeof(dist2));
  60. for (int i = 0;i < n;i++)
  61. scanf("%s",mp[i]);
  62. int yx,yy,mx,my;
  63. for (int i = 0;i < n;i++)
  64. for (int j = 0;j < m;j++)
  65. {
  66. if (mp[i][j] == 'Y')
  67. {
  68. yx = i;yy = j;
  69. }
  70. if (mp[i][j] == 'M')
  71. {
  72. mx = i;my = j;
  73. }
  74. }
  75. while (mmp.size()) mmp.pop();
  76. bfs1(yx,yy);
  77. while (mmp.size()) mmp.pop();
  78. bfs2(mx,my);
  79. int ans = 1000000000;
  80. for (int i = 0;i < n;i++)
  81. for (int j = 0;j < m;j++)
  82. {
  83. if (mp[i][j] == '@')
  84. {
  85. if (dist1[i][j] != -1 && dist2[i][j] != -1)
  86. {
  87. int k = dist1[i][j] + dist2[i][j];
  88. if (k < ans) ans = k;
  89. }
  90. }
  91. }
  92. printf("%d\n",ans);
  93. }
  94. return 0;
  95. }

hdu1241 oil deposits
题意:
找出图中所有的八连块。
思路:
深搜,将所有的与@相连的全部变成*,包括自己,计算一共dfs了几次。
坑:输入用%c,不要用%s,不知道怎么就有问题了QAQ。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. char mp[120][120];
  4. int m,n;
  5. int dx[8] = {0,1,0,-1,1,-1,1,-1};
  6. int dy[8] = {1,0,-1,0,-1,1,1,-1};
  7. void dfs(int x,int y)
  8. {
  9. mp[x][y] = '*';
  10. for (int i = 0;i < 8;i++)
  11. {
  12. int tx = x + dx[i],ty = y + dy[i];
  13. if (tx >= 1 && tx <= m && ty >= 1 && ty <= n && mp[tx][ty] == '@')
  14. dfs(tx,ty);
  15. }
  16. return;
  17. }
  18. int main()
  19. {
  20. while (scanf("%d%d",&m,&n) != EOF)
  21. {
  22. memset(mp,0,sizeof(mp));
  23. if (m == 0 && n == 0) break;
  24. for (int i = 1;i <= m;i++)
  25. for (int j = 1;j <= n;j++)
  26. scanf(" %c",&mp[i][j]);
  27. int ans = 0;
  28. for (int i = 1;i <= m;i++)
  29. for (int j = 1;j <= n;j++)
  30. {
  31. if (mp[i][j] == '@')
  32. {
  33. ans++;
  34. dfs(i,j);
  35. }
  36. }
  37. /*for (int i = 1;i <= m;i++)
  38. for (int j = 1;j <= n;j++)
  39. printf("%c\n",mp[i][j]);*/
  40. printf("%d\n",ans);
  41. }
  42. return 0;
  43. }

poj1426 find the multiple
题意:
给出一个数,找出一个数,满足是这个数的倍数,且所有的数位要么是1,要么是0。
思路:
一开始以为要用数组构造,高精度进行计算,这就触及到我知识的盲区了。搜了一下题解,原来unsighed long long也可以存下。
所以后面一通乱搞,将最早得出的答案记录下来就返回。看代码。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int n;
  4. int ans = 0;
  5. unsigned long long res = 0;
  6. void dfs(unsigned long long k,int num)
  7. {
  8. if (num >= 19) return;
  9. if (k % n == 0)
  10. {
  11. res = k;
  12. ans = 1;
  13. return;
  14. }
  15. if (ans == 1) return;
  16. dfs(k*10,num+1);dfs(k*10 + 1,num+1);
  17. }
  18. int main()
  19. {
  20. while (scanf("%d",&n) != EOF && n)
  21. {
  22. ans = 0;
  23. dfs(1,0);
  24. printf("%I64d\n",res);
  25. }
  26. return 0;
  27. }

poj3126 prime path
题意:
找到一个质数改变为另一个质数所需的最小步数。改变的规则是变为另一个只有一位数字与原数字不同的质数。
思路:
首先利用埃氏筛筛出质数,然后宽搜,不过其中判断显得有点麻烦。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. int a[10005];
  6. typedef pair<int,int> p;
  7. p c[10005];
  8. int main()
  9. {
  10. int t;
  11. scanf("%d",&t);
  12. while (t--)
  13. {
  14. int m,n;
  15. scanf("%d%d",&m,&n);
  16. memset(a,-1,sizeof(a));
  17. memset(c,0,sizeof(c));
  18. a[0] = a[1] = 0;
  19. for (int i = 2;i <= 10000;i++)
  20. if (a[i] == -1)
  21. {
  22. for (int j = 2*i;j <= 10000;j += i) a[j] = 0;
  23. }
  24. int sum = 0;
  25. for (int i = 1000;i < 10000;i++)
  26. if (a[i] == -1)
  27. {
  28. c[sum].first = i;
  29. c[sum].second = 0;
  30. sum++;
  31. }
  32. queue<p> mmp;
  33. mmp.push(p(m,0));
  34. a[m] = 0;
  35. while (mmp.size())
  36. {
  37. p tt = mmp.front();
  38. mmp.pop();
  39. if (tt.first == n) break;
  40. int key = tt.first;
  41. for (int i = 0;i < sum;i++)
  42. {
  43. int tx = c[i].first;
  44. if (a[tx] == 0) continue;
  45. int aa = key / 1000,bb = key % 1000 / 100,cc = key % 100 / 10,dd = key % 10;
  46. int ee = tx / 1000,ff = tx % 1000 / 100,gg = tx % 100 / 10,hh = tx % 10;
  47. int same = 0;
  48. if (aa == ee) same++;
  49. if (bb == ff) same++;
  50. if (cc == gg) same++;
  51. if (dd == hh) same++;
  52. if (same == 3 && a[tx] == -1)
  53. {
  54. a[tx] = 0;
  55. c[i].second = tt.second + 1;
  56. mmp.push(p(tx,c[i].second));
  57. }
  58. }
  59. }
  60. for (int i = 0;i < sum;i++)
  61. if (c[i].first == n)
  62. {
  63. printf("%d\n",c[i].second);
  64. break;
  65. }
  66. }
  67. return 0;
  68. }

fzu2150 fire game
题意:
有一块田,田里要么是草,要么是空的,现在有两个人,他们想玩游戏(2333玄学游戏,就必须把田里的草烧光,两个人放火选的位置是随机的,问他们是否能玩游戏,可以就输出最短时间。
思路:
开始想的是dfs,死活想不通,以为是随机选取两片草地,同时dfs,但是这样子我就不知道怎么操作了。。。后来看了题解,原来是bfs,只是把每两个格子的组合提出来,两个起点的bfs,队列为空时,记录时间。
囧:又忘记初始化vis数组,卡了10分钟,记住记住记住!!!!
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. struct node
  6. {
  7. int x,y;
  8. int t;
  9. };
  10. typedef struct node node;
  11. typedef pair<int,int> p;
  12. p mp[105];
  13. char a[15][15];
  14. bool vis[15][15];
  15. int dx[4] = {0,1,0,-1};
  16. int dy[4] = {-1,0,1,0};
  17. int main()
  18. {
  19. int t;
  20. int cas = 1;
  21. scanf("%d",&t);
  22. while (t--)
  23. {
  24. memset(a,0,sizeof(a));
  25. memset(mp,0,sizeof(mp));
  26. memset(vis,0,sizeof(vis));
  27. int n,m;
  28. scanf("%d%d",&n,&m);
  29. for (int i = 0;i < n;i++)
  30. for (int j = 0;j < m;j++)
  31. scanf(" %c",&a[i][j]);
  32. printf("Case %d: ",cas++);
  33. int sum = 0;
  34. for (int i = 0;i < n;i++)
  35. for (int j = 0;j < m;j++)
  36. if (a[i][j] == '#')
  37. {
  38. mp[sum].first = i;
  39. mp[sum].second = j;
  40. sum++;
  41. }
  42. if (sum == 1)
  43. {
  44. printf("0\n");
  45. continue;
  46. }
  47. int ans = 1000000;
  48. int res;
  49. for (int i = 0;i < sum;i++)
  50. for (int j = i+1;j < sum;j++)
  51. {
  52. memset(vis,0,sizeof(vis));
  53. int number = 2;
  54. node s1,s2;
  55. s1.t = 0,s1.x = mp[i].first,s1.y = mp[i].second;
  56. s2.t = 0,s2.x = mp[j].first,s2.y = mp[j].second;
  57. vis[s1.x][s1.y] = 1;
  58. vis[s2.x][s2.y] = 1;
  59. queue<node> mmp;
  60. mmp.push(s1);mmp.push(s2);
  61. while (mmp.size())
  62. {
  63. node tt = mmp.front();
  64. mmp.pop();
  65. for (int k = 0;k < 4;k++)
  66. {
  67. int tx = tt.x + dx[k],ty = tt.y + dy[k];
  68. if (tx >= 0 && tx < n && ty >= 0 && ty < m && !vis[tx][ty] && a[tx][ty] == '#')
  69. {
  70. vis[tx][ty] = 1;
  71. node pp;
  72. pp.t = tt.t + 1,pp.x = tx,pp.y = ty;
  73. number++;
  74. mmp.push(pp);
  75. }
  76. }
  77. if (!mmp.size())
  78. {
  79. res = tt.t;
  80. }
  81. }
  82. if (number < sum) continue;
  83. else
  84. {
  85. if (res < ans) ans = res;
  86. }
  87. }
  88. if (ans == 1000000)
  89. printf("-1\n");
  90. else
  91. printf("%d\n",ans);
  92. }
  93. return 0;
  94. }

poj3279 fliptile
题意:
有一个n*m的棋盘,上面放有白色的棋子和黑色的棋子,棋子有两面,白色为1,黑色为0,现在,要想办法把整个棋盘变成黑色的,问是否可能以及最少的步数,如果有最少步数相同的翻法,那么就输出字典序最小的翻法。翻棋子的时候,以当前翻的棋子为中心的棋子周围的棋子都会被翻,相当于5连块。
思路:
想了很久,都不知道,于是去看了题解。
第一个没想通的点是,怎样决定从哪里开始翻,原来是第一行的颜色确定了,那么整个棋盘的颜色也就确定了。因为每次决定是否翻一个棋子的时候,是由它上面的棋子是否为白色决定的,当我们翻完最后一行时,前面的所有行都是黑色的,我们只需检查最后一行是否全黑就行了。所以只需列举第一行的所有反转情况。
第二个,是学到了关于用位操作模拟路径压缩的问题。这个题,我们一共有m列,那么第一行的反转情况一共有2^m次方种,用<<比pow要快,而且很方便。我们通过左移操作来模拟第一行是否反转的情况,比如,当m为4的时候,第一行可以有0001,0010,0100,1000,0011,0111等16种不同的情况,我们1来表示反转,用0表示不反转,这样的话就很方便了。那么,我们如何考察哪一位为1呢,同样很方便。再次运用为操作,比如当m为4的时候,我们用0001,0010,0100,1000去与我们所列举的第一行的情况i进行与运算,则为真的位,就是1。比如当i为5,即0101的时候,我们通过与运算就可以知道第二个棋子和第四个棋子是要反转的。Got it?
如何记录字典序呢,只需要把步数最小(是<哦,不是<=)的时候,把相应的i,即第一行的反转操作记录下来,那么最后在进行一次i的反转就可以了。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int mp[20][20];
  4. int t[20][20],f[20][20];
  5. int m,n;
  6. int res;
  7. int dx[4] = {0,1,0,-1};
  8. int dy[4] = {1,0,-1,0};
  9. void flip(int x,int y)
  10. {
  11. res++;f[x][y] = 1;
  12. t[x][y] = !t[x][y];
  13. for (int i = 0;i < 4;i++)
  14. {
  15. int tx = x + dx[i],ty = y + dy[i];
  16. if (tx >= 0 && tx < m && ty >= 0 && ty < n) t[tx][ty] ^= 1;
  17. }
  18. }
  19. bool ok(int k)
  20. {
  21. res = 0;
  22. memcpy(t,mp,sizeof(mp));
  23. memset(f,0,sizeof(f));
  24. for (int i = 0;i < m;i++)
  25. {
  26. if (k & (1 << (m-i-1)))
  27. flip(0,i);
  28. }
  29. for (int i = 1;i < m;i++)
  30. for (int j = 0;j < n;j++)
  31. if (t[i-1][j]) flip(i,j);
  32. for (int i = 0;i < n;i++)
  33. if (t[m-1][i]) return false;
  34. return true;
  35. }
  36. int main()
  37. {
  38. while (scanf("%d%d",&m,&n) != EOF)
  39. {
  40. memset(f,0,sizeof(0));
  41. memset(mp,0,sizeof(0));
  42. memset(t,0,sizeof(0));
  43. for (int i = 0;i < m;i++)
  44. for (int j = 0;j < n;j++)
  45. scanf("%d",&mp[i][j]);
  46. int ans = 100000,p = -1;
  47. for (int i = 0;i < (2 << m);i++)
  48. {
  49. if (ok(i) && res < ans)
  50. {
  51. ans = res,p = i;
  52. }
  53. }
  54. if (p != -1)
  55. {
  56. ok(p);
  57. for (int i = 0;i < m;i++)
  58. {
  59. for (int j = 0;j < n;j++)
  60. {
  61. if (!j) printf("%d",f[i][j]);
  62. else printf(" %d",f[i][j]);
  63. }
  64. printf("\n");
  65. }
  66. }
  67. else
  68. {
  69. printf("IMPOSSIBLE\n");
  70. }
  71. }
  72. return 0;
  73. }

uva11624:fire
题意:
给出一个n*m的格子,里面有墙,有人(只有一个),有fire(可能有很多个),有可走的道路。人只要能在火烧到之前到达任意边界就可以逃出,问人是否能逃出以及所用的最少时间。
思路:
两次dfs,第一次记录火到达所有点的最少时间。第二次搜索人是否能在火到达之前达到边界。
坑:
判断边界的时候,假如输入是n排m列,那么就是x小于n,y小于m,结果我把它当成数学里面的坐标来想去了。。。23wa,想吐血啊,记住教训,保险起见,画图吧!
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <queue>
  4. using namespace std;
  5. const int maxn = 1010;
  6. int a[maxn][maxn];
  7. int b[maxn][maxn];
  8. char mp[maxn][maxn];
  9. int dx[4] = {0,1,0,-1};
  10. int dy[4] = {-1,0,1,0};
  11. typedef pair<int,int> p;
  12. queue<p> mmp;
  13. int m,n;
  14. void bfs1(void)
  15. {
  16. while (mmp.size()) mmp.pop();
  17. for (int i = 0;i < n;i++)
  18. for (int j = 0;j < m;j++)
  19. {
  20. if (mp[i][j] == 'F')
  21. {
  22. a[i][j] = 0;
  23. mmp.push(p(i,j));
  24. }
  25. }
  26. while (mmp.size())
  27. {
  28. p ss = mmp.front();
  29. mmp.pop();
  30. int x = ss.first,y = ss.second;
  31. for (int i = 0;i < 4;i++)
  32. {
  33. int nx = x + dx[i],ny = y + dy[i];
  34. if (nx <0 || nx >= n) continue;
  35. if (ny <0 || ny >= m) continue;
  36. if (mp[nx][ny] == '#') continue;
  37. if (a[nx][ny] != -1) continue;
  38. a[nx][ny] = a[x][y] + 1;
  39. mmp.push(p(nx,ny));
  40. }
  41. }
  42. return;
  43. }
  44. int bfs2(void)
  45. {
  46. while (mmp.size()) mmp.pop();
  47. for (int i = 0;i < n;i++)
  48. for (int j = 0;j < m;j++)
  49. {
  50. if (mp[i][j] == 'J')
  51. {
  52. mmp.push(p(i,j));
  53. b[i][j] = 0;
  54. }
  55. }
  56. while (mmp.size())
  57. {
  58. p ss = mmp.front();
  59. mmp.pop();
  60. int x = ss.first,y = ss.second;
  61. if (x == 0 || x == n-1 || y == 0 || y == m-1)
  62. {
  63. return b[x][y] + 1;
  64. }
  65. for (int i = 0;i < 4;i++)
  66. {
  67. int nx = x + dx[i],ny = y + dy[i];
  68. if (nx <0 || nx >= n) continue;
  69. if (ny <0 || ny >= m) continue;
  70. if (mp[nx][ny] == '#') continue;
  71. if (b[nx][ny] != -1) continue;
  72. if (a[nx][ny] != -1 && b[x][y] + 1 >= a[nx][ny]) continue;
  73. b[nx][ny] = b[x][y] + 1;
  74. mmp.push(p(nx,ny));
  75. }
  76. }
  77. return -1;
  78. }
  79. int main()
  80. {
  81. int t;
  82. scanf ("%d",&t);
  83. while (t--)
  84. {
  85. scanf("%d%d",&n,&m);
  86. memset(b,-1,sizeof(b));
  87. memset(a,-1,sizeof(a));
  88. memset(mp,0,sizeof(mp));
  89. for (int i = 0;i < n;i++)
  90. for (int j = 0;j < m;j++)
  91. scanf(" %c",&mp[i][j]);
  92. int ans = -1;
  93. bfs1();
  94. ans = bfs2();
  95. if (ans == -1) printf("IMPOSSIBLE\n");
  96. else printf("%d\n",ans);
  97. }
  98. return 0;
  99. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注