九宫重排

来源:互联网 发布:井下作业实用数据手册 编辑:程序博客网 时间:2024/04/27 13:55

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

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

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;}

如有不当之处欢迎指出!

0 0
原创粉丝点击