- P1379 八数码难题
- 题意:在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
- 思路:迭代加深就是每次限制搜索深度 ,这样可以在整个搜索树深度很大而答案深度又很小的情况下大大提高效率
- 使k从1开始不断加深枚举 ,作为最大步数进行迭代加深搜索判断
- A*估价函数设置为 :
- 当前状态还有多少个位置与目标状态不对应,若当前步数+估价函数值>枚举的最大步数 则直接返回
- 最优性剪枝:
- 显然当前枚举下一个状态时如果回到上一个状态肯定不是最优,
- 所以我们在枚举下一状态时加入对这种情况的判断即 pre + i==3时 正好对应着回上一个状态,进行剪枝。
-
#include<bits/stdc++.h> using namespace std; int ans[5][5]= {{0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5}}; int cur[5][5],k,flag,sx,sy; char str[15]; int to[5][4]= {{1,0},{0,-1},{0,1},{-1,0}}; bool check() { for(int i=1; i<=3; i++) for(int j=1; j<=3; j++) if(ans[i][j]!=cur[i][j]) return 0; return 1; } bool ok(int step) { int cnt=0; for(int i=1; i<=3; i++) for(int j=1; j<=3; j++) if(ans[i][j]!=cur[i][j]) if(++cnt+step>k)return 0; return 1; } void dfs(int id,int x,int y,int pre) { if(id==k) { if(check())flag=1; return; } if(flag)return; for(int i=0; i<4; i++) { int tx=x+to[i][0]; int ty=y+to[i][1]; if(tx<1||ty<1||ty>3||tx>3||pre+i==3)continue; swap(cur[x][y],cur[tx][ty]); if(!flag&&ok(id)) dfs(id+1,tx,ty,i); swap(cur[tx][ty],cur[x][y]); } } int main() { scanf("%s",str); for(int i=0; i<9; i++) { cur[i/3+1][i%3+1]=str[i]-'0'; if(str[i]-'0'==0)sx=i/3+1,sy=i%3+1; } if(check())printf("0\n"); else { while(++k) { dfs(0,sx,sy,-1); if(flag) { printf("%d\n",k); break; } } } return 0; }
P1379 八数码难题-启发式搜索
猜你喜欢
转载自blog.csdn.net/BePosit/article/details/85208216
今日推荐
周排行