HDU - 3567 IDA* + 曼哈顿距离 + 康托 [kuangbin带你飞]专题二
这题难度颇大啊,TLE一天了,测试数据组数太多了。双向广度优先搜索不能得到字典序最小的,一直WA。
思路:利用IDA*算法,当前状态到达目标状态的可能最小步数就是曼哈顿距离,用于搜索中的剪枝。下次搜索的限制不能直接加1,会超时,应该从当前状态到目标状态最小限制开始搜索。
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn = 4e5 + 5;
int vis[maxn];
int st[9], goal[9];
const int dx[] = {1,0,0,-1};
const int dy[] = {0,-1,1,0};
const char dir[] = {'d','l','r','u'};
int fact[9], loc[9];
void deal() { //1~8阶乘打表,方便编码
fact[0] = 1;
for(int i = 1; i < 9; ++i) fact[i] = fact[i - 1] * i;
}
int KT(int *a) {
int code = 0;
for(int i = 0; i < 9; ++i) {
int cnt = 0;
for(int j = i + 1; j < 9; ++j) if(a[j] < a[i]) cnt++;
code += fact[8 - i] * cnt;
}
return code;
}
void get_pos() {
for(int i = 0; i < 9; ++i) {
loc[goal[i]] = i;
}
}
int get_h(int *a) { //曼哈顿距离
int cnt = 0;
for(int i = 0; i < 9; ++i) {
if(a[i] == 0 || i == loc[a[i]]) continue;
int x = i / 3, y = i % 3;
int n = loc[a[i]];
int px = n / 3, py = n % 3;
cnt += abs(x - px) + abs(y - py);
}
return cnt;
}
char ans[50];
int a[9];
// step + h <= maxd
int maxd, nextd;
int dfs(int step, int pos) {
int h = get_h(a); // cut
//printf("h = %d\n", h);
if(h == 0) {
printf("%d\n", step);
ans[step] = '\0';
printf("%s", ans);
return 1;
}
if(step + h > maxd) {
nextd = min(nextd, step + h);
return 0;
}
int x = pos / 3, y = pos % 3;
for(int i = 0; i < 4; ++i) {
int px = x + dx[i], py = y + dy[i];
if(px < 0 || py < 0 || px >= 3 || py >= 3) continue;
int pz = px * 3 + py;
swap(a[pos], a[pz]);
int code = KT(a);
if(vis[code]) {
swap(a[pos], a[pz]);
continue;
}
vis[code] = 1;
ans[step] = dir[i];
if(dfs(step + 1, pz)) return 1;
vis[code] = 0;
swap(a[pos], a[pz]);
}
return 0;
}
int main() {
deal();
char str[50];
int T, kase = 1;
scanf("%d", &T);
while(T--) {
int pos;
scanf("%s", str);
for(int i = 0; i < 9; ++i) {
if(str[i] == 'X') {
pos = i;
st[i] = 0;
}
else st[i] = str[i] - '0';
}
scanf("%s", str);
for(int i = 0; i < 9; ++i) {
if(str[i] == 'X') goal[i] = 0;
else goal[i] = str[i] - '0';
}
get_pos();
printf("Case %d: ", kase++);
int code = KT(st);
vis[code] = 1;
for(maxd = get_h(st);;) {
nextd = 1 << 30;
memcpy(a, st, sizeof(a));
memset(vis, 0, sizeof(vis));
if(dfs(0, pos)) break;
maxd = nextd;
}
printf("\n");
}
return 0;
}
如有不当之处欢迎指出!
HDU - 3567 IDA* + 曼哈顿距离 + 康托 [kuangbin带你飞]专题二的更多相关文章
- HDU - 1043 A* + 康托 [kuangbin带你飞]专题二
这题我第一次用的bfs + ELFhash,直接TLE,又换成bfs + 康托还是TLE,5000ms都过不了!!我一直调试,还是TLE,我才发觉应该是方法的问题. 今天早上起床怒学了一波A*算法,因 ...
- HDU - 3085 双向BFS + 技巧处理 [kuangbin带你飞]专题二
题意:有两只鬼,一个男孩女孩被困在迷宫中,男孩每秒可以走三步,女孩只能1步,鬼可以两步且可以通过墙.问男孩女孩是否可以在鬼抓住他们之前会合? 注意:每秒开始鬼先移动,然后两人开始移动. 思路:以男孩和 ...
- HDU - 3567 Eight II (bfs预处理 + 康托) [kuangbin带你飞]专题二
类似HDU1430,不过本题需要枚举X的九个位置,分别保存状态,因为要保证最少步数.要保证字典序最小的话,在扩展节点时,方向顺序为:down, left, right, up. 我用c++提交1500 ...
- 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开
[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...
- HDU - 3533 bfs [kuangbin带你飞]专题二
看了好久的样例才看懂. 题意:有一个人要从(0,0)走到(n,m),图中有k个碉堡,每个碉堡可以向某个固定的方向每隔t秒放一次炮,炮弹不能穿越另一个碉堡,会被阻挡.人在移动的过程中不会被炮弹打到,也就 ...
- HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二
终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...
- HDU1560 DNA sequence IDA* + 强力剪枝 [kuangbin带你飞]专题二
题意:给定一些DNA序列,求一个最短序列能够包含所有序列. 思路:记录第i个序列已经被匹配的长度p[i],以及第i序列的原始长度len[i].则有两个剪枝: 剪枝1:直接取最长待匹配长度.1900ms ...
- HDU - 1067 Gap (bfs + hash) [kuangbin带你飞]专题二
题意: 起初定28张卡牌的排列,把其中11, 21, 31, 41移动到第一列,然后就出现四个空白,每个空白可以用它的前面一个数的下一个数填充,例如43后面的空格可以用44填充,但是47后面即 ...
- HDU - 2102 A计划 (BFS) [kuangbin带你飞]专题二
思路:接BFS判断能否在限制时间内到达公主的位置,注意如果骑士进入传送机就会被立即传送到另一层,不会能再向四周移动了,例如第一层的位置(x, y, 1)是传送机,第二层(x, y, 2)也是传送机,这 ...
随机推荐
- js promise看这篇就够了
一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时 ...
- 如何使用 highlight.js 高亮代码
highlight 是一款简单易用的 web 代码高亮插件,可以自动检测编程语言并高亮,兼容各种框架,可以说是十分强大了.下面就简单介绍一下如何使用这款插件. 两种使用方式: 1. 手动选择主题,官网 ...
- 关于word图片显示不全
问题:在编辑word时,在其中一行插入一张图片,但是显示不全. 原因:给文字行距设置成 [ 固定值 ]的原因. 解决方案:先删除图片,在插入图片的一行右键--> 段落,弹出对话框,找到设置行距的 ...
- 关于if和else嵌套—蛋疼
嵌套使用的时候else if和else遵循就近原则,和上面最靠近该语句的if语句匹配,要把else if看成是一个整体.就这么干,这样好理解一点. 一个if...else if...else语句中可以 ...
- MonogoDB 查询小结
MonogoDB是一种NoSQL数据库 优点: 1.数据的存储以json的文档进行存储(面向文档存储) 2.聚合框架查询速度快 3.高效存储二进制大对象 缺点: 1.不支持事务 2.文件存储空间占用过 ...
- SQL Server中计算表达式的和
项目使用的是SQL Server数据库,需要做一个审核规则,字段A中表达式的值和字段B中的值,做比较: 需求本身很简单,但是表达式中存在很多非法字符(非法全角,运算符,汉字--) eg:1.1.1*2 ...
- Cypher查询语言--Neo4j 入门 (一)
目录 操作符 参数 标识符 注解 Start 通过id绑定点 通过id绑定关系 通过id绑定多个节点 所有节点 通过索引查询获取节点 通过索引查询获取关系 多个开始点 Cypher是一个描述性的图形 ...
- 【linux之文件查看,操作】
一.shell如何处理命令 1.shell会根据在命令中出现的空格字符,将命令划分为多个部分 2.判断第一个字段是内部命令还是外部命令 内部命令:内置于shell的命令(shell builtin) ...
- BZOJ 3456: 城市规划 [多项式求逆元 组合数学 | 生成函数 多项式求ln]
3456: 城市规划 题意:n个点组成的无向连通图个数 以前做过,今天复习一下 令\(f[n]\)为n个点的无向连通图个数 n个点的完全图个数为\(2^{\binom{n}{2}}\) 和Bell数的 ...
- 「POJ2505」A multiplication game [博弈论]
题目链接:http://poj.org/problem?id=2505 题目大意: 两个人轮流玩游戏,Stan先手,数字 p从1开始,Stan乘以一个2-9的数,然后Ollie再乘以一个2-9的数,直 ...