题目链接: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. LIN 笔记

    LIN 使用了 1 根线来进行通信,但是,它必须要参考 VBat 和 GND.离开这两个参考电平,并没有办法来判断线上的 bit 状态. 另外,根据经典的 LIN 驱动电路(一个 OC 门),RX 接 ...

  2. MongoDB存储过程创建和使用一例

    mongo的脚本是js语法,所以存储过程也是js语法. 创建: db.system.js.save( { _id: "saveAndCount", value : function ...

  3. input 呼起数字键盘

    1. Android,定义 type="number" 2. iOS,定义 style="ime-mode: disabled;" 注,呼起数字键盘后,用户输入 ...

  4. Sword 内核队列二

    #ifndef __GTC_FIFO_H_ #define __GTC_FIFO_H_ #ifndef GTC_MAX #define GTC_MAX(a,b) ((a) > (b) ? (a) ...

  5. ASP.NET MVC实现Excel文件的上传下载

    在应用系统开发当中,文件的上传和下载是非常普遍的需求.在基于.NET的C/S架构的项目开发当中,有多种方案可以实现文件的上传和下载(httpwebrequest.webclient等),而且多采用异步 ...

  6. NB-Iot的应用领域、覆盖范围,是什么

    该部分分享的是物联网各垂直应用领域里,NB-IoT技术的部署,看看适合NB-IoT技术的垂直应用场景有哪些?垂直应用服务商又该如何部署? 1 NB-IoT适合的垂直应用场景有哪些? 2 NB-IoT垂 ...

  7. java中jdbc源码解读

    在jdbc中一个重要的接口类就是java.sql.Driver,其中有一个重要的方法:Connection connect(String url, java.util.Propeties info); ...

  8. 线程锁Lock

    from threading import Thread, Lock import time def func(): global n n -= 1 n = 10 t_list = [] for i ...

  9. Java课程寒假之开发记账本软件(网页版)之二

    一.实现基础功能之一(记账) 一个记账本最基础之一的功能就是记账,所以也是首先要解决的问题,我选择了上学期使用的MySQL数据库来对账本进行存储. 我选择记账的方法是分开记账,就是支出放在一个表,收入 ...

  10. css之高度塌陷及其解决方法

    浅谈 清除浮动 的多种方式(clearfix) 1.什么是浮动 ? 是否脱离文档流? 1.普通流定位 static(默认方式) 普通流定位,又称为文档流定位,是页面元素的默认定位方式 页面中的块级元素 ...