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 ...
随机推荐
- f5 Seldom used
1.负载均衡算法 2)最快响应速度(Fastest) •优先查看7层请求的连接数,然后查看4层连接数 •需要在virtual server上关联7层的profile,否则与最小连接数相同 •后台服务器 ...
- 安装sql server 2008 提示错误 SQL Server 2005 Express 工具。 失败
安装sql server 2008 management,提示错误:Sql2005SsmsExpressFacet 检查是否安装了 SQL Server 2005 Express 工具. 失败,已安装 ...
- [leetcode]123. Best Time to Buy and Sell Stock III 最佳炒股时机之三
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- linux详解sudoers
sudo使用 Linux是多用户多任务的操作系统, 共享该系统的用户往往不只一个.出于安全性考虑, 有必要通过useradd创建一些非root用户, 只让它们拥有不完全的权限; 如有必要,再来提升权限 ...
- 安装git工具在ubuntu系统
Git is one of the most popular tools used for distributed version control system(VCS). Git is common ...
- Linux下实时查看GPU状态
参考链接: http://blog.csdn.net/yao_yao_2015/article/details/53404389 1. 显示当前GPU使用情况 Nvidia自带了一个nvidia-sm ...
- 基于.net技术的 Rss 订阅开发
RSS(Really Simple Syndication,真正简单的连锁)是一种 Web 内容连锁格式.RSS 成为通过 Web 连锁新闻内容的标准格式.刚好我现在vs的环境也是.net,因为在.N ...
- Vs2015 c# 诊断工具查看程序的占用情况
windbg用着还不熟悉,dottrace 还要版权,着急查看程序的cpu 的使用情况,因为程序开启之后占用处理器资源较大,问题在哪里呢,于是点开了vs2015自带的诊断工具,以前偶尔打开过,没发现 ...
- C# oracle 日期型字段,使用参数传值时,遇到ORA-01810: format code appears twice错误
C#操作oracle数据库时,发现使用to_date('2014-01-03 18:00:00','yyyy-mm-dd hh:MM:ss')时,会出现ORA-01810: format code a ...
- sql 查询某个字段出现的次数
表名随便起个 testtable 那么有这么一个需求,利用你所学的sql语句 单表查询出下表的结果 也就是统计某个时间某个值出现的次数其实一开始我是很懵,毕竟之前也没做过,只能怪自己学得太浅了.过后我 ...