luoguP1379 八数码难题[IDA*]
Posted ZYBGMZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP1379 八数码难题[IDA*]相关的知识,希望对你有一定的参考价值。
题目描述
在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*]的主要内容,如果未能解决你的问题,请参考以下文章