逆向bfs搜索打表+康拓判重
HDU 1043八数码问题
八数码,就是1~8加上一个空格的九宫格,这道题以及这个游戏的目标就是把九宫格还原到从左到右从上到下是1~8然后最后是空格。
没了解康托展开之前,这道题怎么想都觉得很棘手,直接搜索的话也不知道怎么剪枝,而且判重也不可能开一个9维的数组,空间也不允许,所以先了解康托展开是无可厚非的第一步,这里就引用一下大佬的介绍,很简单很实用的关于全排列的一个东西
学会康托展开之后这道题就有很多解法了,很多是用A*的,不过这个我还没学会,只能弱弱的用万能的搜索来暴力过一切了,当然搜索的做法也有几个,直接暴力的正向搜索单组测试数据是可以的,单多组测试数据的话还是会超时,还有种双向bfs的做法,也就是把当前的数列和我们要的目标数列同时加入队列,然后两个相遇时就可以了。
不过我个人觉得那两个写起来比较麻烦不好处理,所以我还是采用一个逆向的bfs来打表,为什么可以打表的,了解康托展开后我们可以知道,这题的全排列最多也就9!,那我们完全可以预处理一下,由目标状态去跑到其他状态,把每个状态的康托展开的值作为它的一个编号,由此打表,具体的如代码
#include<cstdio>
#include<queue>
using namespace std;
const int dir[][]={{,},{,},{,-},{-,}};
const char leg[]={'l','u','r','d'};//因为是逆回去的,所以方向是反的
char s[];
int jc[]={},sm[];
struct Way{
char ans;
int f;
Way(){
f=-;
}
}w[];
struct Node{
int num[];
int kt,p;//康托值,x的位置
};
int kangtuo(int *a)//康托展开
{
int ans=;
for(int i=;i<;i++)
{
int k=;
for(int j=i+;j<;j++)
if(a[i]>a[j])
k++;
ans+=k*jc[-i];
}
return ans;
}
void bfs()
{
queue<Node> q;
Node b;
for(int i=;i<;i++)
b.num[i]=i;
b.kt=,b.p=;
q.push(b);
while(!q.empty())
{
Node e=q.front();
q.pop();
for(int i=;i<;i++)
{
int dx=e.p/+dir[i][];//二维比价好处理位置变化
int dy=e.p%+dir[i][];
if(dx>=&&dx<&&dy>=&&dy<)
{
b=e;b.p=dx*+dy;
int t=b.num[e.p];b.num[e.p]=b.num[b.p];b.num[b.p]=t;
b.kt=kangtuo(b.num);
if(w[b.kt].f==-)
{
w[b.kt].f=e.kt;
w[b.kt].ans=leg[i];
q.push(b);
}
}
}
}
}
int main()
{
for(int i=;i<=;i++)
jc[i]=jc[i-]*i;
bfs();
while(~scanf("%s",s))
{
for(int i=;i<;i++)
scanf("%s",s+i);
for(int i=;i<;i++)
if(s[i]>=''&&s[i]<='')
sm[i]=s[i]-'';
else
sm[i]=;
int kt=kangtuo(sm);
if(w[kt].f==-)//没遍历到这个状态
printf("unsolvable\n");
else
{
while(kt)//回溯输出答案
{
printf("%c",w[kt].ans);
kt=w[kt].f;
}
printf("\n");
}
}
return ;
}
代码千万条,自觉第一条,复制粘贴爽,打铁泪两行
既然涉及到八数码,最后再补充一个结论,怎么直接判断八数码有没有解,这涉及到逆序数,目标状态1~8的逆序数是0,而上下左右的变换并不会改变逆序数的奇偶性,(这里说的逆序数是不计x的)
所以结论就是,序列的奇偶性要和目标状态一致。
逆向bfs搜索打表+康拓判重的更多相关文章
- 八数码问题+路径寻找问题+bfs(隐式图的判重操作)
Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...
- hdu 5012 bfs --- 慎用STL 比方MAP判重
http://acm.hdu.edu.cn/showproblem.php?pid=5012 发现一个问题 假设Sting s = '1'+'2'+'3'; s!="123"!!! ...
- poj3635 FULL tank(TLE) 有限制的最短路(BFS搜索)。
用的BFS+优先队列+二进制压缩状态判重+链式前向星, TLE,好像有人这样过了...好像要用A*算法,还不太会,所以暂时放弃.但是也学会了很多,学习了链式前向星,更深理解了BFS求最优的时候,什么时 ...
- BFS(四):搜索状态判重
在采用广度优先算法进行搜索时,一个需要重点注意的是在搜索过程中判重和去重.前面介绍的几个例子中,判重都较简单,如采用vis[]数组,若vis[i]==0,则i未访问过,i入队列:若vis[i]!=0, ...
- UVA 10651 Pebble Solitaire(bfs + 哈希判重(记忆化搜索?))
Problem A Pebble Solitaire Input: standard input Output: standard output Time Limit: 1 second Pebble ...
- BFS以及hash表判重的应用~
主要还是讲下hash判重的问题吧 这道题目用的是除法求余散列方式 前几天看了下算法导论 由于我们用的是线性再寻址的方式来解决冲突问题 所以hash表的大小(余数的范围)要包含我们要求的范围 对mod的 ...
- poj 1077-Eight(八数码+逆向bfs打表)
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...
- hdu 4444 Walk (离散化+建图+bfs+三维判重 好题)
Walk Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submi ...
- HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
随机推荐
- oracle学习笔记03
一:表空间 /* 创建表空间:逻辑单位,通常我们新建一个项目,就会去创建表空间,在表空间中创建用户,用户去创建表. 语法:create tablespace 表空间名字 datafile '文件的路径 ...
- Win10怎么添加开机启动项?Win10添加开机自动运行软件三种方法
Win10管理开机启动项的方法相信大家已经非常熟悉,msconfig命令各系统都通用,那么很多用户发觉Win10和Win7 XP等系统不同,没有启动文件夹,那么我们怎么添加开机启动项呢?如晨软件或程序 ...
- git diff 的简单使用(比较版本区别)
假如我们修改viewMail.vue 文件(部分代码) 从 //根据ID获取详情 getById () { let that = this; this.viewMailModal = true; th ...
- 出现 HTTP 错误 500.19 错误代码 0x800700b7
这个内容出现主要问题是在IIS上,我们一般程序开发 iis中默认的路径只是http://localhost/,相当于环境变量中已定义好了,如果自己创建的项目直接将路径定义到这,就会替换图二中的路径,然 ...
- CN丶Moti-个人博客
欢迎访问我的个人博客,获取更多有用的东西 链接一 链接二 也可以关注我的微信订阅号:CN丶Moti
- EF Core的级联删除
级联删除由DeleteBehavior的枚举值来设置: 行为名称 对内存中的依赖项/子项的影响 对数据库中的依赖项/子项的影响 Cascade 删除实体 删除实体 ClientSetNull 外键属性 ...
- 利用css伪类选择器hover控制两个元素属性
示例1: <html> <body> <style> #a:hover {color : #FFFF00;} #a:hover > #b:first-chil ...
- 8.Spring整合Hibernate_2_声明式的事务管理(Annotation的方式)
声明式的事务管理(AOP的主要用途之一) (Annotation的方式) 1.加入annotation.xsd 2.加入txManager bean 3.<tx:annotation-drive ...
- 【Struts2】防止表单重复提交
一.概述 二.Struts2中解决方案 三.实现步骤 一.概述 regist.jsp----->RegistServlet 表单重复提交 危害: 刷票. 重复注册.带来服务器访问压力(拒绝服务) ...
- 【python+selenium】selenium grid(分布式)
前言 原文:https://blog.csdn.net/real_tino/article/details/53467406 Selenium grid是用来分布式执行测试用例脚本的工具,比如测试人员 ...