最小步数模型 AcWing 1107. 魔板

妖狐艹你老母 2024-04-08 13:32 162阅读 0赞

最小步数模型 AcWing 1107. 魔板

原题链接

AcWing 1107. 魔板

算法标签

BFS

思路

如何求最少的基本操作完成基本状态到特殊状态的转换

即求步数 采用BFS
原因
在这里插入图片描述

对于状态存储

采用康拓扩展
采用hash法存储(C++ 采用map C++11 建议采用unorderer_map存储)

在这里插入图片描述

如何输出字典序最小的操作序列

若前缀序列一致, 则按照先A再B再C扩展可以得到最小的操作序列

在这里插入图片描述

代码

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define rep(i, a, b) for(int i=a;i<b;++i)
  4. #define Rep(i, a, b) for(int i=a;i>=b;--i)
  5. #define x first
  6. #define y second
  7. using namespace std;
  8. typedef pair<int, int> PII;
  9. const int N = 1005;
  10. char g[2][4];
  11. // 存储从转移至该状态的上一个状态
  12. // 同时存储操作选择为 A or B or C
  13. unordered_map<string, pair<char, string>> pre;
  14. // 存储每个状态的步数
  15. unordered_map<string, int> d;
  16. inline int rd(){
  17. int s=0,w=1;
  18. char ch=getchar();
  19. while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
  20. while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
  21. return s*w;
  22. }
  23. void put(int x) {
  24. if(x<0) putchar('-'),x=-x;
  25. if(x>=10) put(x/10);
  26. putchar(x%10^48);
  27. }
  28. // 将当前字符串放入g中,对于所有move操作对g操作
  29. void set0(string s){
  30. rep(i, 0, 4){
  31. g[0][i]=s[i];
  32. }
  33. for(int i=7, j=0; j<4; --i, ++j){
  34. g[1][j]=s[i];
  35. }
  36. }
  37. // 将g放入当前字符串中,对于所有move操作返回g操作后的s字符串
  38. string get0(){
  39. string s;
  40. rep(i, 0, 4){
  41. s+=g[0][i];
  42. }
  43. Rep(i, 3, 0){
  44. s+=g[1][i];
  45. }
  46. return s;
  47. }
  48. string move0(string s){
  49. set0(s);
  50. rep(i, 0, 4){
  51. swap(g[0][i], g[1][i]);
  52. }
  53. return get0();
  54. }
  55. string move1(string s){
  56. set0(s);
  57. int v0=g[0][3], v1=g[1][3];
  58. Rep(i, 3, 0){
  59. g[0][i]=g[0][i-1];
  60. g[1][i]=g[1][i-1];
  61. }
  62. g[0][0]=v0, g[1][0]=v1;
  63. return get0();
  64. }
  65. string move2(string s){
  66. set0(s);
  67. int v=g[0][1];
  68. g[0][1]=g[1][1];
  69. g[1][1]=g[1][2];
  70. g[1][2]=g[0][2];
  71. g[0][2]=v;
  72. return get0();
  73. }
  74. int bfs(string st, string end){
  75. if(st==end){
  76. return 0;
  77. }
  78. queue<string> q;
  79. q.push(st);
  80. d[st]=0;
  81. while(!q.empty()){
  82. string t=q.front();
  83. q.pop();
  84. string m[3];
  85. m[0]=move0(t);
  86. m[1]=move1(t);
  87. m[2]=move2(t);
  88. rep(i, 0, 3){
  89. if(!d.count(m[i])){
  90. d[m[i]]=d[t]+1;
  91. pre[m[i]]={'A'+i, t};
  92. q.push(m[i]);
  93. if(m[i]==end){
  94. return d[end];
  95. }
  96. }
  97. }
  98. }
  99. return -1;
  100. }
  101. signed main(){
  102. ios::sync_with_stdio(false);
  103. cin.tie(0);
  104. cout.tie(0);
  105. int x;
  106. string st, end;
  107. rep(i, 0, 8){
  108. x=rd();
  109. end+=x+'0';
  110. }
  111. rep(i, 1, 9){
  112. st+=i+'0';
  113. }
  114. int cnt=bfs(st, end);
  115. printf("%lld\n", cnt);
  116. string ans;
  117. while(end!=st){
  118. ans+=pre[end].x;
  119. end=pre[end].y;
  120. }
  121. reverse(ans.begin(), ans.end());
  122. if(cnt){
  123. printf("%s", ans.c_str());
  124. }
  125. return 0;
  126. }

参考文献
AcWing 1107. 魔板(算法提高课)y总视频
AcWing 1107. 魔板(算法提高课)y总代码

原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,162人围观)

还没有评论,来说两句吧...

相关阅读

    相关 华为OD机试Python【求

    题目 你在一个一维的数轴上,起始位置为0。你每次只能走2步或3步,无论是向左还是向右。有时你可能需要走到负坐标上去,才能最终到达你的目标位置。 任务: 给定一个坐标