九宫重排

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

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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值