1. 程式人生 > >luoguP1379 八數碼難題[IDA*]

luoguP1379 八數碼難題[IDA*]

-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,int
g){ 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*]