九宫重排

    xiaoxiao2025-05-27  13

    蓝桥杯的一道题。原题链接

    我用了全排列的编码优化。

    AC代码

    #include<cstdio> #include<cstring> const int maxn=400000; const int dx[]={-1,1,0,0}; const int dy[]={0,0,-1,1}; typedef int state[9]; int goal[9]; int res[maxn][9]; //存储访问过的节点 int d[maxn],fact[9]; int vis[maxn]; void init() { fact[0]=1; for(int i=1;i<9;++i) fact[i]=i*fact[i-1]; } int KT_solve(int row) //编码函数 { int code=0; for(int i=0;i<9;++i) { int cnt=0; for(int j=i+1;j<9;++j) { if(res[row][j]<res[row][i]) ++cnt; } code+=cnt*fact[8-i]; } if(vis[code]) return 0; return vis[code]=1; } int bfs() { init(); int front=1,real=2; while(front<real) { state &s=res[front]; //"引用"简化代码 if(memcmp(goal,s,sizeof(s))==0) return front; int pos; for(pos=0;pos<9;++pos) if(!s[pos]) break; int x=pos/3,y=pos%3; for(int i=0;i<4;++i) { int newx=x+dx[i],newy=y+dy[i]; int new_pos=newx*3+newy; if(newx>=0&&newy<3&&newy>=0&&newy<3) { state &t=res[real]; //向状态数组加入新的状态 memcpy(&t,&s,sizeof(s)); t[pos]=s[new_pos]; t[new_pos]=s[pos]; d[real]=d[front]+1; if(KT_solve(real)) real++; } } front++; } return 0; } int main() { memset(vis,0,sizeof(vis)); d[1]=0; char s[10]; scanf("%s",s); for(int j=0;j<9;++j) { if(s[j]=='.') res[1][j]=0; else res[1][j]=s[j]-'0'; } scanf("%s",s); for(int j=0;j<9;++j) { if(s[j]=='.') goal[j]=0; else goal[j]=s[j]-'0'; } int ans=bfs(); if(ans>0) printf("%d\n",d[ans]); else printf("-1\n"); return 0; }

    如有不当之处欢迎指出!

    转载请注明原文地址: https://ju.6miu.com/read-1299311.html
    最新回复(0)