• 5 h0255. 迷宫问题,6 h0253. 鸣人和佐助(广度优先搜索)


    5 h0255. 迷宫问题

    给定一个 n×n 的二维数组,如下所示:

    1. int maze[5][5] = {
    2. 0, 1, 0, 0, 0,
    3. 0, 1, 0, 1, 0,
    4. 0, 0, 0, 0, 0,
    5. 0, 1, 1, 1, 0,
    6. 0, 0, 0, 1, 0,
    7. };

    它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

    数据保证至少存在一条从左上角走到右下角的路径。

    输入格式:

    第一行包含整数 n(0≤n≤1000)。

    接下来 n 行,每行包含 n 个整数 0 或 1,表示迷宫。

    输出格式:

    输出从左上角到右下角的最短路线,如果答案不唯一,输出任意一条路径均可。

    按顺序,每行输出一个路径中经过的单元格的坐标,左上角坐标为 (0,0),右下角坐标为 (n−1,n−1)。

    输入样例:

    1. 5
    2. 0 1 0 0 0
    3. 0 1 0 1 0
    4. 0 0 0 0 0
    5. 0 1 1 1 0
    6. 0 0 0 1 0

    输出样例:

    1. 0 0
    2. 1 0
    3. 2 0
    4. 2 1
    5. 2 2
    6. 2 3
    7. 2 4
    8. 3 4
    9. 4 4

    代码长度限制

    16 KB

    时间限制

    400 ms

    内存限制

    64 MB

     代码:

            一开始用递归写的广搜,测试点通不过,问老师说递归不需要广搜哈哈,就改成不用递归的广搜了哈哈。

    不带递归的广搜:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. const int Max = 1010;
    9. using namespace std;
    10. //结点结构
    11. typedef struct Point
    12. {
    13. int x, y;
    14. }point;
    15. //地图
    16. int maze[Max][Max];
    17. point path[Max][Max]; //走过的路径,每个位置记录他的父位置
    18. int visitied[Max][Max] = {0}; //看结点是否经过
    19. int n;
    20. //上下左右移动的数组,上下左右的顺序
    21. int xMove[4] = {-1, 1, 0, 0};
    22. int yMove[4] = { 0, 0,-1, 1};
    23. point start; // 起点的位置
    24. point endp; //终点的位置
    25. void bfs();
    26. void show();
    27. void showPath();
    28. int main()
    29. {
    30. //迷宫大小为n
    31. cin >> n ;
    32. //初始化迷宫、起点和中点,包一圈围墙好判断
    33. memset(maze, 1, sizeof(maze));
    34. start.x = 1; start.y = 1;
    35. endp.x = n; endp.y = n;
    36. //输入地图
    37. for(int i = 1; i <= n; i++)
    38. for(int j = 1; j <= n; j++)
    39. cin >> maze[i][j];
    40. //bfs解决问题
    41. visitied[1][1] = 1; //起始点设为走过
    42. path[1][1].x = -1; path[1][1].y = -1; //设出发点的父结点为-1,-1,用来做输出的停止
    43. bfs();
    44. show();
    45. //showPath(); //测试路径数组
    46. return 0;
    47. }
    48. void bfs()
    49. {
    50. queue q; //存放能走的路,遍历完四个方向后出队
    51. point next; //下一个结点
    52. q.push(start); //将第一个结点范进队列
    53. //遍历所有队列的元素
    54. while(!q.empty())
    55. {
    56. for(int i = 0; i < 4; i++)
    57. {
    58. //设置下一个结点
    59. //cout<< "当前判断的是" << q.front().x << ' ' << q.front().y << "位置" << endl;
    60. next.x = q.front().x + xMove[i];
    61. next.y = q.front().y + yMove[i];
    62. //如果是0,并且没走过,入队
    63. if(maze[next.x][next.y] == 0 && visitied[next.x][next.y] == 0)
    64. {
    65. //cout<< "结点:" << next.x << ' ' << next.y << "位置可以走" << endl;
    66. q.push(next);
    67. visitied[next.x][next.y] = 1;
    68. //在路径path中,记录该节点的父元素位置
    69. path[next.x][next.y] = q.front();
    70. }
    71. }
    72. q.pop();
    73. //cout << d.x << ' ' << d.y << ' ' << d.t << ' ' << d.time << endl;
    74. }
    75. }
    76. void show()
    77. {
    78. //从迷宫终点往回找,并存进栈中
    79. point now, next;
    80. now.x = now.y = n;
    81. stack s;
    82. s.push(now);
    83. //now为起点时结束
    84. while(path[now.x][now.y].x != -1 && path[now.x][now.y].y != -1)
    85. {
    86. next = path[now.x][now.y]; //在path中找下一个位置的坐标next
    87. now = next; //入栈
    88. s.push(now);
    89. }
    90. //输出
    91. while(!s.empty())
    92. {
    93. now = s.top();
    94. cout << now.x-1 << ' ' << now.y-1 << endl;
    95. s.pop();
    96. }
    97. }
    98. //测试路径
    99. void showPath()
    100. {
    101. for(int i = 1 ;i <= n; i++)
    102. {
    103. for(int j = 1; j <= n; j++)
    104. {
    105. cout << '(' << path[i][j].x << ' ' << path[i][j].y << ')' << ' ';
    106. }
    107. cout << endl;
    108. }
    109. }

    带递归的广搜:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. /*思路:从起点出发,每次判断上下左右的是否为0(通路),是的话将该条通路放进队列,
    7. 将所有通路放进队列后,再依次判断每个通路的上下左右是否为0。
    8. */
    9. using namespace std;
    10. //每个位置的坐标和它的父结点在队列中的位置
    11. struct Point
    12. {
    13. int x, y;
    14. int f;
    15. };
    16. void bfs(Point s); //广度优先遍历
    17. void show(Point q); //按照要求输出函数
    18. void show2();
    19. int n; //迷宫的行列
    20. int maze[1010][1010];//存放迷宫的二维数组
    21. int path = 0;
    22. Point que[1000010]; //队列,存放可以走的通路值
    23. int head = 0; //头指针
    24. int tail = 0; //尾指针
    25. Point resort[1000010]; //答案存放在这
    26. int main()
    27. {
    28. //按照要求输入
    29. cin >> n;
    30. if(n == 0)
    31. {
    32. cout << 0 << ' ' << 0 << endl;
    33. return 0;
    34. }
    35. for(int i = 0; i <= n+1; i++)
    36. {
    37. for(int j = 0; j <= n+1; j++)
    38. {
    39. maze[i][j] = 1;
    40. }
    41. }
    42. for(int i = 1; i <= n; i++)
    43. {
    44. for(int j = 1; j <= n; j++)
    45. {
    46. cin >> maze[i][j];
    47. }
    48. }
    49. //定义一个位置,用来当起点
    50. Point s;
    51. s.f = -1; s.x = 1; s.y = 1;
    52. //把起点先放进队列
    53. que[tail++] = s;
    54. //用起点来调用bfs算法
    55. bfs(s);
    56. //输出
    57. show(que[tail-1]);
    58. for(int i = path-1; i >= 0; i--)
    59. cout << resort[i].x-1 << ' ' << resort[i].y-1 << endl;
    60. //测试用
    61. /* show2();
    62. for(int i = 0; i <= n+1; i++)
    63. {
    64. for(int j = 0; j <= n+1; j++)
    65. {
    66. cout << maze[i][j] << ' ';
    67. }
    68. cout << endl;
    69. }*/
    70. }
    71. void bfs(Point s)
    72. {
    73. Point q; //用来存放每个改变的位置
    74. q.f = head; //当前判断的数是头结点
    75. maze[s.x][s.y] = 2; //该点设为走过
    76. int count = 0;
    77. //如果该点是终点,返回
    78. if(s.x == n && s.y == n)
    79. {
    80. return;
    81. }
    82. //如果上下左右的节点是0,放进队列,并且置该点为2
    83. //上
    84. q.x = s.x-1; q.y = s.y;
    85. if(maze[q.x][q.y] == 0)
    86. {
    87. //cout << "上" << endl;
    88. que[tail++] = q;
    89. count++;
    90. }
    91. //下
    92. q.x = s.x+1; q.y = s.y;
    93. if(maze[q.x][q.y] == 0)
    94. {
    95. //cout << "下" << endl;
    96. que[tail++] = q;
    97. count++;
    98. }
    99. //左
    100. q.x = s.x; q.y = s.y-1;
    101. if(maze[q.x][q.y] == 0)
    102. {
    103. //cout << "左" << endl;
    104. que[tail++] = q;
    105. count++;
    106. }
    107. //右
    108. q.x = s.x; q.y = s.y+1;
    109. if(maze[q.x][q.y] == 0)
    110. {
    111. //cout << "右" << endl;
    112. que[tail++] = q;
    113. count++;
    114. }
    115. //cout << "----------------------------------" <
    116. //再依次调用bfs
    117. head++;
    118. bfs(que[head]);
    119. }
    120. void show(Point q)
    121. {
    122. while(q.f != -1)
    123. {
    124. //cout << q.x-1 << ' ' << q.y-1 << ' ' << endl;
    125. resort[path++] = q;
    126. q = que[q.f];
    127. }
    128. if(q.f == -1)
    129. {
    130. //cout << q.x-1 << ' ' << q.y-1 << ' ' << endl;
    131. resort[path++] = q;
    132. }
    133. }
    134. void show2()
    135. {
    136. for(int i = 0; i < tail; i++)
    137. {
    138. cout << i << ": " << que[i].x-1 << ' ' << que[i].y-1 << ' ' << que[i].f << endl;
    139. }
    140. }

    6 h0253. 鸣人和佐助

    佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?

    已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?

    输入格式:

    输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
    后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。

    输出格式:

    输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。

    输入样例1:

    1. 4 4 1
    2. #@##
    3. **##
    4. ###+
    5. ****

    输出样例1:

    6
    

    输入样例2:

    1. 4 4 2
    2. #@##
    3. **##
    4. ###+
    5. ****

    输出样例2:

    4
    

    代码长度限制

    16 KB

    时间限制

    400 ms

    内存限制

    64 MB

     代码:

            其实我是先做的这道题,然后用这道题的代码改成上一题的,话说鸣人的查克拉难道不是用不完的吗哈哈。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. const int Max = 210;
    8. using namespace std;
    9. //结点结构
    10. typedef struct Point
    11. {
    12. int x, y;
    13. int t; //查克拉
    14. int time; //花的时间
    15. }point;
    16. //地图
    17. char maze[Max][Max];
    18. point path[Max][Max]; //走过的路径,每个位置记录他的父位置
    19. int visitied[Max][Max] = {0}; //看结点是否经过
    20. int m, n, t;
    21. //上下左右移动的数组,上下左右的顺序
    22. int xMove[4] = {-1, 1, 0, 0};
    23. int yMove[4] = { 0, 0,-1, 1};
    24. point mingRen; // 名人的位置
    25. point zuoZhu; //佐助的位置
    26. int bfs();
    27. int main()
    28. {
    29. //行m,列n,名人查克拉t
    30. cin >> m >> n >> t;
    31. //初始化迷宫,包一圈围墙好判断
    32. memset(maze, 0, sizeof(maze));
    33. //初始化path,让没走过的为no
    34. //其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下
    35. for(int i = 1; i <= m; i++)
    36. for(int j = 1; j <= n; j++)
    37. {
    38. cin >> maze[i][j];
    39. //找到名人和佐助的位置
    40. if(maze[i][j] == '@')
    41. {
    42. mingRen.x = i;
    43. mingRen.y = j;
    44. }
    45. if(maze[i][j] == '+')
    46. {
    47. zuoZhu.x = i;
    48. zuoZhu.y = j;
    49. }
    50. }
    51. //bfs解决问题
    52. mingRen.t = t; //名人的查克拉
    53. mingRen.time = 0;//一开始的时间为0
    54. visitied[mingRen.x][mingRen.y] = 1; //起始点设为走过
    55. int resort = bfs();
    56. cout << resort;
    57. return 0;
    58. }
    59. int bfs()
    60. {
    61. queue q; //存放能走的路,遍历完四个方向后出队
    62. point next; //下一个结点
    63. q.push(mingRen); //将第一个结点范进队列
    64. //遍历所有队列的元素
    65. while(!q.empty())
    66. {
    67. for(int i = 0; i < 4; i++)
    68. {
    69. //设置下一个结点
    70. next.x = q.front().x + xMove[i];
    71. next.y = q.front().y + yMove[i];
    72. next.t = q.front().t;
    73. next.time = q.front().time;
    74. //如果是*,并且没走过,则不需要小号查克拉,直接入队
    75. if(maze[next.x][next.y] == '*' && visitied[next.x][next.y] == 0)
    76. {
    77. next.time++;
    78. q.push(next);
    79. //cout << next.x << ' ' << next.y << ' ' << next.t << ' ' << next.time << endl;
    80. visitied[next.x][next.y] = 1;
    81. //在路径path中,记录该节点的父元素位置
    82. path[next.x][next.y] = mingRen;
    83. }
    84. //如果是#,大蛇丸手下,判断查克拉
    85. else if(maze[next.x][next.y] == '#' && visitied[next.x][next.y] == 0)
    86. {
    87. if(next.t > 0)
    88. {
    89. next.time++;
    90. //cout << " haha" << endl;
    91. next.t--; //消耗一点查克拉
    92. q.push(next);
    93. //cout << next.x << ' ' << next.y << ' ' << next.t << ' ' << next.time << endl;
    94. visitied[next.x][next.y] = 1;
    95. //在路径path中,记录该节点的父元素位置
    96. path[next.x][next.y] = mingRen;
    97. }
    98. }
    99. //如果是+,就是佐助,存入路径,结束调用
    100. else if(maze[next.x][next.y] == '+')
    101. {
    102. next.time++;
    103. q.push(next);
    104. path[next.x][next.y] = mingRen;
    105. return next.time;
    106. }
    107. }
    108. point d = q.front();
    109. q.pop();
    110. //cout << d.x << ' ' << d.y << ' ' << d.t << ' ' << d.time << endl;
    111. }
    112. //到这说明到不了佐助
    113. return -1;
    114. }

    若对您有帮助麻烦点个赞哦~

  • 相关阅读:
    惨,给Go提的代码被批麻了
    2. IDEA配置antlr4(on mac)
    深度学习硬件介绍
    Assert断言常用工具类
    bootstrap 主题
    并发编程之 ThreadLocal
    高级深入--day37
    在 Kubernetes 上部署 DM
    重庆开放大学学子们的好帮手
    LeetCode-62-不同路径-动态规划
  • 原文地址:https://blog.csdn.net/weixin_63484669/article/details/127693927