HDU 1043 Eight(反向BFS+打表+康托展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043

题目大意:传统八数码问题

解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各个状态记录下来,因为数字太大所以用康托展开将数字离散化。

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 using namespace std;
 8 typedef long long ll; 
 9 const int N=4e5+5;
10 
11 int vis[N];
12 string path[N];
13 char map[15];
14 char index[5]="udrl";//因为是逆向所以方向要反一下 
15 int d[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
16 int fac[15]={1,1,2,6,24,120,720,5040,40320};
17 
18 struct node{
19     char num[10];
20     int pos;
21     string path;
22 }pre,now;
23 
24 //求康托展开值 
25 int cantor(char s[]){
26     int sum=0;
27     int n=strlen(s);
28     for(int i=0;i<n;i++){
29         int cnt=0;
30         for(int j=i+1;j<n;j++){
31             if(s[i]>s[j])
32                 cnt++;
33         }
34         sum+=cnt*fac[n-i-1];
35     }
36     return sum+1;
37 }
38 //从12345678x逆向BFS打表 
39 void bfs(){
40     queue<node>q;
41     now.pos=8;
42     for(int i=0;i<8;i++)
43         now.num[i]=i+1+'0';
44     now.num[8]='0';
45     now.num[9]='';
46     q.push(now);
47     while(!q.empty()){
48         pre=q.front();
49         q.pop();
50         int pos=pre.pos;
51         //转换成二维坐标 
52         int x=pos/3;
53         int y=pos%3;    
54         for(int i=0;i<4;i++){
55             int xx=x+d[i][0];
56             int yy=y+d[i][1];
57             if(xx<0||yy<0||xx>2||yy>2)
58                 continue;
59             //转换回一维坐标 
60             int new_pos=xx*3+yy;
61             now=pre;
62             swap(now.num[pos],now.num[new_pos]);
63             int tmp=cantor(now.num);
64             if(!vis[tmp]){
65                 now.pos=new_pos;
66                 //index[i]要加在前面,反的嘛 
67                 now.path=index[i]+now.path;
68                 vis[tmp]=1;
69                 //存储路径 
70                 path[tmp]=now.path;
71                 q.push(now);
72             }
73         }
74     }
75 }
76 
77 int main(){
78     char c;
79     bfs();
80     while(cin>>c){
81         //x转换成0便于康托展开 
82         if(c=='x')
83             map[0]='0';
84         else
85             map[0]=c;
86         for(int i=1;i<9;i++){
87             cin>>map[i];
88             if(map[i]=='x')
89                 map[i]='0';
90         }
91         int aim=cantor(map);
92         if(vis[aim])
93             cout<<path[aim]<<endl;
94         else
95             cout<<"unsolvable"<<endl;
96     }
97 }
原文地址:https://www.cnblogs.com/fu3638/p/7529246.html