[关闭]
@Moritz 2019-03-29T08:17:52.000000Z 字数 3586 阅读 517

九宫重排

BFS C++ 蓝桥杯 所有文稿


题目描述

如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

img

第一个图的局面记为:12345678.,第二个图的局面记为:123.46758

已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入

输入第一行包含九宫的初态,第二行包含九宫的终态。

输出

输出最少的步数,如果不存在方案,则输出-1。

样例输入

  1. 12345678.
  2. 123.46758

样例输出

  1. 3

思路:bfs,map<string,int>判重和记录步数
非常少有的一次AC了,优化什么的……

  1. /*21:22-21:49*/
  2. /*9:39-10:52*/
  3. #include <iostream>
  4. #include <string>
  5. #include <queue>
  6. #include <map>
  7. #include <cstdio>
  8. using namespace std;
  9. map<string,int> ge;
  10. queue<string> qu;
  11. string u(string str,int dot){
  12. swap(str[dot],str[dot-3]);
  13. return str;
  14. }
  15. string d(string str,int dot){
  16. swap(str[dot],str[dot+3]);
  17. return str;
  18. }
  19. string l(string str,int dot){
  20. string str2=str.substr(0,dot-1)+'.'+str[dot-1]+str.substr(dot+1);
  21. return str2;
  22. }
  23. string r(string str,int dot){
  24. string str2;
  25. if (dot>0){str2=str.substr(0,dot-1)+str[dot-1]+str[dot+1]+'.'+str.substr(dot+2);return str2;}
  26. str[0]=str[1];str[1]='.';//注意 如果'.'下标为0 则下标会超出范围
  27. return str;
  28. }
  29. string (*fun[])(string str,int dot)={&u,&d,&l,&r};
  30. void push(string str,int dot){//其实应该有简化版的。。
  31. int num=ge[str];
  32. switch(dot){
  33. case 0:for(int i=1;i<=3;i+=2){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  34. ge[str2]=num+1;qu.push(str2);}}break;
  35. case 1:for(int i=1;i<=3;i++){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  36. ge[str2]=num+1;qu.push(str2);}}break;
  37. case 2:for(int i=1;i<=2;i++){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  38. ge[str2]=num+1;qu.push(str2);}}break;
  39. case 3:for(int i=0;i<=3;i++){if(i!=2){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  40. ge[str2]=num+1;qu.push(str2);}}}break;
  41. case 4:for(int i=0;i<=3;i++){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  42. ge[str2]=num+1;qu.push(str2);}}break;
  43. case 5:for(int i=0;i<=3;i++){if(i!=3){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  44. ge[str2]=num+1;qu.push(str2);}}}break;
  45. case 6:for(int i=0;i<=3;i+=3){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  46. ge[str2]=num+1;qu.push(str2);}}break;
  47. case 7:for(int i=0;i<=3;i++){if(i!=1){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  48. ge[str2]=num+1;qu.push(str2);}}}break;
  49. case 8:for(int i=0;i<=2;i+=2){string str2=fun[i](str,dot);if(!ge.count(str2)) {
  50. ge[str2]=num+1;qu.push(str2);}}break;
  51. }
  52. }
  53. int main(){
  54. string s,e,str;
  55. int sdot;
  56. cin>>s>>e;
  57. ge[s]=0;
  58. qu.push(s);
  59. bool find=false;
  60. while(!qu.empty()){
  61. str=qu.front();
  62. qu.pop();
  63. push(str,str.find('.'));
  64. if (str==e) {cout<<ge[e];find=true;break;}
  65. }
  66. if (!find) cout<<-1;
  67. return 0;
  68. }

据说会超时,用双向广度搜索,参考代码,(未解决)

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <string>
  4. #include <iostream>
  5. #include <queue>
  6. #include <map>
  7. using namespace std;
  8. map <string, int> M1;
  9. map <string, int> M2;
  10. typedef pair <string, int> P;
  11. int dir[4] = {1, -1, 3, -3};
  12. string s, e; // s 代表起始, e 代表结束
  13. bool judge(int x)
  14. {
  15. if(x < 0 || x > 8)
  16. return false;
  17. else
  18. return true;
  19. }
  20. int bfs()
  21. {
  22. P pre1, nex1, pre2, nex2;
  23. pre1.first = s;
  24. pre1.second = 0;
  25. pre2.first = e;
  26. pre2.second = 0;
  27. queue <P> Q1;
  28. queue <P> Q2;
  29. M1[s] = 0;
  30. M2[s] = 0;
  31. Q1.push(pre1);
  32. Q2.push(pre2);
  33. while(!Q1.empty())
  34. {
  35. pre1 = Q1.front();
  36. Q1.pop();
  37. pre2 = Q2.front();
  38. Q2.pop();
  39. string ts1 = pre1.first;
  40. int tn1 = pre1.second;
  41. string ts2 = pre2.first;
  42. int tn2 = pre2.second;
  43. int it1 = ts1.find('.');
  44. int it2 = ts2.find('.');
  45. if(ts1 == e)
  46. {
  47. return tn1;
  48. }
  49. for(int i = 0; i < 4; ++ i)
  50. {
  51. int t1 = it2 + dir[i];
  52. string t2 = ts2;
  53. char t3 = t2[it2];
  54. t2[it2] = t2[t1];
  55. t2[t1] = t3;
  56. int t4 = tn2 + 1;
  57. if((i == 0 && (it2 == 2 || it2 == 5))||(i == 1 && (it2 == 3 || it2 == 6)))
  58. continue;
  59. if(judge(t1))
  60. {
  61. if(M2[t2])
  62. continue;
  63. M2[t2] = tn2 + 1;
  64. if(M1[t2])
  65. return M1[t2] + M2[t2];
  66. nex2.first = t2;
  67. nex2.second = t4;
  68. Q2.push(nex2);
  69. }
  70. }
  71. for(int i = 0; i < 4; ++ i)
  72. {
  73. int t1 = it1 + dir[i];
  74. string t2 = ts1;
  75. char t3 = t2[it1];
  76. t2[it1] = t2[t1];
  77. t2[t1] = t3;
  78. int t4 = tn1 + 1;
  79. if((i == 0 && (it1 == 2 || it1 == 5))||(i == 1 && (it1 == 3 || it1 == 6)))
  80. continue;
  81. if(judge(t1))
  82. {
  83. if(M1[t2])
  84. continue;
  85. M1[t2] = tn1 + 1;
  86. if(M2[t2])
  87. return M1[t2] + M2[t2];
  88. nex1.first = t2;
  89. nex1.second = t4;
  90. Q1.push(nex1);
  91. }
  92. }
  93. }
  94. return -1;
  95. }
  96. int main()
  97. {
  98. int ans;
  99. cin >> s >> e;
  100. ans = bfs();
  101. if(ans == -1)
  102. cout << "-1" << endl;
  103. else
  104. cout << ans << endl;
  105. return 0;
  106. }

2019.3.23

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注