HDU 1043 Eight(反向BFS+打表+康托展开)
Posted Yeader
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]=‘\0‘; 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 }
以上是关于HDU 1043 Eight(反向BFS+打表+康托展开)的主要内容,如果未能解决你的问题,请参考以下文章