P1379 八數碼難題
阿新 • • 發佈:2019-02-13
bfs,像輸入一樣我們用一個數來表示狀態,因為不能開一個9位的陣列,又因為如果數的八位確定,那麼最後一位就能確定,所以我們可以開一個8位的陣列來記錄這個狀態是否進過隊。
重點是將0與其它位轉換,基於九宮格的特點,我們只能將0與和它相距 1 -1 3 -3 位的數字交換,下面是數位交換的原則:
1. 要得到第x位前面的部分:/10^x
2. 要得到第x位後面的部分:%10^(x-1)
3. 要得到第x位的部分:/10^(x-1) %10
還需要注意一個問題(一開始自己忽略掉了),就是0在九宮格的最右邊是不能與下一位的數交換,同理在最左邊時,也不能與上一位的數字交換。
#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;
}