HDU1043

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

解题思路:反向BFS + 康托展开

  从目标状态 “1 2 3 4 5 6 7 8 x" 反过来做BFS,记录其可能访问到的状态,用康托展开为每一个状态 ”编码“(我不知道怎么说比较合适,其实就是找一个数来代表这个状态),用 fa 来记录每个状态的上一个状态,方便读取转移路径。思路不难,实现难!

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=500000;
 7 const int cx[4]={0,0,1,-1},cy[4]={1,-1,0,0};
 8 const int factor[]={ 1,1,2,6,24,120,720,5040,40320,362880 };
 9 char go[6]="lrud";
10 struct state{
11     int s[10];
12     int fa,pos,cnum;
13     char nowc;
14 }ku[maxn];
15 int vis[maxn];
16 char ans[1000];
17 int cantor(int x[9]){
18     int sum=0,s;
19     for(int i=0;i<9;i++){
20         s=0;
21         for(int j=i+1;j<9;j++){
22             if(x[j]<x[i])   s++;
23         }
24         sum+=s*factor[9-i-1];
25     }
26     return sum+1;
27 }
28 void init(){
29     memset(vis,0,sizeof(vis));
30     for(int i=0;i<8;i++)    ku[0].s[i]=i+1;
31     ku[0].s[8]=0;
32     ku[0].fa=-1,ku[0].pos=8;
33     ku[0].cnum=cantor(ku[0].s);
34     int head=0,ending=1;
35     while(head<ending){
36         state now=ku[head];
37         int x=now.pos/3,y=now.pos%3;
38         for(int i=0;i<4;i++){
39             state next;
40             int dx=x+cx[i],dy=y+cy[i];
41             if(dx<0||dx>=3||dy<0||dy>=3)    continue;
42             next.pos=dx*3+dy;
43             for(int j=0;j<9;j++)    next.s[j]=now.s[j];
44             swap(next.s[next.pos],next.s[now.pos]);
45             next.cnum=cantor(next.s);
46             if(!vis[next.cnum]){
47                 next.fa=head;
48                 next.nowc=go[i];
49                 ku[ending]=next;
50                 vis[next.cnum]=ending;
51                 ending++;
52             }
53         }
54         head++;
55     }
56 }
57 void find_root(int t){
58     int ind=0;
59     t=vis[t];
60     for(;ku[t].fa!=-1;t=ku[t].fa,ind++)
61         ans[ind]=ku[t].nowc;
62 }
63 int main()
64 {
65     init();
66     char input[30];
67     int ins[9];
68     while(gets(input)){
69         int ind=0,l=strlen(input);
70         for(int i=0;i<l;i++){
71             if(input[i]=='x')   ins[ind++]=0;
72             else if(input[i]>'0'&&input[i]<'9')    ins[ind++]=input[i]-'0';
73         }
74         int tt=cantor(ins);
75         if(!vis[tt])    printf("unsolvable\n");
76         else{
77             memset(ans,0,sizeof(ans));
78             find_root(tt);
79             printf("%s\n",ans);
80         }
81     }
82     return 0;
83 }

 

转载于:https://www.cnblogs.com/Blogggggg/p/7474694.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值