P1379 八数码难题

luogu 传送门ios

bfs,像输入同样咱们用一个数来表示状态,由于不能开一个9位的数组,又由于若是数的八位肯定,那么最后一位就能肯定,因此咱们能够开一个8位的数组来记录这个状态是否进过队。web

重点是将0与其它位转换,基于九宫格的特色,咱们只能将0与和它相距 1 -1 3 -3 位的数字交换,下面是数位交换的原则:
1. 要获得第x位前面的部分:/10^x
2. 要获得第x位后面的部分:%10^(x-1)
3. 要获得第x位的部分:/10^(x-1) %10数组

还须要注意一个问题(一开始本身忽略掉了),就是0在九宫格的最右边是不能与下一位的数交换,同理在最左边时,也不能与上一位的数字交换。svg

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define T 123804765
using namespace std;
int ans,s;
bool f[88888888];
int MOD[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};//MOD[i]是10^i 
struct H{
    int x,step;
};
int mov[]={-1,1,-3,3};//0的移动方向:左右上下 
int bfs()
{
    queue <H> q;
    H k;
    k.x=s;k.step=0;
    f[s/10]=1;
    q.push(k);
    while(!q.empty())
    {
        k=q.front();
        q.pop();
        if(k.x==T) return k.step;
        int j=1,p=k.x;
        while(p%10)
        {j++;p/=10;}//第几位是0 
        for(int i=0;i<4;i++)
        {
            int t=j,tt=j+mov[i];//0要交换到的位

            if(t%3==0&&mov[i]==1) continue;
            if(t%3==1&&mov[i]==-1) continue;

            if(tt>=1&&tt<=9)
            {
                if(t<tt) swap(t,tt);
                int x;
                x=k.x/MOD[t]*MOD[t]+k.x%MOD[tt-1];
                int x1=k.x/MOD[t-1]%10;
                int x2=k.x/MOD[tt-1]%10;
                int x3=((k.x/MOD[tt]*MOD[tt])%MOD[t-1]);
                x+=x3+x1*MOD[tt-1]+x2*MOD[t-1];
                if(!f[x/10])
                {
                    H l;
                    if(x==T) return k.step+1;
                    l.x=x,l.step=k.step+1;
                    q.push(l);f[x/10]=1;
                }
            }
        }

    }
}
int main()
{
    scanf("%d",&s);
    ans=bfs();
    printf("%d",ans);
    return 0;
}