题目描述

简单介绍一下八数码问题:
在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图:
1 2 3
4 5 6
7 8
在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字6
下移一位:
1 2 3 1 2 3
4 5 6 → 4 5
7 8 7 8 6
或者将数字 8 右移一位:
1 2 3 1 2 3
4 5 6 → 4 5 6
7 8 7 8
1~8按顺序排列的情况称为“初始状态”(如最上方图)“八数码问题”即是
求解对于任意的布局,将其移动至“初始状态”的方法。
给定一个的九宫格布局,请输出将它移动至初始状态的移动方法的步骤。

输入

输入包含多组数据,处理至文件结束。每组数据占一行,包含8个数字
和表示空位的‘x’,各项以空格分隔,表示给定的九宫格布局。
例如,对于九宫格
1 2 3
4 6
7 5 8
输入应为:1 2 3 x 4 6 7 5 8
注意,输入的数字之间可能有(不止一个?)空格。

输出

对于每组输入数据,输出一行,即移动的步骤。向上、下、左、右移动
分别用字母u、d、l、r表示;如果给定的布局无法移动至“初始 状态”,
请输出unsolvable。 如果有效的移动步骤有多种,输出任意即可。

首先先介绍一下A*算法

A*算法是 BFS 的一种改进。

定义起点 \(s\) ,终点 \(t\) 。

从起点(初始状态)开始的距离函数 \(g(x)\) 。

到终点(最终状态)的距离函数 \(h(x), h*(x)\) 。

定义每个点的估价函数 \(f(x)=g(x)+h(x)\) 。

A*算法每次从 优先队列 中取出一个 \(f\) 最小的,然后更新相邻的状态。

如果 \(h\leq h*\) ,则 A*算法能找到最优解。

上述条件下,如果 \(h\) 满足三角形不等式,则 A*算法不会将重复结点加入队列

其实…… \(h=0\) 时就是 DFS 算法, \(h=0\) 并且边权为 \(1\) 时就是 BFS

对于八数码问题(A*经典题)

\(h\) 函数可以定义为,不在应该在的位置的数字个数。

容易发现 \(h\) 满足以上两个性质,此题可以使用 A*算法求解。

代码实现:

/*
A* BFS
1)首先根据逆序对来判断是否有解
2)用状态的曼哈顿距离来作为估价函数
3)BFS {
1、预处理,需要存储步数和上一步状态
2、定义优先队列来进行搜索
3、根据答案倒推出答案
}
*/
/*---------------------------------*/
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int getval(string str) { //使用曼哈顿距离作为估价函数
int cnt = 0;
for(int i = 0; i < 9; i++) {
if(str[i] == 'x') continue;
int t = str[i] - '1';
cnt += abs(i / 3 - t / 3) + abs(i % 3 - t % 3); //计算曼哈顿距离
}
return cnt;
}
string bfs(string start) {
string end = "12345678x", opt = "urdl"; //存储目标状态和操作
int wk[4][2] = {{-1,0}, {0,1}, {1,0}, {0,-1}};
map<string, int> dist;
map<string, pair<char, string> > prev; //记录上一步操作和上一步的状态
priority_queue<pair<int, string>, vector<pair<int, string> >, greater<pair<int, string> > > heap; //小根堆作为BFS的"队列" dist[start] = 0; //初始距离为0
heap.push(make_pair(getval(start), start));
while(!heap.empty()) {
pair<int, string> t = heap.top(); heap.pop(); //取+弹
//处理当前状态
string state = t.second;
if(state == end) break;
int x, y; //存储'x'的坐标
for(int i = 0; i < 9; i++)
if(state[i] == 'x') {
x = i / 3, y = i % 3;
break;
}
string str = state; //存储当前state状态方便复位
for(int i = 0; i < 4; i++) {
int dx = x + wk[i][0], dy = y + wk[i][1];
if(dx >= 0 && dx < 3 && dy >=0 && dy < 3) {
state = str;
swap(state[x*3 + y], state[dx*3 + dy]); //四个方向交换
if(!dist.count(state) || dist[state] > dist[str] + 1) { //更新(未到过或不是最短)
dist[state] = dist[str] + 1;
prev[state] = make_pair(opt[i], str);
heap.push(make_pair(dist[state] + getval(state), state));
}
}
}
}
string ans;
while(end != start) {
ans += prev[end].first;
end = prev[end].second;
}
reverse(ans.begin(), ans.end()); //翻转得到答案
return ans;
}
int main() {
char ch;
while(cin >> ch) {
string start, judge; //judge存是否有解,start存起始状态
start += ch;
if (ch != 'x') judge += ch;
for (int i = 0; i < 8; i++) {
cin >> ch; start += ch;
if (ch != 'x') judge += ch; //judge判断是否有解
}
int cnt = 0; //存储逆序对
for (int i = 0; i < 8; i++)
for (int j = i; j < 8; j++)
if (judge[i] > judge[j]) cnt++;
if (cnt & 1) cout << "unsolvable" << endl; //逆序对为奇数则无解
else cout << bfs(start) << endl;
}
return 0;
}
//IDA*

