当前位置:   article > 正文

小丑的身份证和复印件 (BFS + Floyd)

小丑的身份证和复印件 (BFS + Floyd)

本题链接:登录—专业IT笔试面试备考平台_牛客网

题目:

样例:

输入
  1. 2 10
  2. (JOKERjoke
  3. #####asdr)
输出
12

思路:

        根据题意,要求最短时间,实际上也可以理解为最短距离。

        所以应该联想到有关最短距离的算法,在这里给出的 n,m是100,所以我们可以暴力求最短距离即可,身份碎片虽然分大小写,但是它们都是唯一的点,所以可以通过Floyd,记录每个点之间的最短距离,随后累加即可,其次这里的最短距离可以用BFS求得最短距离。注意一个细节,初始化无穷大的时候,尽量小一些,否则多个INF累加爆 long long 就会答案错误。

代码详解如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <climits>
  5. #include <algorithm>
  6. #define endl '\n'
  7. #define int long long
  8. #define x first
  9. #define y second
  10. #define umap unordered_map
  11. #define All(x) x.begin(),x.end()
  12. #pragma GCC optimize(3,"Ofast","inline")
  13. #define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
  14. using namespace std;
  15. const int N = 2e6 + 10;
  16. inline void solve();
  17. signed main()
  18. {
  19. // freopen("a.txt", "r", stdin);
  20. IOS;
  21. int _t = 1;
  22. // cin >> _t;
  23. while (_t--)
  24. {
  25. solve();
  26. }
  27. return 0;
  28. }
  29. using PII = pair<int,int>;
  30. int n,m;
  31. PII rem[256]; // rem 记录最短路中字符的位置
  32. char g[110][110];
  33. int dist[256][256]; // Floyd最短距离
  34. int dx[] = {0,1,0,-1};
  35. int dy[] = {1,0,-1,0};
  36. // BFS 求字符a 到字符 b 之间的最短路
  37. inline int Dist(char a,char b)
  38. {
  39. // 标记是否走动过当前位置
  40. vector<vector<bool>>st(110,vector<bool>(110,false));
  41. // 判断是否可以走动的条件
  42. auto isRun = [&](int x,int y)->bool
  43. {
  44. return (x >= 0 and x < n and y >= 0 and y < m and !st[x][y] and g[x][y] != '#');
  45. };
  46. // BFS 求最短路
  47. int step = 0;
  48. queue<PII>q;
  49. q.emplace(rem[a]);
  50. while(q.size())
  51. {
  52. int sz = q.size();
  53. while(sz--)
  54. {
  55. PII now = q.front();
  56. q.pop();
  57. if(g[now.x][now.y] == b)
  58. {
  59. rem[b] = now; // 记录当前最短路的位置
  60. return step;
  61. }
  62. st[now.x][now.y] = true;
  63. for(int i = 0;i < 4;++i)
  64. {
  65. int bx = now.x + dx[i];
  66. int by = now.y + dy[i];
  67. if(isRun(bx,by))
  68. {
  69. st[bx][by] = true;
  70. q.emplace(PII(bx,by));
  71. }
  72. }
  73. }
  74. ++step;
  75. }
  76. // 返回无穷大
  77. return INT_MAX;
  78. }
  79. inline void solve()
  80. {
  81. // 拿取碎片的方案
  82. vector<char>plan = {'J','O','K','E','R','j','o','k','e','r'};
  83. cin >> n >> m;
  84. for(int i = 0;i < n;++i)
  85. {
  86. for(int j = 0;j < m;++j)
  87. {
  88. char c;
  89. cin >> c;
  90. g[i][j] = c;
  91. // 存储好起点和终点的位置
  92. if(c == '(') rem[c] = PII(i,j);
  93. if(c == ')') rem[c] = PII(i,j);
  94. }
  95. }
  96. // 存储起点到各个字符之间的最短距离
  97. for(char &p:plan) dist['('][p] = Dist('(',p);
  98. // 存储终点到各个字符之间的最短距离
  99. for(char &p:plan) dist[p][')'] = Dist(')',p);
  100. // 存储各个点之间的最短距离
  101. for(char &st:plan)
  102. {
  103. for(char &ed:plan)
  104. {
  105. if(st == ed) continue;
  106. dist[st][ed] = Dist(st,ed);
  107. }
  108. }
  109. sort(All(plan));
  110. // 全排列遍历所有的捡碎片方案
  111. // 获取最小的一种答案即可
  112. int ans = INT_MAX;
  113. do
  114. {
  115. int res = 0;
  116. res += dist['('][*plan.begin()]; //累加起点开始的最短距离
  117. for(int i = 1;i < 10;++i) res += dist[plan[i - 1]][plan[i]]; // 按顺序累加最短距离
  118. res += dist[plan.back()][')']; // 累加最后到终点最短距离
  119. ans = min(ans,res);
  120. }while(next_permutation(All(plan)));
  121. if(ans >= INT_MAX) cout << "-1" << endl;
  122. else cout << ans << endl;
  123. }

最后提交:

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

闽ICP备14008679号