题目链接:https://vijos.org/p/1360

优先队列BFS:

这个八数码问题本身其实是之前人工智能实验课的作业……

首先,如果不带估价函数,直接用优先队列BFS,肯定也是能得到正确结果的,至于用时怎么样,可以看评测结果……

代码:

#include<bits/stdc++.h>
using namespace std;
int dx[]={,,,-};
int dy[]={,-,,};
string ed="";
struct Node
{
int dist;
int x,y;
string mp; #define X(idx) (idx/3)
#define Y(idx) (idx%3)
char& val(int i,int j){return mp[i*+j];} void Zero()
{
for(int i=;i<;i++)
{
if(mp[i]!='') continue;
x=X(i), y=Y(i); break;
}
} bool operator<(const Node& o)const{return dist>o.dist;}
}st;
map<string,bool> vis;
priority_queue<Node> Q;
int main()
{
cin>>st.mp;
st.dist=;
st.Zero(); vis.clear();
Q.push(st), vis[st.mp]=;
while(Q.size())
{
Node now=Q.top(); Q.pop();
if(now.mp==ed)
{
cout<<now.dist<<endl;
break;
}
for(int k=;k<;k++)
{
Node nxt=now;
nxt.x+=dx[k], nxt.y+=dy[k], nxt.dist++;
if(nxt.x< || nxt.x> || nxt.y< || nxt.y>) continue;
swap(nxt.val(now.x,now.y),nxt.val(nxt.x,nxt.y));
if(!vis[nxt.mp]) Q.push(nxt), vis[nxt.mp]=;
}
}
}

评测结果:

Astar算法:

然后,我们知道,优先队列BFS里的优先队列,是一个维护当前代价的二叉堆,

我们接下来增加Astar算法的估价函数 $eval(x)$,考虑到要这个估价函数,是要不大于从当前状态到目标状态的实际代价的,

因此我考虑将其设定成:将当前状态下的九宫格看做一个长度为 $9$ 的字符串 $s$,目标状态也可以看做一个字符串 $t = "123804765"$,统计这两个字符串使得 $s_i \neq t_i$ 的 $i$ 的个数,记为 $e$,再取 $eval(x) = \lfloor \frac{e}{2} \rfloor$ 即可。

这也是很好理解的,因为不可能用更少的步数使得当前状态变为目标状态了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int dx[]={,,,-};
int dy[]={,-,,};
string ed="";
struct Node
{
int dist,eval;
int x,y;
string mp; #define X(idx) (idx/3)
#define Y(idx) (idx%3)
char& val(int i,int j){return mp[i*+j];} void Zero()
{
for(int i=;i<;i++)
{
if(mp[i]!='') continue;
x=X(i), y=Y(i); break;
}
} void Eval()
{
eval=;
for(int i=;i<;i++) eval+=(mp[i]!=ed[i]);
eval/=;
} bool operator<(const Node& o)const
{
return dist+eval>o.dist+o.eval;
}
}st;
map<string,bool> vis;
priority_queue<Node> Q;
int main()
{
cin>>st.mp;
st.dist=;
st.Zero();
st.Eval(); vis.clear();
Q.push(st), vis[st.mp]=;
while(Q.size())
{
Node now=Q.top(); Q.pop();
if(now.mp==ed)
{
cout<<now.dist<<endl;
break;
}
for(int k=;k<;k++)
{
Node nxt=now;
nxt.x+=dx[k], nxt.y+=dy[k], nxt.dist++;
if(nxt.x< || nxt.x> || nxt.y< || nxt.y>) continue;
swap(nxt.val(now.x,now.y),nxt.val(nxt.x,nxt.y));
if(!vis[nxt.mp])
{
nxt.Eval();
Q.push(nxt), vis[nxt.mp]=;
}
}
}
}

评测结果:

总结:

比较普通的优先队列维护下的BFS,和加了估价算法的Astar算法,可以明显看到时间和空间的使用都明显降低了。

(鉴于有可能会有同样在做这个实验的同学搜索到本文,我还是要声明一下:上面的两个代码都是我亲手敲的,没有看网上任何别的博客,想要拿去借鉴的同学,建议看懂了之后根据自己的思路做一些修改乃至优化……直接抄袭这样的事情最好还是不要做……)

Vijos 1360 - 八数码问题 - [A*]的更多相关文章

  1. vijos 1360 八数码问题 - 启发式搜索

    背景 Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们. 描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0 ...

  2. 【宽搜】Vijos P1360 八数码问题

    题目链接: https://vijos.org/p/1360 题目大意: 3x3格子上放1~8数字,一个空位,每次空位可与上下左右交换,固定终止布局,求输入的起始布局需要几步到达终止布局 题目思路: ...

  3. 关于八数码问题中的状态判重的三种解决方法(编码、hash、&lt;set&gt;)

    八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...

  4. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  5. 八数码问题:C++广度搜索实现

    毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...

  6. ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)

    八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...

  7. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

  8. 双向广搜+hash+康托展开 codevs 1225 八数码难题

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  9. UVALive 6665 Dragon’s Cruller --BFS,类八数码问题

    题意大概就是八数码问题,只不过把空格的移动方式改变了:空格能够向前或向后移动一格或三格(循环的). 分析:其实跟八数码问题差不多,用康托展开记录状态,bfs即可. 代码: #include <i ...

随机推荐

  1. golang 使用pprof和go-torch做性能分析

    软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...

  2. Ubuntu18.04下的模拟神器RetroArch

    安装 直接通过apt安装 sudo add-apt-repository ppa:libretro/stable sudo apt update sudo apt install retroarch ...

  3. Windows利用文件夹映射来同步文件

    在windows服务器上有时有这样的需求: 你的文件在f:\test中,但由于其它原因用户访问的是e:\test,如果又希望e:\test 中的文件与f:\test的保持同步,除了用同步软件来做外,可 ...

  4. Python(字符编码)

    https://www.cnblogs.com/zihe/p/6993891.html 一 了解字符编码的知识储备 1. 文本编辑器存取文件的原理(nodepad++,pycharm,word) 打开 ...

  5. ero-configuration Web Application Debugging with Xdebug and PhpStorm

    1. Install Xdebug To use Xdebug with PhpStorm for debugging PHP applications, you need to have a PHP ...

  6. Gorm使用详解

    1.什么是Gorm go语言编写的orm框架 特点: 1)全功能ORM 2)关联(包含一个,包含多个,属于,多对多) 3)Callbacks(创建/保存/更新/删除/查找前后回调) 4)预加载 5)事 ...

  7. Linux下C语言执行shell命令

    有时候在代码中需要使用到shell命令的情况,下面就介绍一下怎么在C语言中调用shell命令: 这里使用popen来实现,关于popen的介绍,查看 http://man7.org/linux/man ...

  8. 在BootStrap的modal中使用Select2

      bootstrap 3 $.fn.modal.Constructor.prototype.enforceFocus = function() {}; bootstrap4 $.fn.modal.C ...

  9. NO.1 hadoop简介

    第一次接触这个时候在网上查了很多讲解,以下很多只是来自网络. 1.Hadoop (1)Hadoop简介    Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层 ...

  10. crontab命令详解

    一. Crontab 介绍 1.crontab命令的功能是在一定的时间间隔调度一些命令的执行,我理解为windows下的任务计划. 2./etc/crontab 文件 在/etc目录下有一个cront ...