[关闭]
@zsh-o 2018-12-22T18:34:03.000000Z 字数 2488 阅读 1152

商汤C++ 第三题 - 分割后处理 - BFS、DFS

算法


商汤的第三题,地址:分割后处理,主要复习一遍BFS和DFS,包括DFS的递归写法、栈写法和BFS的队列写法

image.png-143kB

  1. // 两次求相邻区域,第一次求水面区域,标记为确定水面,第二次求陆地区域,过程中所有不是确定水面的全部标记为陆地,最后求陆地面积(在第二次搜索过程中求)
  2. // 需要使用bfs或dfs,都写一遍
  3. #include <stdio.h>
  4. #include <string.h>
  5. const int MAXN = 1e3 + 1;
  6. const int MAXM = 1e3 + 1;
  7. const int MAXSTACK = 1e8 + 1;
  8. int M, N;
  9. int A[MAXM][MAXN];
  10. bool visted[MAXM][MAXN];
  11. //四个方向
  12. int LM[] = {1, -1, 0, 0};
  13. int LN[] = {0, 0, -1, 1};
  14. //把标记为mark,dfs深度优先搜索需要用到栈,judge判断当前遍历点是否符合条件
  15. void dfs(int m, int n, bool (*judge)(int,int), int mark){
  16. if(!judge(m, n) || visted[m][n]){
  17. return;
  18. }
  19. int* _stack = new int[MAXSTACK];
  20. int head = 0; // head==0 为空
  21. _stack[head] = m;
  22. _stack[head + 1] = n;
  23. head += 2;
  24. visted[m][n] = true;
  25. A[m][n] = mark;
  26. while(head > 0){
  27. int cm = _stack[head - 2];
  28. int cn = _stack[head - 1];
  29. bool changed = false;
  30. //判断四个方向
  31. for(int i=0; i<4; i++){
  32. int nextm = cm + LM[i];
  33. int nextn = cn + LN[i];
  34. if((nextm >=0 && nextm < M) && (nextn >=0 && nextn < N) && !visted[nextm][nextn] && judge(nextm, nextn)){
  35. _stack[head] = nextm;
  36. _stack[head + 1] = nextn;
  37. head += 2;
  38. visted[nextm][nextn] = true;
  39. changed = true;
  40. A[nextm][nextn] = mark;
  41. //printf("(%d, %d) - ", nextm, nextn);
  42. break;
  43. }
  44. }
  45. if(!changed){
  46. head -= 2;
  47. }
  48. }
  49. delete _stack;
  50. }
  51. void _dfs(int m, int n, bool (*judge)(int, int), int mark){
  52. if(!judge(m, n) || visted[m][n]){
  53. return;
  54. }
  55. visted[m][n] = true;
  56. A[m][n] = mark;
  57. for(int i=0; i<4; i++){
  58. int nextm = m + LM[i];
  59. int nextn = n + LN[i];
  60. if(nextm >=0 && nextm < M && nextn >= 0 && nextn < N){
  61. _dfs(nextm, nextn, judge, mark);
  62. }
  63. }
  64. }
  65. void bfs(int m, int n, bool (*judge)(int, int), int mark){
  66. if(!judge(m, n) || visted[m][n]){
  67. return;
  68. }
  69. // head == tail 为空,不用考虑满的问题
  70. int* _queue = new int[MAXSTACK];
  71. int head = 0;
  72. int tail = 0;
  73. _queue[head] = m;
  74. _queue[head + 1] = n;
  75. head += 2;
  76. while(head != tail){
  77. int cm = _queue[tail];
  78. tail = (tail + 1) % MAXSTACK;
  79. int cn = _queue[tail];
  80. tail = (tail + 1) % MAXSTACK;
  81. visted[cm][cn] = true;
  82. A[cm][cn] = mark;
  83. for(int i=0; i<4; i++){
  84. int nextm = cm + LM[i];
  85. int nextn = cn + LN[i];
  86. if(nextm >= 0 && nextm < M && nextn >= 0 && nextn < N && !visted[nextm][nextn] && judge(nextm, nextn)){
  87. _queue[head] = nextm;
  88. head = (head + 1) % MAXSTACK;
  89. _queue[head] = nextn;
  90. head = (head + 1) % MAXSTACK;
  91. printf("(%d, %d) - ", nextm, nextn);
  92. }
  93. }
  94. }
  95. delete _queue;
  96. }
  97. bool judge1(int x, int y){
  98. return A[x][y] == 0;
  99. }
  100. bool judge2(int x, int y){
  101. return A[x][y] != -1;
  102. }
  103. int main(){
  104. memset(visted, 0x00, sizeof(visted));
  105. scanf("%d%d", &M, &N);
  106. int a;
  107. for(int i=0; i<M; i++){
  108. for(int j=0; j<N; j++){
  109. scanf("%d", &a);
  110. A[i][j] = a;
  111. }
  112. }
  113. //从上左右均检测一次海域
  114. for(int i=0; i<N; i++){
  115. {
  116. printf("\nstart: (%d, %d) - ", 0, i);
  117. bfs(0, i, judge1, -1);
  118. }
  119. }
  120. for(int i=0; i<M; i++){
  121. {
  122. printf("\nstart: (%d, %d) - ", i, 0);
  123. bfs(i, 0, judge1, -1);
  124. }
  125. {
  126. printf("\nstart: (%d, %d) - ", i, N-1);
  127. bfs(i, N-1, judge1, -1);
  128. }
  129. }
  130. for(int i=0; i<N; i++){
  131. A[M-1][i] = 2;
  132. printf("\nstart: (%d, %d) - ", M - 1, i);
  133. bfs(M-1, i, judge2, 2);
  134. }
  135. int area = 0;
  136. for(int i=0; i<M; i++){
  137. for(int j=0; j<N; j++){
  138. if(A[i][j] == 2){
  139. area++;
  140. }
  141. }
  142. }
  143. printf("%d\n", area);
  144. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注