在学习八数码A*搜索问题的时候须要知道下面几个点:

Hash:利用康托展开进行hash

康托展开主要就是依据一个序列求这个序列是第几大的序列。

A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算就能够。

减枝:在八数码里。随意交换一个空行和一个位置的数字,这个八数码的逆序数是不变的,这样就能够依据眼下状态推断是否可达终点状态了。

第一次做这个题用的map进行哈希,结果果断超时。之后又写了LRJ书上的hash方法也超时了,最后仅仅能用康托展开了

具体请參考:【八数码的八重境地】 http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

/*
康托展开
A* 算法
八数码逆序数性质
*/
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 370015;
//322560
struct State{
int mat[3][3];
int h,g,cvalue;
int posx,posy;
friend bool operator < (State p,State q){
if(p.h != q.h)
return p.h > q.h;
else
return p.g > q.g;
}
}start;
int vis[maxn],fa[maxn],cnt;
//-------------------init----------------------------------
void init(){
memset(vis,-1,sizeof(vis));
memset(fa,-1,sizeof(fa));
cnt = 0;
}
bool isok(State &state){
int temp[9];
for(int i = 0,k = 0; i < 3; i ++)
for(int j = 0; j < 3; j++,k++)
temp[k] = state.mat[i][j];
int ret = 0;
for(int i = 0; i < 9; i++)
for(int j = 0; j < i; j++){
if(temp[i] && temp[j] && temp[j] > temp[i])
ret ++;
}
return (ret & 1) ? 0 : 1;
}
//---------------------------------------------------------
const int Hash[] = {1,1,2,6,24,120,720,5040,40320};
int Cantor(State &stemp){
int temp[9];
for(int i = 0,k = 0; i < 3; i++)
for(int j = 0; j < 3; j++, k++)
temp[k] = stemp.mat[i][j];
int ret = 0;
for(int i = 0; i < 9; i++){
int val = 0;
for(int j = 0; j < i; j++)
if(temp[j] > temp[i]) val ++;
ret += Hash[i] * val;
}
return ret;
}
//----------------------------------------------------------
int get_h(State &temp){
int ret = 0;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++){
ret +=
abs(i - (temp.mat[i][j] - 1)/3) + abs(j - (temp.mat[i][j] - 1) % 3);
}
return ret;
}
//----------------------------------------------------------
//ulldrdrulldrruldlurrd
const char cdir[] = "dlru";
const int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}}; //d l r u
void dfs_print(int u){
if(vis[u] < 0)
return;
dfs_print(fa[u]);
printf("%c",cdir[vis[u]]);
}
bool bfs(){
priority_queue<State>q;
start.cvalue = Cantor(start);
start.h = get_h(start);
start.g = 0;
q.push(start);
vis[start.cvalue] = - 2;
State temp;
while(!q.empty()){
State now = q.top(); q.pop();
if(now.cvalue == 322560){
dfs_print(now.cvalue);
puts("");
return true;
}
for(int i = 0; i < 4; i++){
temp = now;
int x = now.posx + dir[i][0];
int y = now.posy + dir[i][1];
temp.posx = x;
temp.posy = y;
if(x >= 0 && x < 3 && y >= 0 && y < 3){
swap(temp.mat[x][y],temp.mat[now.posx][now.posy]);
int cvalue = Cantor(temp);
if(vis[cvalue] == -1 && isok(temp)){
vis[cvalue] = i;
fa[cvalue] = now.cvalue;
temp.h = get_h(temp);
temp.g = now.g + 1;
temp.cvalue = cvalue;
q.push(temp);
if(temp.cvalue == 322560){
dfs_print(cvalue);
puts("");
return true;
}
cnt ++;
}
}
}
}
return false;
}
int main(){
char _in[10][2];
while(scanf("%s",_in[0]) != EOF){
init();
for(int i = 1; i < 9; i++)
scanf("%s",_in[i]);
for(int k = 0,i = 0; i < 3; i++)
for(int j = 0; j < 3; j++,k ++){
if(_in[k][0] == 'x'){
_in[k][0] = '0';
start.posx = i;
start.posy = j;
}
start.mat[i][j] = _in[k][0] - '0';
}
if(!bfs())
printf("unsolvable\n");
}
return 0;
}
/*
1
2
6
24
120
720
5040
40320
*/

