首页 > 代码库 > 八数码难题

八数码难题

思考还是不周到 没有考虑到0的那种情况
谢谢出数据的人(和善的微笑)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<string>
 7 #define N 600000
 8 using namespace std;
 9 int fac[9]={1,1,2,6,24,120,720,5040,40320};
10 int st[N][9],z[9],d[N],zz,dis[N],fa[N];
11 int y[5]={0,3,-3,1,-1};
12 int vis[N];
13 int kt(int s[]){
14     int t;
15     int sum=0;
16     for (int i=0;i<=8;++i){
17         t=0;
18         for (int j=i+1;j<=8;++j)
19             if (s[j]<s[i]) t++;
20         sum+=t*fac[8-i];
21     }
22     return sum;
23 }
24 void nkt(int x);
25 int bfs(){
26     int h=0,t=1;
27     while (h<t){
28         h++;
29         vis[d[h]]=1;
30         if (d[h]==zz) return d[h];
31         int x;
32         for (x=0;x<=8;++x) if (st[h][x]==0) break;
33         for (int i=1;i<=4;++i){
34             if (0<=x+y[i]&&x+y[i]<=8){
35                 if ((x==2||x==5)&&y[i]==1) continue;
36                 if ((x==3||x==6)&&y[i]==-1) continue;
37                 int l=st[h][x+y[i]];
38                 t++;
39                 for (int j=0;j<=8;++j) st[t][j]=st[h][j];
40                 st[t][x]=l,st[t][x+y[i]]=0;
41                 d[t]=kt(st[t]);
42                 if (vis[d[t]]) t--;
43                 else{
44                     dis[d[t]]=dis[d[h]]+1;
45                     fa[d[t]]=d[h];}
46             }
47         }
48     }
49     return 0;
50 }
51 void nkt(int x){
52     bool viss[10]={0};
53     int t;
54     for (int i=0;i<=8;++i){
55         t=x/fac[8-i];
56         x%=fac[8-i];
57         int j;
58         for (j=0;j<=8;++j)
59             if (!viss[j]){
60                 if (!t) break;
61                 t--;
62             }
63         cout<<j;
64         viss[j]=1;
65     }
66 }
67 void pr(int x){
68     if (!fa[x]) return ;
69     pr(fa[x]);
70     nkt(x);
71     cout<<endl;
72 }
73 int main(){
74     //freopen ("bsm.in","r",stdin);
75     //freopen ("bsm.out","w",stdout);
76     for (int i=0;i<=8;++i) scanf ("%d",&st[1][i]);
77     for (int i=0;i<=8;++i) scanf ("%d",&z[i]);
78     d[1]=kt(st[1]);
79     vis[d[1]]=1;
80     zz=kt(z);
81     if (d[1]==zz){
82         cout<<0;
83         return 0;
84     }
85     int num=bfs();
86     if (num){
87          cout<<dis[num]<<endl;
88          nkt(d[1]);
89          cout<<endl;
90          pr(num);
91     }
92     else cout<<-1;
93     return 0;
94   }

为了学康托和逆康托强行都用了qaq
然而似乎只用康托?
这样使得我的时间非常不优秀 = A =
关于康托
就是求一个序列在原本这么多数的全排列中的序号
这样就能保证八数码移动到的每个序列都有独有的值
方便判重
应该是比stl快一点的但我似乎打丑了qwq
具体实现可以百度呀OvO
其实我是仗着上次看了半个小时nextpermutation所以压根没仔细算qwq

八数码难题