HDU3567 Eight II —— IDA*算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567
Eight II
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 130000/65536 K (Java/Others)
Total Submission(s): 3420 Accepted Submission(s): 742
In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid which can be represented as an 'X'. Tiles in grids having a common edge with the blank grid can be moved into
that blank grid. This operation leads to an exchange of 'X' with one tile.
We use the symbol 'r' to represent exchanging 'X' with the tile on its right side, and 'l' for the left side, 'u' for the one above it, 'd' for the one below it.
A state of the board can be represented by a string S using the rule showed below.
The problem is to operate an operation list of 'r', 'u', 'l', 'd' to turn the state of the board from state A to state B. You are required to find the result which meets the following constrains:
1. It is of minimum length among all possible solutions.
2. It is the lexicographically smallest one of all solutions of minimum length.
The input of each test case consists of two lines with state A occupying the first line and state B on the second line.
It is guaranteed that there is an available solution from state A to B.
The first line is in the format of "Case x: d", in which x is the case number counted from one, d is the minimum length of operation list you need to turn A to B.
S is the operation list meeting the constraints and it should be showed on the second line.
12X453786
12345678X
564178X23
7568X4123
dd
Case 2: 8
urrulldr
题解:
POJ1077 的强化版。
问:为什么加了vis判重比不加vis判重还要慢?
答:因为当引入vis判重时,就需要知道棋盘的状态,而计算一次棋盘的状态,就需要增加(8+7+……1)次操作,结果得不偿失。
更新:其实IDA*算法不能加vis判重,因为IDA*的本质就是dfs, 根据dfs的特性, 第一次被访问所用的步数并不一定是最少步数,所以如果加了vis判重,就默认取了第一次被访问时所用的步数,而这个步数不一定是最优的。所以第二份代码是错误的,即使过了oj的数据。
未加vis判重(202MS):
2017-09-10 10:25:57 | Accepted | 3567 | 202MS | 1712K |
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- #include <vector>
- #include <queue>
- #include <stack>
- #include <map>
- #include <string>
- #include <set>
- #define ms(a,b) memset((a),(b),sizeof((a)))
- using namespace std;
- typedef long long LL;
- const int INF = 2e9;
- const LL LNF = 9e18;
- const int MOD = 1e9+;
- const int MAXN = 1e6+;
- //M为棋盘, pos_goal为目标状态的每个数字所在的位置, pos_goal[dig] = pos,
- //即表明:在目标状态中,dig所在的位置为pos。pos_goal与M为两个互逆的数组。
- int M[MAXN], pos_goal[MAXN];
- int fac[] = { , , , , , , , , };
- int dir[][] = { ,, ,-, ,, -, };
- char op[] = {'d', 'l', 'r', 'u' };
- int 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+;
- }
- int dis_h(int s[]) //获得曼哈顿距离
- {
- int dis = ;
- for(int i = ; i<; i++)
- if(s[i]!=)
- {
- int x = i/, y = i%;
- int xx = pos_goal[s[i]]/, yy = pos_goal[s[i]]%; //此处须注意
- dis += abs(x-xx) + abs(y-yy);
- }
- return dis;
- }
- char path[];
- int kase, nextd;
- bool IDAstar(int loc, int depth, int pre, int limit)
- {
- int h = dis_h(M);
- if(depth+h>limit)
- {
- nextd = min(nextd, depth+h);
- return false;
- }
- if(h==)
- {
- path[depth] = '\0';
- printf("Case %d: %d\n", kase, depth);
- puts(path);
- return true;
- }
- int x = loc/;
- int y = loc%;
- for(int i = ; i<; i++)
- {
- if(i+pre==) continue; //方向与上一步相反, 剪枝
- int xx = x + dir[i][];
- int yy = y + dir[i][];
- if(xx>= && xx<= && yy>= && yy<=)
- {
- int tmploc = xx*+yy;
- swap(M[loc], M[tmploc]);
- path[depth] = op[i];
- if(IDAstar(xx*+yy, depth+, i, limit))
- return true;
- swap(M[loc], M[xx*+yy]);
- }
- }
- return false;
- }
- int main()
- {
- int T;
- char str[];
- scanf("%d",&T);
- for(kase = ; kase<=T; kase++)
- {
- int loc;
- scanf("%s", str);
- for(int i = ; i<; i++)
- {
- if(str[i]=='X') M[i] = , loc = i;
- else M[i] = str[i]-'';
- }
- scanf("%s", str);
- for(int i = ; i<; i++)
- {
- if(str[i]=='X') pos_goal[] = i;
- else pos_goal[str[i]-''] = i;
- }
- for(int limit = dis_h(M); ; limit = nextd) //迭代加深搜
- {
- nextd = INF;
- if(IDAstar(loc, , INF, limit))
- break;
- }
- }
- }
加了vis判重(936MS)
2017-09-10 10:26:10 | Accepted | 3567 | 936MS | 5620K |
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- #include <vector>
- #include <queue>
- #include <stack>
- #include <map>
- #include <string>
- #include <set>
- #define ms(a,b) memset((a),(b),sizeof((a)))
- using namespace std;
- typedef long long LL;
- const int INF = 2e9;
- const LL LNF = 9e18;
- const int MOD = 1e9+;
- const int MAXN = 1e6+;
- int M[MAXN], pos_goal[MAXN];
- int fac[] = { , , , , , , , , };
- int dir[][] = { ,, ,-, ,, -, };
- char op[] = {'d', 'l', 'r', 'u' };
- int 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+;
- }
- int dis_h(int s[]) //获得曼哈顿距离
- {
- int dis = ;
- for(int i = ; i<; i++)
- if(s[i]!=)
- {
- int x = i/, y = i%;
- int xx = pos_goal[s[i]]/, yy = pos_goal[s[i]]%;
- dis += abs(x-xx) + abs(y-yy);
- }
- return dis;
- }
- char path[];
- int kase, nextd, vis[MAXN];
- bool IDAstar(int loc, int depth, int pre, int limit)
- {
- int h = dis_h(M);
- if(depth+h>limit)
- {
- nextd = min(nextd, depth+h);
- return false;
- }
- if(h==)
- {
- path[depth] = '\0';
- printf("Case %d: %d\n", kase, depth);
- puts(path);
- return true;
- }
- int x = loc/;
- int y = loc%;
- for(int i = ; i<; i++)
- {
- if(i+pre==) continue; //方向与上一步相反, 剪枝
- int xx = x + dir[i][];
- int yy = y + dir[i][];
- if(xx>= && xx<= && yy>= && yy<=)
- {
- int tmploc = xx*+yy;
- swap(M[loc], M[tmploc]);
- int status = cantor(M);
- if(!vis[status])
- {
- vis[status] = ;
- path[depth] = op[i];
- if(IDAstar(xx*+yy, depth+, i, limit))
- return true;
- vis[status] = ;
- }
- swap(M[loc], M[xx*+yy]);
- }
- }
- return false;
- }
- int main()
- {
- int T;
- char str[];
- scanf("%d",&T);
- for(kase = ; kase<=T; kase++)
- {
- int loc;
- scanf("%s", str);
- for(int i = ; i<; i++)
- {
- if(str[i]=='X') M[i] = , loc = i;
- else M[i] = str[i]-'';
- }
- scanf("%s", str);
- for(int i = ; i<; i++)
- {
- if(str[i]=='X') pos_goal[] = i;
- else pos_goal[str[i]-''] = i;
- }
- vis[cantor(M)] = ;
- for(int limit = dis_h(M); ; limit = nextd) //迭代加深搜
- {
- nextd = INF;
- ms(vis,);
- if(IDAstar(loc, , INF, limit))
- break;
- }
- }
- }
HDU3567 Eight II —— IDA*算法的更多相关文章
- 【学时总结】 ◆学时·II◆ IDA*算法
[学时·II] IDA*算法 ■基本策略■ 如果状态数量太多了,优先队列也难以承受:不妨再回头看DFS-- A*算法是BFS的升级,那么IDA*算法是对A*算法的再优化,同时也是对迭代加深搜索(IDF ...
- HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法
先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...
- LEETCODE —— Best Time to Buy and Sell Stock II [贪心算法]
Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...
- HDU4513 吉哥系列故事——完美队形II Manacher算法
题目链接:https://vjudge.net/problem/HDU-4513 吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others) Me ...
- 八数码(IDA*算法)
八数码 IDA*就是迭代加深和A*估价的结合 在迭代加深的过程中,用估计函数剪枝优化 并以比较优秀的顺序进行扩展,保证最早搜到最优解 需要空间比较小,有时跑得比A*还要快 #include<io ...
- HDU1560 DNA sequence —— IDA*算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Oth ...
- IDA*算法——骑士精神
例题 骑士精神 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者 ...
- UVA - 11212 Editing a Book(IDA*算法+状态空间搜索)
题意:通过剪切粘贴操作,将n个自然段组成的文章,排列成1,2,……,n.剪贴板只有一个,问需要完成多少次剪切粘贴操作可以使文章自然段有序排列. 分析: 1.IDA*搜索:maxn是dfs的层数上限,若 ...
- 还不会ida*算法?看完这篇或许能理解点。
IDA* 算法分析 IDA* 本质上就是带有估价函数和迭代加深优化的dfs与,A * 相似A *的本质便是带 有估价函数的bfs,估价函数是什么呢?估价函数顾名思义,就是估计由目前状态达 到目标状态的 ...
随机推荐
- MySQL-JDBC Loadbalance深入解析
背景说明 公司的整个电商系统搭建在华为云上,根据老总的估计,上线3个月之后日订单量会达到百万级别,保守估计3个月之后总订单个数预计会有5千万.MySQL单表达到千万级别,就会出现明显的性能问题.根据如 ...
- MySQL的LOOP, LEAVE 和ITERATE语句(类似Continue、Break的写法)
和REPEAT和while语句不同,LOOP.LEAVE.ITERATE更像其他编程语言中的goto语句. LOOP要设定一个label指定循环的开始位置,而LEAVE则像其他语言中的Break会离开 ...
- 洛谷——P2049 魔术棋子
P2049 魔术棋子 题目描述 在一个M*N的魔术棋盘中,每个格子中均有一个整数,当棋子走进这个格子中,则此棋子上的数会被乘以此格子中的数.一个棋子从左上角走到右下角,只能向右或向下行动,请问此棋子走 ...
- 基于R-Tree的最近邻查询
转自基于R-Tree的最近邻查询 BAB(Branch.and.Band)算法是由Nick Roussopoulousnl等人于1995年提出的,是最早的基于R.树的静态最近邻查询算法.该算法使用MI ...
- 如何通过SQL注入获取服务器本地文件
写在前面的话 SQL注入可以称得上是最臭名昭著的安全漏洞了,而SQL注入漏洞也已经给整个网络世界造成了巨大的破坏.针对SQL漏洞,研究人员也已经开发出了多种不同的利用技术来实施攻击,包括非法访问存储在 ...
- react 创建组件 (四)Stateless Functional Component
上面我们提到的创建组件的方式,都是用来创建包含状态和用户交互的复杂组件,当组件本身只是用来展示,所有数据都是通过props传入的时候,我们便可以使用Stateless Functional Compo ...
- Eclipse - 循环cin的输出怎样终止
循环cin的输出怎样终止 本文地址: http://blog.csdn.net/caroline_wendy Eclipse中, 使用CDT编写C++代码时, 循环(while)cin输入程序, 须要 ...
- h5 录音 自动生成proto Js语句 UglifyJS-- 对你的js做了什么 【原码笔记】-- protobuf.js 与 Long.js 【微信开发】-- 发送模板消息 能编程与会编程 vue2入坑随记(二) -- 自定义动态组件 微信上传图片
得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...
- POJ 1151 HDU 1542 Atlantis(扫描线)
题目大意就是:去一个地方探险,然后给你一些地图描写叙述这个地方,每一个描写叙述是一个矩形的右下角和左上角.地图有些地方是重叠的.所以让你求出被描写叙述的地方的总面积. 扫描线的第一道题,想了又想,啸爷 ...
- Mmseg中文分词算法解析
Mmseg中文分词算法解析 @author linjiexing 开发中文搜索和中文词库语义自己主动识别的时候,我採用都是基于mmseg中文分词算法开发的Jcseg开源project.使用场景涉及搜索 ...