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 存. 每次扩展时再转化为矩阵. ...
随机推荐
- LoadRunner-循环
Edit Runtime Settings ,设置循环次数 在Open Parameter List 里设置循环参数,比如用例为删除notice,每执行一次用例id值不同. 把id替换为参数,并在参数 ...
- QtCreator 可以通过 Clang-Tidy 和 CLazy 对你的代码进行静态检查
QtCreator 可以通过 Clang-Tidy 和 CLazy 对你的代码进行静态检查 打开你的工程,点击Analyze -> Clang-Tidy and CLazy 选择你想分析的 cp ...
- LightOj 1265 - Island of Survival(概率)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1265 题目大意:有一个生存游戏,里面t只老虎,d只鹿,还有一个人,每天都要有两个生物碰 ...
- Python3学习之路~2.1 列表、元组操作
列表 列表是我们以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作. 定义列表(list) names=['Amy','Bob','Cindy','David'] 通过下标访问列 ...
- HTML5 脚本 语言代码 URL 符号实体 ASCII码 颜色
1.HTML<noscript> 标签 <noscript> 标签提供无法使用脚本时的替代内容,比方在浏览器禁用脚本时,或浏览器不支持客户端脚本时. <noscript& ...
- ubuntu设置目录容量大小
1:方法如下 sudo dd if=/dev/zero of=/root/disk1.img bs=2M count=10 // 2M*10=20M zero 是de ...
- 用lua扩展你的Nginx(整理)
首先得声明.这不是我的原创,是在网上搜索到的一篇文章,原著是谁也搞不清楚了.按风格应该是属于章亦春的文章. 整理花了不少时间,所以就暂写成原创吧. 一. 概述 Nginx是一个高性能.支持高并发的,轻 ...
- test examples/test scripts
//https://www.getpostman.com/docs/v6/postman/scripts/test_examples //Setting an environment variable ...
- [LeetCode] 195. Tenth Line_Easy tag: Bash
Given a text file file.txt, print just the 10th line of the file. Example: Assume that file.txt has ...
- java中Integer 和String 之间的转换
java中Integer 和String 之间的转换 将数组转换成字符串:char[] array = {'a','b','c','d','e'};String str = new String(ar ...