luoguP1379 八數碼難題[IDA*]
阿新 • • 發佈:2017-05-14
-i 感謝 ida har 初始 text can int 夢裏
總是在夢裏我看到你無助的雙眼 我的心又一次被喚醒
題目描述
在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始布局(初始狀態)和目標布局(為了使題目簡單,設目標狀態為123804765),找到一種最少步驟的移動方法,實現從初始布局到目標布局的轉變。
輸入輸出格式
輸入格式:
輸入初試狀態,一行九個數字,空格用0表示
輸出格式:
只有一行,該行只有一個數字,表示從初始狀態到目標狀態需要的最少移動次數(測試數據中無特殊無法到達目標狀態數據)
輸入輸出樣例
輸入樣例#1:283104765輸出樣例#1:
4
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 using namespace std; 6 7 //目標態 8 int fin[9][2]={{1,1},{0,0},{0,1},{0,2},{1,2},{2,2},{2,1},{2,0},{1,0}}; 9 10 struct State{ 11 int a[3][3]; 12 }; 13 14 int lim=0,ok;15 16 //計算f(n)函數 17 int H(const State &st){ 18 int ret=0; 19 for(int i=0;i<3;i++) 20 for(int j=0;j<3;j++){ 21 int t=st.a[i][j]; 22 if(t) ret+=abs(fin[t][0]-i)+abs(fin[t][1]-j); 23 } 24 return ret; 25 } 26 27 void dfs(State st,intg){ 28 int h=H(st); 29 if(ok||g+h>lim) 30 return; 31 if(!h){ 32 ok=1; 33 return; 34 } 35 int x,y; 36 for(int i=0;i<3;i++) 37 for(int j=0;j<3;j++) 38 if(!st.a[i][j]){ 39 x=i,y=j; 40 break; 41 } 42 if(x>0){ 43 swap(st.a[x][y],st.a[x-1][y]); 44 dfs(st,g+1); 45 swap(st.a[x][y],st.a[x-1][y]); 46 } 47 if(x<2){ 48 swap(st.a[x][y],st.a[x+1][y]); 49 dfs(st,g+1); 50 swap(st.a[x][y],st.a[x+1][y]); 51 } 52 if(y>0){ 53 swap(st.a[x][y],st.a[x][y-1]); 54 dfs(st,g+1); 55 swap(st.a[x][y],st.a[x][y-1]); 56 } 57 if(y<2){ 58 swap(st.a[x][y],st.a[x][y+1]); 59 dfs(st,g+1); 60 swap(st.a[x][y],st.a[x][y+1]); 61 } 62 } 63 64 int main(){ 65 State st; 66 char ch[10]; 67 scanf("%s",ch); 68 for(int i=0;i<3;i++) 69 for(int j=0;j<3;j++) 70 st.a[i][j]=ch[i*3+j]-‘0‘; 71 while(++lim){ 72 dfs(st,0); 73 if(ok) break; 74 } 75 printf("%d\n",lim); 76 return 0; 77 }
在寫盲目bfs 1590ms 後很久才用的IDA*解法
感謝will7101在luogu上題解給本蒟蒻此題IDA*稍短代碼的啟蒙
終於學會了計算h(n) QwQ
總是在夢裏我看到你無助的雙眼 我的心又一次被喚醒
luoguP1379 八數碼難題[IDA*]