当前位置:   article > 正文

杭电OJ 1044(C++)_c++ oj p1044

c++ oj p1044
  1. #include <iostream>
  2. #include <cstring>
  3. #include <queue>
  4. using namespace std;
  5. struct node
  6. {
  7. int x; int y; int time;
  8. node(int a, int b, int c) :x(a), y(b), time(c){}
  9. };
  10. int W, H, L, M, ans, vals;
  11. char maze[55][55]; //输入的迷宫矩阵
  12. bool vis[55][55]; //迷宫的访问矩阵
  13. int graph[15][15]; //距离虚图
  14. int jewel[15]; //起点、终点、珠宝点的价值
  15. bool isUsed[15]; //起点、终点、珠宝店的访问数组
  16. int dx[4] = { 0, 1, 0, -1 }; //上下方向
  17. int dy[4] = { -1, 0, 1, 0 }; //左右方向
  18. //广度优先搜索,建立一张虚图,起点、终点、珠宝点两两之间距离的图
  19. void bfs(int x1, int y1)
  20. {
  21. memset(vis, false, sizeof(vis));
  22. int u, v; //u为当前点的索引,v为下一个点的索引
  23. char a = maze[x1][y1]; //取出当前字符
  24. if (a == '@') u = 0; //当前点为起点
  25. if (a >= 'A' && a <= 'J') u = a - 'A' + 1; //当前点为珠宝点
  26. node pos(0, 0, 0), nextpos(0, 0, 0); //当前点,下一步的点
  27. pos.x = x1; pos.y = y1; pos.time = 0;
  28. queue<node> Q;
  29. Q.push(pos);
  30. vis[pos.x][pos.y] = true;
  31. while (!Q.empty())
  32. {
  33. pos = Q.front(); Q.pop();
  34. if (pos.time == L) //超时,剪枝
  35. break;
  36. for (int i = 0; i < 4; i++)
  37. {
  38. nextpos.x = pos.x + dx[i];
  39. nextpos.y = pos.y + dy[i];
  40. nextpos.time = pos.time + 1;
  41. // 如果为墙壁或者访问过,跳过
  42. if (maze[nextpos.x][nextpos.y] == '*' || vis[nextpos.x][nextpos.y])
  43. continue;
  44. //如果超出矩阵的范围,跳过
  45. if (nextpos.x < 0 || nextpos.x >= H || nextpos.y < 0 || nextpos.y >= W)
  46. continue;
  47. vis[nextpos.x][nextpos.y] = true; //设置为访问过
  48. if (maze[nextpos.x][nextpos.y] == '@') //下一点为起点
  49. graph[u][0] = graph[0][u] = nextpos.time;
  50. else if (maze[nextpos.x][nextpos.y] == '<') //下一点为终点
  51. graph[u][M + 1] = graph[M + 1][u] = nextpos.time;
  52. else if (maze[nextpos.x][nextpos.y] >= 'A'&&maze[nextpos.x][nextpos.y] <= 'J')
  53. { //下一点为珠宝点
  54. v = maze[nextpos.x][nextpos.y] - 'A' + 1; //取得珠宝顺序的索引
  55. graph[u][v] = graph[v][u] = nextpos.time;
  56. }
  57. Q.push(nextpos); //加入队列
  58. }
  59. }
  60. }
  61. //对虚图进行深度优先搜索
  62. void dfs(int index, int limit, int je)
  63. { //index当前点的索引,limit为当前走过的时间,je为当前取得珠宝的价值和
  64. if (limit > L) return; //超过时间范围,结束,ans为初始值-1
  65. if (ans == vals) return; //没超过时间范围的前提下,已取得所有珠宝的总价值
  66. if (index == M + 1) //到达出口
  67. {
  68. if (je > ans)
  69. ans = je;
  70. return;
  71. }
  72. for (int i = 1; i <= M + 1; i++) //深度优先搜索
  73. {
  74. if (isUsed[i] || graph[index][i] == 0) continue; //访问过,或者无法到达
  75. isUsed[i] = true;
  76. dfs(i, limit + graph[index][i], je + jewel[i]);
  77. isUsed[i] = false; //回溯
  78. }
  79. }
  80. int main()
  81. {
  82. int t;
  83. cin >> t;
  84. for (int tt = 1; tt <= t; tt++)
  85. {
  86. ans = -1; //最后结果
  87. vals = 0; //珠宝价值和
  88. cin >> W >> H >> L >> M;
  89. for (int i = 1; i <= M; i++)
  90. {
  91. cin >> jewel[i]; //输入珠宝价值
  92. vals += jewel[i]; //珠宝的价值和
  93. }
  94. jewel[0] = jewel[M + 1] = 0; //初始化起点和终点的价值为0
  95. for (int i = 0; i < H; i++)
  96. cin >> maze[i]; //输入迷宫数组(一次一行)
  97. memset(graph, 0, sizeof(graph)); //初始化虚图,无法到达时间距离为0
  98. for (int i = 0; i < H; i++)
  99. for (int j = 0; j < W; j++)
  100. { //只允许起点和珠宝点进行广度优先搜索
  101. if (maze[i][j] == '@' || (maze[i][j] >= 'A'&&maze[i][j] <= 'J'))
  102. bfs(i, j); //建立起点、终点、珠宝点两两之间距离的虚图
  103. }
  104. memset(isUsed, false, sizeof(isUsed));
  105. isUsed[0] = true;
  106. dfs(0, 0, 0);
  107. cout << "Case " << tt << ":" << endl;
  108. if (ans == -1)
  109. cout << "Impossible" << endl;
  110. else
  111. cout << "The best score is " << ans << "." << endl;
  112. if (tt != t)
  113. cout << endl;
  114. }
  115. return 0;
  116. }

 

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

闽ICP备14008679号