洛谷 P1379 八數碼難題
阿新 • • 發佈:2020-10-21
洛谷 P1379 八數碼難題
JDOJ 1461: VIJOS-P1360 八數碼問題
Description
在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始佈局(初始狀態)和目標佈局(為了使題目簡單,設目標狀態為123804765),找到一種最少步驟的移動方法,實現從初始佈局到目標佈局的轉變。
Input
輸入初試狀態,一行九個數字,空格用0表示
Output
只有一行,該行只有一個數字,表示從初始狀態到目標狀態需要的最少移動次數(測試資料中無特殊無法到達目標狀態資料)
Sample Input
283104765
Sample Output
4
最優解宣告:
題解:
雙向BFS+map去重。
這裡採用了把序列化成矩陣的模式,方便繼續往下搜。
程式碼:
#include<cstdio> #include<algorithm> #include<cstdlib> #include<map> #include<queue> #define ll long long int using namespace std; int n,g=123804765; int a[4][4],fx,fy,nx,ny; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; queue<int> q; map<int,int> v,ans; int main() { scanf("%d",&n); if(n==g) { printf("0"); exit(0); } q.push(n); q.push(g); ans[n]=0; ans[g]=1; v[g]=2; v[n]=1; while(!q.empty()) { ll now,cur=q.front(); q.pop(); now=cur; for(int i=3;i>=1;i--) for(int j=3;j>=1;j--) { a[i][j]=now%10,now/=10; if(a[i][j]==0) fx=i,fy=j; } for(int i=0;i<4;i++) { nx=fx+dx[i]; ny=fy+dy[i]; if(nx<1 || nx>3 || ny<1 || ny>3) continue; swap(a[fx][fy],a[nx][ny]); now=0; for(int p=1;p<=3;p++) for(int j=1;j<=3;j++) now=now*10+a[p][j]; if(v[now]==v[cur]) { swap(a[fx][fy],a[nx][ny]); continue; } if(v[now]+v[cur]==3) { printf("%d",ans[cur]+ans[now]); exit(0); } ans[now]=ans[cur]+1; v[now]=v[cur]; q.push(now); swap(a[fx][fy],a[nx][ny]); } } }