1. 程式人生 > >P1379 八數碼難題

P1379 八數碼難題

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