vijos 1360 八数码问题 - 启发式搜索
背景
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
格式
输入格式
输入初试状态,一行九个数字,空格用0表示
输出格式
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例1
样例输入1
283104765
样例输出1
4
这题直接广搜是可以的,不过非常地耗费内存和时间,所以这里用到了A*算法
股价函数是以它和目标节点的差作股价,不过单用股价函数是不可以的(全W的教训)
还要有现在所走的步数,把两者相加,得到优先级,优先级越低的越先搜索
priority = h(x) + step;
如何说明这个的正确性呢?假设有有一个节点x,h(x) = 2,如果它不能尽快地达到目标状态,以至于优先级超过排在第二的节点y,那么y就会被取出队列进行更新。要使股价函数h(x)的值要减少1(当h(x)=2时是特例),至少需要移动一步,这样就能够保证第一次搜到目标节点一定步数是最少的。如果还不明白,就这么再说一下个人的理解,(h[x]+step)是按照最优的情况移动一次h(x)就减少了1的步数加1进行预算,如果最优的情况下x都不比y优,那么就应当先搜索y。
Code:
/**
* Vijos.org
* Problem#1360
* Accepted
* Time:76ms
* Memory:996k
**/
#include<iostream>
#include<queue>
#include<set>
using namespace std;
typedef bool boolean;
typedef class MyData{
public:
char datas[][];
void in(){
for(int i=;i<=;i++){
for(int j=;j<=;j++){
cin>>datas[i][j];
}
}
}
MyData(){}
MyData(string str){
for(int i=;i<=;i++){
this->datas[i/][i%] = str[i];
}
}
boolean equals(MyData another){
for(int i=;i<=;i++){
for(int j=;j<=;j++){
if(this->datas[i][j]!=another.datas[i][j]) return false;
}
}
return true;
}
boolean operator <(MyData another) const{ for(int i=;i<=;i++){
for(int j=;j<=;j++){
if(this->datas[i][j]!=another.datas[i][j]) return this->datas[i][j]<another.datas[i][j];
}
}
return false;
}
}MyData;
typedef class Node{
public:
int pro;
int step;
MyData d;
int x;
int y;
Node():pro(),step(){}
Node(int pro,int step,MyData d):pro(pro),step(step),d(d){}
boolean operator <(Node another) const{
return this->pro>another.pro;
}
}Node;
int fstep = -;
priority_queue<Node> que;
set<MyData> s;
int m[][]={{,,-,},{,,,-}};
MyData aim("");
int h(Node node){
int result = ;
for(int i=;i<=;i++){
for(int j=;j<=;j++){
if(node.d.datas[i][j]!=aim.datas[i][j]) result++;
}
}
return result;
}
void swap(Node* node,int x,int y,int x1,int y1){
char a=node->d.datas[x][y];
node->d.datas[x][y]=node->d.datas[x1][y1];
node->d.datas[x1][y1]=a;
}
void find(Node start){
start.step = ;
start.pro=h(start);
for(int a=;a<=;a++){
for(int b=;b<=;b++){
if(start.d.datas[a][b]==''){
start.x=a;
start.y=b;
break;
}
}
}
s.insert(start.d);
que.push(start);
while(!que.empty()){
Node e = que.top();
que.pop();
if(fstep != -&&e.step >= fstep) continue;
if(e.d.equals(aim)) fstep = e.step;
for(int i=;i<=;i++){
Node eu = e;
int x=eu.x,y=eu.y;
eu.x += m[][i];
eu.y += m[][i];
if(eu.x>=&&eu.x<=&&eu.y>=&&eu.y<=){
swap(&eu,x,y,eu.x,eu.y);
eu.pro = h(eu) + eu.step + ;
eu.step++;
if(!s.count(eu.d)){
s.insert(eu.d);
que.push(eu);
}
}
}
}
}
int main(){
MyData d;
d.in();
find(Node(,,d));
cout<<fstep;
return ;
}
vijos 1360 八数码问题 - 启发式搜索的更多相关文章
- Vijos 1360 - 八数码问题 - [A*]
题目链接:https://vijos.org/p/1360 优先队列BFS: 这个八数码问题本身其实是之前人工智能实验课的作业…… 首先,如果不带估价函数,直接用优先队列BFS,肯定也是能得到正确结果 ...
- 【宽搜】Vijos P1360 八数码问题
题目链接: https://vijos.org/p/1360 题目大意: 3x3格子上放1~8数字,一个空位,每次空位可与上下左右交换,固定终止布局,求输入的起始布局需要几步到达终止布局 题目思路: ...
- luoguP1379 八数码难题[启发式搜索]
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- c++ 启发式搜索解决八数码问题
本文对八数码问题 启发式搜索 (C++)做了一点点修改 //fn=gn+hn #include<iostream> #include<queue> #include<st ...
- A*八数码
帮同学写的八数码,启发式搜索 创建两个表open,close,分别用的stl中的优先队列priority_queue和map,好久没写过代码了,bug调了半天 #include <iostrea ...
- 双向广搜+hash+康托展开 codevs 1225 八数码难题
codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启 ...
- Codevs 1225 八数码难题
1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的 ...
- 八数码问题 Eight Digital Problem
八数码问题 利用启发式搜索,找出以下问题的最优解. #include <iostream> #include <vector> #include <algorithm&g ...
- 【洛谷P1379】八数码难题(广搜、A*)
八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...
随机推荐
- git 出现 refusing to merge unrelated histories 解决
如果出现refusing to merge unrelated histories,使用以下方法即可 git pull origin master --allow-unrelated-historie ...
- OKEX API
本文介绍OKEX API Rest 开始使用 REST,即Representational State Transfer的缩写,是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方 ...
- KVM--安装及初步使用
KVM是Kernel-based Virtual Machine的简称,是一个开源的虚拟化模块,今天我将在CentOS7的操作系统上安装KVM,以下是我的安装步骤. 一.环境信息 系统: CentOS ...
- 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp
正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...
- 洛谷P4289 移动玩具 HAOI2008 搜索+状压
正解:状压 解题报告: 先,放下传送门QwQ 说真的我jio得这题不管是思路还是实现上,都还是有一定难度的?然后就看到神仙hl博客里一句"太水了不讲了"就过掉了,,,好的趴太强辽Q ...
- Elasticsearch教程-从入门到精通(转)
原文:http://mageedu.blog.51cto.com/4265610/1714522?utm_source=tuicool&utm_medium=referral 各位运维同行朋友 ...
- 共享访问在.NET中的编程实现
转载:http://blog.csdn.net/zhzuo/article/details/1732937 共享访问在.NET中的编程实现 发布日期:2007-08-08 | 更新日期:2009-03 ...
- 十天精通CSS3(7)
:enabled选择器 在Web的表单中,有些表单元素有可用(“:enabled”)和不可用(“:disabled”)状态,比如输入框,密码框,复选框等.在默认情况之下,这些表单元素都处在可用状态.那 ...
- [PAT]A+B Format[简单]
1001 A+B Format (20)(20 分) Calculate a + b and output the sum in standard format -- that is, the dig ...
- apply、map、applymap、Dropna
DataFrame常用易混淆方法 apply && map && applymap 1.apply():作用在一维的向量上时,可以使用apply来完成,如下所示 2.m ...