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


我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。


我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
题解:
九宫重排,迷宫问题的最短路问题都是可以用广度优先搜索算法来解决的,具体就是以当前状态为起点,遍历其周围的各个结点,把它们分别放在队列中,在对当前状态处理完之后,就可以进行当前状态的迭代了
注意,上面的"状态"必须的完整的,因为他周围的每个后继状态都需要当前的完整信息,这样才能进行下一次迭代,进行完备的广度搜索.
对于此题,具体就是:当前矩阵,步数,空格位置.
代码示例:
1 #include<iostream>
2 #include<queue>
3 using namespace std;
4 int dir[]={0,1,0,-1,0};//方向
5 int jc[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};//0-9的阶乘
6 bool visit_kt[1000000]={false};//康托visit判断
7 struct node
8 {//状态
9 char str[10];
10 int step;
11 int spx,spy;
12 };
13 bool check(node &start,node &end)
14 {//检测是否成功
15 for(int j=0;j<9;j++)
16 if(start.str[j]!=end.str[j]) return false;
17 return true;
18 }
19 void init(node &start,node &end)
20 {
21 //初始态,终态的初始化
22 for(int j=0;j<9;j++)
23 {
24 scanf("%c",&start.str[j]);
25 if(start.str[j]=='.')
26 {
27 start.spx=j/3+1;
28 start.spy=j%3;
29 start.step=0;
30 }
31 }
32 getchar();
33 for(int j=0;j<9;j++)
34 {
35 scanf("%c",&end.str[j]);
36 if(end.str[j]=='.')
37 {
38 end.spx=j/3+1; end.spy=j%3;
39 end.step=0;
40 }
41 }
42 }
43 void print(string a)
44 {//打印,状态的矩阵
45 cout<<"-------------"<<endl;
46 for(int i=0;i<3;i++)
47 {
48 for(int j=0;j<3;j++)
49 {
50 int index=i*3+j;
51 cout<<a[index]<<" ";
52 }
53 cout<<"-----------"<<endl;
54 }
55 }
56 int por(string a)//康托展开
57 {
58 int size = 0;
59 for (int i = 0; i < 9; i++) {
60 int len = 0;
61 for (int j = i + 1; j < 9; j++) {
62 if (a[i] > a[j])len++;
63 }
64 size += len * jc[9-i-1];
65 }
66 return size;
67 }
68
69 int main()
70 {
71 queue<node> q;
72 node start,end;
73 int count=0;
74 init(start,end);
75 q.push(start);
76 if(check(start,end))
77 {//防止数据太狗
78 cout<<0<<endl; return 0;
79 }
80 while(!q.empty())
81 {
82 node local=q.front();
83 q.pop();
84 for(int i=0;i<4;i++)
85 {
86 node temp=local;
87 int x=local.spx,y=local.spy;
88 x=x+dir[i]; y=y+dir[i+1];//后继空格的位置
89 if(x<0||x>2||y<0||y>2) continue;
90 temp.str[3*(local.spx)+local.spy]=temp.str[3*(x)+y];
91 temp.str[3*(x)+y]='.';
92 temp.spx=x; temp.spy=y;//空格
93 /*以上都是为了得出temp结点(状态),*/
94 int index=por(temp.str);//康托值
95 if(!visit_kt[index])
96 {//
97 if(check(temp,end))
98 {//判断是否成功
99 cout<<temp.step<<endl;
100 cout<<temp.str<<endl;
101 return 0;
102 }
103 visit_kt[index]=true;
104 temp.step++;
105 q.push(temp);//入队
106 if(count<10)//test it
107 print(temp.str);
108 count++;
109 }
110 }
111 }
112 cout<<"no"<<endl;
113 return 0;
114 }
来源:https://www.cnblogs.com/zww-kjj/p/12235291.html