hdu-1043(八数码+bfs打表+康托展开)
参考文章:https://www.cnblogs.com/Inkblots/p/4846948.html
康托展开:https://blog.csdn.net/wbin233/article/details/72998375
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043
题意:给出一串数(有9个,其中有一个x),表示这些数再3*3的矩阵中的排序序列,如果可以通过交换x与其他数字的操作,
最终得到目的矩阵(eg:12345678x),就输出x的移动方向。分别用u表示向上,d表示向下,l向左,r向右。
思路:考察八数码的知识,由于数据总量可以接受,可以用bfs打表的方式先列出存在的每个情况,利用康托展开的映射关系(也就是每一个序列对应一个hash值)
来求出移动的方向。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std; #define MAX 400000
#define AIM 46234 //124567890对应的hash值 bool v[MAX];
char path[MAX][]; //总路径
int len; char dir[]="durl"; //反向搜索
int mov[][]={{-,},{,},{,-},{,}}; //八数码状态结构体
struct Node{
int s[];
int loc;
int status; //hash值排列值
int fa; //记录父状态
char d; //移动方向
};
Node n[MAX]; int fac[]={,,,,,,,,,}; //康托展开对应的hash值 int Inverse_cantor(int s[])
{
int sum=;
for(int i=;i<;i++)
{
int num=;
for(int j=i+;j<;j++) //逆序数计数器 (康托展开需要)
{
if(s[j]<s[i]) num++;
}
sum+=num*fac[-i-];
}
return sum+;
} void count_path(Node end) //反向记录路径
{
int status = end.status;
int f=end.fa;
len=;
path[status][len++]=end.d;
while(f)
{
path[status][len++]=n[f].d; //记录方向
f=n[f].fa; //查找父状态方向
}
} void BFS()
{
memset(v,,sizeof(v));
Node next;
int head=,tail=;
for(int i=;i<;i++) //目标状态
n[].s[i]=i+; n[].s[]=;
n[].loc=;//空位是8
n[].status=AIM;
v[AIM]=true;
while(head<=tail)
{
int x=n[head].loc/;
int y=n[head].loc%;
for(int i=;i<;i++) //遍历四个方向
{
int tx=x+mov[i][];
int ty=y+mov[i][];
if(tx<||tx>||ty<||ty>) continue; next=n[head]; //更新状态
next.loc=tx*+ty; //计算新空位
next.s[n[head].loc]=next.s[next.loc]; //原空位替换
next.s[next.loc]=; //新空位
next.fa=head;
next.d=dir[i];
next.status=Inverse_cantor(next.s);
//判断重复,并且新入队列
if(!v[next.status])
{
v[next.status]=true;
count_path(next);
n[++tail]=next;
}
}
head++;
}
} int main(void)
{
BFS();
char ch[];
Node cur;
while(~scanf("%s",ch))
{
if(!strcmp(ch,"x")) cur.s[]=,cur.loc=;
else cur.s[]=ch[]-'';
for(int i=;i<;i++)
{
scanf("%s",ch);
if(!strcmp(ch,"x"))
cur.s[i]=,cur.loc=i;
else cur.s[i]=ch[]-'';
}
cur.status=Inverse_cantor(cur.s);
if(v[cur.status])
printf("%s\n",path[cur.status]);
else printf("unsolvable\n");
}
return ;
}
hdu-1043(八数码+bfs打表+康托展开)的更多相关文章
- HDU 1043 Eight(反向BFS+打表+康托展开)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...
- Eight POJ - 1077 HDU - 1043 八数码
Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...
- HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- HDU1043 八数码(BFS + 打表)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 , 康托展开 + BFS + 打表. 经典八数码问题,传说此题不做人生不完整,关于八数码的八境界 ...
- HDU 1043 八数码(八境界)
看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...
- HDU 1043 八数码(A*搜索)
在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...
- HDU 1043 八数码问题的多种解法
一.思路很简单,搜索.对于每一种状态,利用康托展开编码成一个整数.于是,状态就可以记忆了. 二.在搜索之前,可以先做个优化,对于逆序数为奇数的序列,一定无解. 三.搜索方法有很多. 1.最普通的:深搜 ...
- hdu 1043 八数码问题
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- HDU 1043 八数码 Eight A*算法
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
随机推荐
- Cisco无线AP上联口为trunk时无法注册故障处理
网络环境:WLC5520 AP:1832i-h-k9 客户实施过程中电话告知其将AP和交换机互联的端口类型设置为TRUNK口后,AP无法注册到WLC上,后经过查看配置发现客户用于AP管理的VLAN为 ...
- Qt的pro文件--项目配置的部分字段
Qt项目配置的部分字段: 库: LIBS += -L /usr/local/lib -lpcap INCLUDEPATH += /usr/local/include/
- swift - 高斯模糊
/* case extraLight case light case dark @available(iOS 10.0, *) case regular @available(iOS 10.0, ...
- openCV基础知识
openCV主体分为5个模块: CV图像处理函数和计算机视觉算法: ML机器学习库,包含许多聚类和数据分析函数: HighGUI图像和视频的输入输出: [分成三部分:硬件部分--摄像机;文件部分--载 ...
- [z]分区truncate操作的介绍及对全局索引和空间释放影响的案例解析
[z]https://www.2cto.com/database/201301/181226.html 环境: [sql] [oracle@localhost ~]$ uname -r 2.6.18- ...
- Oracle_PL/SQL(3) 游标
引言:PLSQL数据类型标量数据类型:数字类.字符类.日期类.布尔类(boolean).复合数据类型:记录(%rowtype).表.数组引用类型:REF CURSORLOB类型:BLOB.CLOB 1 ...
- linux 管道符与通配符
###管道符 *命令格: 命令1 | 命令2 //命令1的正确输出作为命令2的操作对象 ll | more netstat -an | grep xxx 通配符 类似于正则表达式 ? 一个以上 [] ...
- H5C3动画
1 渐变 /* 渐变:不同颜色之间的柔和过渡 线性渐变:沿着某条直线发生渐变效果 注意:渐变准备来说是一张背景图 语法:linear-gradient */ background-image: lin ...
- Vue 不同环境配置相应的 API 地址
我使用的是 Vue + ElementUI 进行构建的项目,在开发过程中,使用的是前后端分离的模式,所以经常会出现多环境配置信息,尤其是 Api 接口地址的配置,如果在代码中使用判断的方式,感觉不友好 ...
- 补课:Shell命令${}
Shell中的${}.##和%%使用范例: 代码如下:file=/dir1/dir2/dir3/my.file.txt可以用${ }分别替换得到不同的值:${file#*/}:删掉第一个 / 及其左边 ...