HDU 1043 八数码(A*搜索)的更多相关文章

  1. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  2. HDU 1043 八数码(八境界)

    看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...

  3. HDU 1043 八数码问题的多种解法

    一.思路很简单,搜索.对于每一种状态,利用康托展开编码成一个整数.于是,状态就可以记忆了. 二.在搜索之前,可以先做个优化,对于逆序数为奇数的序列,一定无解. 三.搜索方法有很多. 1.最普通的:深搜 ...

  4. HDU 1043 八数码 Eight A*算法

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. Eight hdu 1043 八数码问题 双搜

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. hdu 1043 八数码问题

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  7. hdu3567 八数码(搜索)--预处理

    题意:为你两个状态,求a到b 的最小路径,要求字典序最小. 思路: 最开始想的是目标状态是变化的,所以打表应该不行,然后直接上A*,但是TLE了- -(瞬间无语) 然后看了下别人的思路,预处理出9个状 ...

  8. (中等) HDU 1043 Eight,经典搜索问题。

    Problem Description The 15-puzzle has been around for over 100 years; even if you don't know it by t ...

  9. 【P1379】八数码难题(搜索+暴力)

    这个题真是... 不想说什么了,及其复杂和烦人的一道题.基础思路就是bfs,用两个队列分别进行0的位置的计算和每一步的状态..然而这个题最重要的一点在于判重,实际上可以康托展开用全排列的个数进行判重, ...

随机推荐

  1. 紫书 例题 10-23 UVa 10213(欧拉公式+高精度)

    用欧拉公式V-E+F=2 V是顶点数,E是边数,F是面数 具体推导见https://blog.csdn.net/QWsin/article/details/53635397 要用高精度 #includ ...

  2. Qt 5.3 下OpenCV 2.4.11 开发(0)图像处理基本概念

    1.普通情况下的RGB彩色图像:它的每一个像素点都是由三个通道组成,即红色(R).绿色(G)和蓝色(B).8位三通道彩色图像就是每一个像素中每一个通道的取值范围都是 0~255(即二进制下的8位数), ...

  3. linux命令su与su-的差别

    su命令和su -命令最大的本质差别就是: su仅仅是切换了root身份.但Shell环境仍然是普通用户的Shell. 而su -连用户和Shell环境一起切换成root身份了. 仅仅有切换了Shel ...

  4. 使用ssh过程中对数据库进行update时报错

    报错信息:org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in ...

  5. Eclipse下面的Maven管理的SSH框架整合(Struts,Spring,Hibernate)

    搭建的环境:eclispe下面的maven web项目 Struts:    2.5.10 Spring:    4.3.8 Hibernate:   5.1.7 .Final MySQL:   5. ...

  6. Windows系统时间同步出错解决办法(w32tm /register按回车,可能是为了解决时间COM注册的问题)

    有时候我们设置本地时间与Internet时间同步时,经常连接服务器time.windows.com超时,导致时间同步失败,解决办法如下: 利用快捷键"Win+R"调出运行框,输入: ...

  7. vue8 生命周期

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. TFRecord —— tensorflow 下的统一数据存储格式

    tensorflow 提供了统一的数据存储格式,即 TFRecord(record 表示记录),以提高程序的可扩展性,当数据来源十分复杂时,仍能有效记录输入数据中的信息. 1. tfrecord 使用 ...

  9. CentOS 与Ubuntu 安装软件包的对比

    工作需要开始转向centos,简单记录软件包安装 wget不是安装方式 他是一种下载软件类似与迅雷 如果要下载一个软件 我们可以直接 wget 下载地址 ap-get是ubuntu下的一个软件安装方式 ...

  10. 超级硬件代理解决企业Web提速上网问题

    超级硬件代理解决企业Web提速上网问题 需求分析: XX集团是五家企业重组建立的特大型工程勘察设计咨询企业,下设10多个分公司,上网人数众多.有多台WEB server,对外服务,访问量及大.以前无论 ...