当前位置:   article > 正文

c++算法学习笔记 (7) BFS

c++算法学习笔记 (7) BFS

1.走迷宫

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <queue>
  4. #include <cstring>
  5. using namespace std;
  6. typedef pair<int, int> PII;
  7. const int N = 105;
  8. int n, m;
  9. int g[N][N]; // 存图
  10. int d[N][N]; // 每个点到起点的距离
  11. queue<PII> q[N * N];
  12. int bfs()
  13. {
  14. q->push(make_pair(0, 0));
  15. memset(d, -1, sizeof d);
  16. d[0][0] = 0;
  17. int dx[4] = {-1, 0, 1, 0};
  18. int dy[4] = {0, 1, 0, -1};
  19. while (!q->empty())
  20. {
  21. PII t = q->front(); // 取队头
  22. q->pop();
  23. for (int i = 0; i < 4; i++)
  24. {
  25. int x = t.first + dx[i], y = t.second + dy[i];
  26. if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
  27. { // 在范围内且“第一次搜到”
  28. d[x][y] = d[t.first][t.second] + 1; // 距离+1
  29. q->push(make_pair(x, y));
  30. }
  31. }
  32. }
  33. return d[n - 1][m - 1]; // 右下角的距离
  34. }
  35. int main()
  36. {
  37. cin >> n >> m;
  38. for (int i = 0; i < n; i++)
  39. {
  40. for (int j = 0; j < m; j++)
  41. {
  42. cin >> g[i][j];
  43. }
  44. }
  45. cout << bfs() << endl;
  46. return 0;
  47. }

2.八数码

在一个 3×3 的网格中,1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。

例如:

  1. 1 2 3
  2. x 4 6
  3. 7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

  1. 1 2 3
  2. 4 5 6
  3. 7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

  1. 1 2 3 1 2 3 1 2 3 1 2 3
  2. x 4 6 4 x 6 4 5 6 4 5 6
  3. 7 5 8 7 5 8 7 x 8 7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将 3×3 的初始网格描绘出来。

例如,如果初始网格如下所示:

  1. 1 2 3
  2. x 4 6
  3. 7 5 8

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 −1。

输入样例:
2 3 4 1 5 x 7 6 8
输出样例
19

思路:12345678x及其剩余的状态用string 存储,这样比较的时候直接与"12345678x"比。

  1. // 八数码
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <unordered_map>
  5. #include <queue>
  6. using namespace std;
  7. int bfs(string start)
  8. {
  9. string end = "12345678x";
  10. queue<string> q; // 状态
  11. unordered_map<string, int> d; // 每个状态的距离
  12. q.push(start);
  13. d[start] = 0; // 起点到起点的距离为0
  14. int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
  15. while (q.size())
  16. {
  17. auto t = q.front(); // t此时为string
  18. q.pop();
  19. int distance = d[t];
  20. if (t == end)
  21. return d[t];
  22. // 状态转移
  23. int k = t.find("x"); // 找x的下标
  24. int x = k / 3, y = k % 3;
  25. for (int i = 0; i < 4; i++)
  26. {
  27. int a = x + dx[i], b = y + dy[i]; // 转移后x的坐标
  28. if (a >= 0 && a < 3 && b >= 0 && b < 3)
  29. { // 坐标未出界
  30. swap(t[k], t[a * 3 + b]); // 状态更新(转移x)
  31. if (!d.count(t))
  32. { // t状态之前没被搜到过
  33. d[t] = distance + 1;
  34. q.push(t);
  35. }
  36. /// 还原状态,为下一种转换情况做准备
  37. swap(t[k], t[a * 3 + b]); // 恢复状态(不要忘记!!!)
  38. }
  39. }
  40. }
  41. // 无法转换到目标状态,返回-1
  42. return -1;
  43. }
  44. int main()
  45. {
  46. string start;
  47. for (int i = 0; i < 9; i++)
  48. {
  49. char c;
  50. cin >> c;
  51. start += c;
  52. }
  53. cout << bfs(start) << endl;
  54. return 0;
  55. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/284895
推荐阅读
相关标签
  

闽ICP备14008679号