题目链接:P1379 八数码难题
题目大意: 要求最少步骤的移动方法,实现从初始布局到目标布局的转变。
解题思路: 这道题目要用到搜索中比较难的搜索方法—迭代加深的A*算法。所谓迭代加深就是每次限制搜索深度, 这样可以在整个搜索树深度很大而答案深度又很小的情况下大大提高效率。使maxdep从1开始不断加深枚举, 作为最大步数进行迭代加深搜索判断,而对于不用移动的情况可以一开始直接特判。在这里我们的A*估价函数设置为当前状态还有多少个位置与目标状态不对应。这只是我们预估现在的状态到目标状态的距离,我们预想的距离一定是比实际距离短,或者刚好等于实际距离的值(因为这是我们每一步都走正确的预估步数)。若当前步数+估价函数值>枚举的最大步数 则直接返回(现在花费的步数+预估的步数>=现在花费的步数+实际花费的步数,也就是超出了最大的步数)。当然这只是基本思路,搜索还可以有很大优化。我们在搜索中再加入最优性剪枝, 显然当前枚举下一个状态时如果回到上一个状态肯定不是最优, 所以我们在枚举下一状态时加入对这种情况的判断。将状态数组对称化可以实现这一操作:

const int dx[] = { 0,1,-1,0 };
const int dy[] = { 1,0,0,-1 };

索引0和3对称,索引1和2对称。

if (i == 3 - pre||!isValid(tx,ty)) {continue;}

i是现在的状态,pre是上一个状态,如果i+pre==3,则说明我们枚举下一个状态时回到了上一个状态。(比如说上一次我向右走,这一次向左走,就回到了出发点,肯定不是最优解)。
参考文章: A*算法和启发性搜索
代码:

#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 5000;
const int goal[4][4] =
{ {0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5} };//目标状态
const int dx[] = { 0,1,-1,0 };
const int dy[] = { 1,0,0,-1 };
int map[maxn][maxn],stx,sty,maxdep;
bool flag = 0;
char s[maxn];
inline int h() {int cnt = 0;for (int i = 1; i <=3; i++) {for (int j = 1; j <=3; j++) {if (map[i][j] != goal[i][j]) {cnt++;}}}return cnt;//当前状态还有多少个位置与目标状态不对应
}
bool isValid(int x, int y) {if (x < 1 || x > 3 || y < 1 || y > 3) {return false;}return true;
}
void DFS(int dep,int maxdep, int pre,int x,int y ) {if (dep == maxdep) {if (h() == 0) {//说明到达的目标状态flag = 1;return;}}if (flag) {return;}for (int i = 0; i < 4; i++) {int tx = x + dx[i];int ty = y + dy[i];if (i == 3 - pre||!isValid(tx,ty)) {continue;//剪枝}swap(map[x][y], map[tx][ty]);//交换0和map[tx][ty]if (h() + dep <= maxdep) {DFS(dep + 1, maxdep, i, tx, ty);}//只有当前步数+估价函数值<=最大的步数才去递归swap(map[x][y], map[tx][ty]);}
}
int main() {cin >> s;for (int i = 0; i < 9; i++) {map[(i / 3)+1][(i % 3)+1] = s[i]-'0';if (s[i] == '0') {stx = i / 3+1;sty = i % 3+1;}}if (h() == 0) {cout << 0 << endl;return 0;}while (++maxdep) {DFS(0,maxdep, -1, stx, sty);if (flag) {break;}}cout << maxdep << endl;
}

洛谷—P1379 八数码难题相关推荐

  1. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

  2. [洛谷] P1379 八数码难题( 提高+/省选- )

    八数码 1.题目 2.分析 3.代码 1. bfs (+queue) + unordered_map 重点分析 2.双向bfs (适用于知道起始状态的情况) 思路分析 3.双向bfs优化 思路 4.总 ...

  3. IDA*-洛谷P1379 八数码难题

    https://daniu.luogu.org/problem/show?pid=1379 省选的收获 暗金 学会了A*啦啦啦: 我在第一天学了A*; 然后回家颓废之余思考思考: 又问了van爷一些小 ...

  4. 洛谷 1379 八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...

  5. P1379 八数码难题 题解(双向宽搜)

    博客园同步 原题链接 简要题意: 给定一个 3 × 3 3 \times 3 3×3 的矩阵,每次可以把空格旁边(四方向)的一个位置移到空格上.求到目标状态的最小步数. 前置知识: 单向宽搜的写法 O ...

  6. 【洛谷】P1379 八数码难题

    题目地址: https://www.luogu.com.cn/problem/P1379 题目描述: 在3×33×33×3的棋盘上,摆有八个棋子,每个棋子上标有111至888的某一数字.棋盘中留有一个 ...

  7. 洛谷OJ:P1379 八数码难题(双向搜索)

    思路:相信不少小伙伴上来就是暴力DFS,但是拿到题之后我们不妨想一想如果纯DFS爆搜下来会产生多少种状态,这样的方法是否是最优的? 这里选择使用一种称之为双向搜索的方法(通过知乎学到的,放出来shar ...

  8. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

  9. 【codevs1225】八数码难题,如何精确地搜索

    1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道 ...

最新文章

  1. C#正则表达式编程(三):Match类和Group类用法
  2. 理解并取证:DLS网络架构和PPPOE数据帧
  3. HTML5事件——contextmenu 隐藏鼠标右键菜单
  4. java中string 和stringbuffer的区别_Java中的String,StringBuilder,StringBuffer三者的区别...
  5. webUI自动化二-获取元素信息相关方法
  6. 物联网卡云平台如何分析信息数据
  7. 《实用机器学习》中的一些拓展问题
  8. Jquery 数组操作(转)
  9. loadrunner11下载
  10. 经典卷积神经网络---VGG16网络
  11. 交换机解决电脑IP地址冲突
  12. 黑马程序员培训没兄弟会高级
  13. ELMO驱动器与nanotec电机通过compser软件调试PID参数的方式
  14. 小红书种草营销的本质是什么?如何投入更有效?
  15. [JZOJ3461] 小麦亩产一千八
  16. 贪心(百练1328):安放雷达(区间问题)
  17. 读“技术的执念”有感
  18. Linux服务器之Samba匿名访问配置
  19. 品牌如何开展饥饿营销?
  20. DB2相关数据库命令

热门文章

  1. 第十五届“中国电机工程学会杯”全国大学生电工数学建模竞赛
  2. 【代码质量】C/C++静态检测/静态分析|TscanCode|cppcheck
  3. python长沙培训学校
  4. 近乎完美的行走于虚拟世界?Pathbender推出跑步机StriderVR
  5. 可编程网卡芯片在滴滴云网络的应用实践
  6. 微信:如何查询自己名下已实名认证绑定的几个微信账户?
  7. 【数据结构/C语言版】【图】拓扑排序
  8. con和com开头单词规律_背单词其实有诀窍!孩子掌握这15条自然拼读规则,效果事半功倍!...
  9. 家庭组网常见的几种误区
  10. Python将形如”\xe4...的十六进制编码字符串恢复为中文