【描述】
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。

空格周围的棋子可以移到空格中。

要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

【题解】

搜索经典题目,网上各种搞法,于是我就写个A*水一下。。。

主要说一下启发函数的写法:

首先定义一个dis[10][10]数组,记录偏移距离,我们把地图中的点按行标号,则dis[i][j]表示从第i个点到第j个点至少移动的步数。

举个栗子:

点的编号:1 2 3

       4 5 6

       7 8 9

那么显然dis[1][2]=1,dis[2][9]=3,dis[3][4]=3

这个dis数组可通过预处理完成,应该是这个样子:

0 1 2 1 2 3 2 3 4
1 0 1 2 1 2 3 2 3
2 1 0 3 2 1 4 3 2
1 2 3 0 1 2 1 2 3
2 1 2 1 0 1 2 1 2
3 2 1 2 1 0 3 2 1
2 3 4 1 2 3 0 1 2
3 2 3 2 1 2 1 0 1
4 3 2 3 2 1 2 1 0

接着定义一个p[10]数组,p[i]表示数字i在目标状态中的位置,也可以通过预处理完成,

const int p[10]={5,1,2,3,6,9,8,7,4};

然后定义一个r[10]数组,r[i]表示数字i在当前状态中的位置,这个需要动态维护。

那么估价函数的值当然就是数字0-8 的偏移量之和了。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
const int dx[]={,,-,};
const int dy[]={,,,-};
const int p[]={,,,,,,,,};
int s,flag,r[],a[][],map[][],dis[][];
bool check() {for(int i=;i<=;i++)if(r[i]!=p[i])return ;return ;}
int get() {int t=;for(int i=;i<=;i++)t+=dis[r[i]][p[i]];return t;}
int jue(int a,int b){int t=a-b; return t<?-t:t;}
int calx(int i){return (i-)/+;}
int caly(int i){return i%==?:i%;}
void dfs(int depth,int x,int y)
{
if(depth+get()>s) return;
if(check()) {flag=; return;}
for(int i=;i<;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if(xx<||yy<||xx>||yy>) continue;
swap(a[x][y],a[xx][yy]); swap(r[a[x][y]],r[a[xx][yy]]);
dfs(depth+,xx,yy);
swap(a[x][y],a[xx][yy]); swap(r[a[x][y]],r[a[xx][yy]]);
}
}
void pre()
{
for(int i=;i<=;i++)
for(int j=i+;j<=;j++)
dis[i][j]=dis[j][i]=calx(j)-calx(i)+jue(caly(i),caly(j));
}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
pre();
int sx,sy;
for(int i=;i<=;i++)
{
char ch=getchar(); int x=calx(i),y=caly(i);
map[x][y]=ch-''; r[ch-'']=i;
if(ch=='') sx=x,sy=y;
}
for(s=;;s++)
{
memcpy(a,map,sizeof(map)); dfs(,sx,sy);
if(flag) {printf("%d\n",s); break;}
}
return ;
}

八数码问题——A*大法好的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. P1379 八数码问题

    aoapc上的八数码问题,在luogu上也有类似的题,p1379,经典题目,lrj给出了一个算法,同时给出了三种判重的方法.本来想用std::queue改写一下,但是出了各种问题,只好抄代码ac掉这道 ...

  8. [cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)

    快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚 ...

  9. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

随机推荐

  1. Gradle配置IDEA正常识别JPA Metamodel Generator动态生成的代码

    我们在使用JPA动态查询构建查询条件时,为了实现安全的类型检查,常常需要引用Hibernate JPA Metamodel Generator自动为我们生成静态元模型类. 而这些类由于编译时由Hibe ...

  2. Robot Framework接口测试(4)

    现在我们已经做好了进行接口测试的必要准备:1.拼接发送的报文:2.发送报文的方法.现在我们实现RF上的接口测试. 我们先对发送的方法进行一下封装: 1.拼接报文方法: #coding : utf-8 ...

  3. Hexo博客网站再配置

    这两天整理网站方面的事,本地IIS部署,个人网站,发现我的hexo做的个人网站实在很单调,于是找来资料做进一步的配置. 一.网站图标 看一下hexo\themes\modernist\layout\_ ...

  4. js中使用分号的情况

  5. unity drawcall测试

    unity引擎影响drawcall的元素(使用Quad和Cube对比测试) 1.相机的background(没有渲染元素区域的颜色),4Verts.2Tris.1SetPass calls:      ...

  6. UOJ #188 Sanrd —— min_25筛

    题目:http://uoj.ac/problem/188 参考博客:https://www.cnblogs.com/cjoieryl/p/10149748.html 关键是枚举最小质因子...所以构造 ...

  7. Java文件压缩优化工具(ProGuard) 软件介绍 Soft content

    ProGuard是一款免费的Java类文件的压缩.优化.混肴器.它可以帮你删除没用的类,字段,方法与属性,使字节码最大程度地优化,使用简短且无意义的名字来重命名类.字段和方法 .目前eclipse已经 ...

  8. java代码反转toCharAT()的用法

    总结:反转注意for循环里面的变化 package clientFrame; //字符串反转 public class we { public static void main(String[] ar ...

  9. 网络编程Socket之wireshark使用

    这里只对wireshark进行简单的使用介绍.里面的报表,IO图形分析等以后再谈....  这里不提供下载地址了,不是什么稀有资源,我使用的wireshark是在百度软件中心下载的. 第一步:选择需要 ...

  10. EasyUI 读数据库图

    EasyUI 读数据库图 function edit_dg() { //选中一行,获取这一行的主键值 var idImg = $("#tbDeviceClassBrowstab") ...