参考:

八码数-IDA*算法https://blog.csdn.net/weixin_43769146/article/details/103102622

八码数有解条件推广https://blog.csdn.net/tiaotiaoyly/article/details/2008233#commentBox

曼哈頓距離wiki讲解https://zh.wikipedia.org/wiki/%E6%9B%BC%E5%93%88%E9%A0%93%E8%B7%9D%E9%9B%A2

八数码的八个境界 https://www.cnblogs.com/goodness/archive/2010/05/04/1727141.htmlEight HDU - 1043

Eight HDU - 1043 (反向搜索 + 康拓展开 / A* + BFS / IDA* )的更多相关文章

  1. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  2. hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】

    <题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为 ...

  3. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  4. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  5. POJ-1077 HDU 1043 HDU 3567 Eight (BFS预处理+康拓展开)

    思路: 这三个题是一个比一个令人纠结呀. POJ-1077 爆搜可以过,94ms,注意不能用map就是了. #include<iostream> #include<stack> ...

  6. POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...

  7. hdu 1043(经典搜索)

    题意: 给你一个初始的图,然后每次输入一个图,要求移动x最小的步数达到和初始图一样,输出路径 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 ...

  8. HDU 4531 bfs/康拓展开

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4531 吉哥系列故事——乾坤大挪移 Time Limit: 2000/1000 MS (Java/Othe ...

  9. HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】

    本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...

  10. hdoj1043 Eight(逆向BFS+打表+康拓展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 思路: 由于自己对康拓展开用的太少,看到这个题没想到康拓展开,最开始打算直接转换为数字,但太占内 ...

随机推荐

  1. 伯俊ERP与金蝶云星空对接集成连通应收单新增

    伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应收单新增(应收单-标准应收单(KD应收单销售退) 数据源系统:伯俊ERP 未来,伯俊科技也会砥砺前行,不断为品牌提供更全面的零售终端致胜利器.伯俊科 ...

  2. MAUI+Masa Blazor APP 各大商店新手发布指南-华为篇

    目录 前言 准备材料 一.企业认证 二.审核资料 审核注意事项 总结 前言 AppGallery Connect(简称AGC)是华为应用市场推出的应用一站式服务平台,致力于为开发者提供应用创意.开发. ...

  3. Educational Codeforces Round 26 Problem B

    B. Flag of Berland time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  4. 研发提效必备技能:手把手教你基于Docker搭建Maven私服仓库

    沉淀,成长,突破,帮助他人,成就自我. 大家好,我是冰河~~ 在研发的过程中,很多企业都会针对自身业务特点来定制研发一些工具类库,但是这些工具类库又不会对外公开,那如何在组织内部共享这些类库呢?一种很 ...

  5. 【C#】【System.Linq】一些便捷的数据处理方法(Range、Select)

    因为用习惯了Python中一些便捷的方法,随即查询C#中有没有类似的. 一.Range()方法 在Python中,range(Start,End,Step)可以直接生成一个可迭代对象,便用于需要循环多 ...

  6. TS MQTT封装

    TS MQTT封装 导入相关包 npm i mqtt npm i lodash guid 随机生成就行,具体可以参考百度或者随便生成一个随机数* 代码封装 import mqtt from 'mqtt ...

  7. TDD、BDD、ATDD都是什么、有什么区别?(下)

    在<TDD.BDD.ATDD都是什么.有什么区别?(下)>一文中,探讨了TDD.BDD和ATDD的概念.虽然TDD.BDD和ATDD都是软件开发中使用的测试方法,但它们在方法和重点上有所不 ...

  8. Kotlin委托属性(1)

    在Kotlin中,委托属性(Delegated Properties)是一种强大的语言特性,允许你将属性的 getter 和 setter 方法的实现委托给其他对象.这使得你能够通过委托来重用代码.将 ...

  9. 文心一言 VS 讯飞星火 VS chatgpt (29)-- 算法导论5.2 1题

    一.在 HIRE-ASSISTANT 中,假设应聘者以随机顺序出现,你正好雇用一次的概率是多少?正好雇用 n 次的概率是多少? 文心一言: 讯飞星火: 华为盘古: 在HIRE-ASSISTANT中,假 ...

  10. 2021-01-04:mysql里的innodb引擎的数据结构,你有看过吗?

    福哥答案2021-01-04: 面试官刚开始问我看过mysql源码没,然后问了这个问题.回答B+树,过不了面试官那关. 答案来自<MySQL技术内幕 InnoDB存储引擎 第2版>第四章, ...