[关闭]
@tenlee 2015-07-31T09:48:23.000000Z 字数 2465 阅读 1631

HDU 5335 Walk Out(2015多校联合)

HDUOJ


题目链接

戳我

题目大意

mn的矩阵,每个格子是0或者1,探险家初始位置是(1,1),终点位置是(n,m),且只能向 上下左右四个方向走,因为从 起点到终点 所走的路径是由01构成的,故可表示成二进制数,要求寻找一条路径表示的二进制数最小.

样例解释

2 //T 两组测试样例
2 2 // n,m, 行 列
11 //第一行
11 //第二行 路径为(1,1)>(1,2)>(2,2)(也可以是其他),故为111
3 3 //n, m
001
111
101 //路径为(1,1)>(1,2)>(2,2)>(3>2)>(3,3)故为00101,即101

解题思路

因为是二进制,所以要尽可能的走0,走0走的离终点越近越好.

代码

  1. //Author LJH
  2. //www.cnblogs.com/tenlee
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <cctype>
  7. #include <cmath>
  8. #include <algorithm>
  9. #include <vector>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #define clc(a, b) memset(a, b, sizeof(a))
  14. using namespace std;
  15. const int inf = 0x3f;
  16. const int INF = 0x3f3f3f3f;
  17. const int maxn = 1e3+10;
  18. int MOVE[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
  19. struct Point
  20. {
  21. int x, y;
  22. int step;
  23. }p[maxn];
  24. int vis[maxn][maxn];
  25. char g[maxn][maxn];
  26. int n, m;
  27. char ans[maxn*4];
  28. queue<Point> q;
  29. queue<Point> q1;
  30. inline bool judge(int x, int y)
  31. {
  32. if(x < 0 || x >= n || y < 0 || y >= m) return false;
  33. return true;
  34. }
  35. void BFS(int x, int y)
  36. {
  37. while(!q.empty()) q.pop();
  38. int xx, yy;
  39. int dis = m+n-2;
  40. Point s, now, next;
  41. s.x = x; s.y = x; s.step = 0;
  42. q.push(s);
  43. while(!q.empty() && g[x][y] == '0') //开始一直走0
  44. {
  45. now = q.front(); q.pop();
  46. q1.push(now);
  47. if(n-1-now.x+m-1-now.y < dis) //寻找离终点最近的 0 点 的距离
  48. {
  49. dis = n-1-now.x+m-1-now.y;
  50. }
  51. for(int i = 0; i < 4; i++)
  52. {
  53. xx = now.x + MOVE[i][0];
  54. yy = now.y + MOVE[i][1];
  55. if(!judge(xx, yy)) continue;
  56. if(g[xx][yy] == '1') continue;
  57. if(vis[xx][yy]) continue;
  58. vis[xx][yy] = 1;
  59. next.x = xx; next.y = yy;
  60. next.step = now.step + 1;
  61. q.push(next);
  62. }
  63. }//q已空
  64. while(!q1.empty())
  65. {
  66. now = q1.front(); q1.pop();
  67. if(n-1-now.x+m-1-now.y == dis) //把到终点的距离等于dis的0点加入队列
  68. {
  69. q.push(now);
  70. }
  71. } //q1 已空
  72. if(dis == 0) //此时说明可以直接走0到终点
  73. {
  74. ans[0] = '0';
  75. ans[1] = '\0';
  76. return;
  77. }
  78. int t = 0; // 所走的路径
  79. char flag = '1';
  80. if(dis == n+m-2) ans[t++] = '1';
  81. while(!q.empty())
  82. {
  83. flag = '1';
  84. while(!q.empty()) //属于同一层的都找出来
  85. {
  86. now = q.front(); q.pop();
  87. //printf("x = %d, y = %d, step = %d\n", now.x, now.y, now.step);
  88. for(int i = 0; i < 2; i++)
  89. {
  90. xx = now.x + MOVE[i][0];
  91. yy = now.y + MOVE[i][1];
  92. if(!judge(xx, yy) || vis[xx][yy]) continue;
  93. vis[xx][yy] = 1;
  94. if(g[xx][yy] == '0') flag = '0'; //如果该层有0,则把0都挑出来作为下一步
  95. next.x = xx; next.y = yy; next.step = now.step + 1;
  96. q1.push(next);
  97. }
  98. }
  99. while(!q1.empty())
  100. {
  101. now = q1.front(); q1.pop();
  102. if(now.x == n-1 && now.y == m-1)
  103. {
  104. ans[t++] = g[n-1][m-1];
  105. ans[t] = '\0';
  106. return;
  107. }
  108. if(g[now.x][now.y] == flag)//如果该层有0,则把0都挑出来作为下一步
  109. {
  110. q.push(now);
  111. }
  112. }
  113. ans[t++] = flag;
  114. }
  115. }
  116. int main()
  117. {
  118. int T;
  119. scanf("%d", &T);
  120. while(T--)
  121. {
  122. clc(vis, 0);
  123. scanf("%d %d", &n, &m);
  124. for(int i = 0; i < n; i++)
  125. {
  126. scanf("%s", g[i]);
  127. }
  128. if(n == 1 && m == 1)
  129. {
  130. puts(g[0]);
  131. continue;
  132. }
  133. BFS(0, 0);
  134. printf("%s\n", ans);
  135. }
  136. return 0;
  137. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注