Uva1343-The Rotation Game-IDA*算法
原题https://uva.onlinejudge.org/external/13/1343.pdf
题意:
有个#字型的棋盘,2行2列,一共24个格。

如图:每个格子是1或2或3,一共8个1,8个2,8个3.
有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面。
求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字。如果有多个解,输出字典序最小的操作步骤。
分析:
很明显的一个状态空间搜索问题,不过可以注意到,虽然每一个状态有八个可能的后续状态,随着操作数n的增加,总状态数 8^n 还是大得可怕。比如当n=11时,总状态为8^11 = 85亿。就算通过自己创建特制的哈希表进行状态判重,优化效果并不明显,因为最近一直在做状态空间搜索问题,即使用bfs+剪枝+哈希表,这些程序都无一例外的超时了,所以现在看到状态空间搜索问题,如果没有特别好的剪枝,我绝对不敢用bfs了.....
回到这道题,所有可以用bfs,回溯解决的问题,尤其是解答树的结点数没有明显上限的题,选择用迭代加深搜索算法都特别好用(原因可以参考我上一篇文章)。这里IDA*(迭代加深A*算法)其实说白了就是迭代加深+剪枝.
A*算法是对于每一步考虑 g(n) + h()和MAXD的关系。
稍微解释一下,g(n)是从起点到当前状态的总步数,MAXD是我们提前通过计算证明得到的最短路线总步数的上限,h()是启发函数,是整个算法的关键,我们设计的h()可以预估从当前状态到目标状态至少需要的步数。
这样,上面的关系式就很好理解了。g(n) + h() > MAXD 意味着当前已经走的步数+至少还需要的步数 > 我可以走的步数上限,这种状态,必然已经没有继续的必要,回溯。
对于这道题,可以注意到,对于每一次操作,我们最多可以让中心格子多一个目标数字,如果当前中心格子待整理的数字个数大于我们还可以走的步数,回溯。
这样,就得到了
if (d + num_unordered() > MAXD) return false;
这一核心剪枝公式。 剩下的就简单了。
代码只有52行,还是很简洁的。而且运行速度很快。过30组数据只用了126ms.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = , LEN = ;
int board[LEN][LEN - ] = { {, , , , , , }, {, , , , , , },
{, , , , , , }, {, , , , , , },
{, , , , , , }, {, , , , , , },
{, , , , , , }, {, , , , , , } };
int check_order[] = {, , , , , , , }, a[MAXN], maxd;
char order[]; int unordered() {
int n1 = , n2 = , n3 = ;
for (int i = ; i < LEN; i++)
if (a[check_order[i]] == ) n1++;
else if (a[check_order[i]] == ) n2++;
else n3++;
return LEN - max(max(n1, n2), n3);
} void rotate(int di) {
int t = a[board[di][]];
for (int i = ; i < LEN - ; i++) a[board[di][i - ]] = a[board[di][i]];
a[board[di][LEN - ]] = t;
} bool dfs(int d) {
int cnt = unordered();
if (!cnt) return true;
if (cnt + d > maxd) return false;
int temp[MAXN]; memcpy(temp, a, sizeof(a));
for (int i = ; i < LEN; i++) {
rotate(i);
order[d] = i + 'A';
if (dfs(d + )) return true;
memcpy(a, temp, sizeof(a));
}
return false;
} int main() {
freopen("in", "r", stdin);
while (scanf("%d", &a[]) && a[]) {
for (int i = ; i < MAXN; i++) scanf("%d", &a[i]);
if (!unordered()) { printf("No moves needed\n%d\n", a[]); continue;}
for (maxd = ;; maxd++) if (dfs()) break;
for (int i = ; i < maxd; i++) printf("%c", order[i]);
printf("\n%d\n", a[]);
}
return ;
}

顺便纪念一下排第六(前面3个是virtual oj......)
Uva1343-The Rotation Game-IDA*算法的更多相关文章
- HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法
先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...
- 【学时总结】 ◆学时·II◆ IDA*算法
[学时·II] IDA*算法 ■基本策略■ 如果状态数量太多了,优先队列也难以承受:不妨再回头看DFS-- A*算法是BFS的升级,那么IDA*算法是对A*算法的再优化,同时也是对迭代加深搜索(IDF ...
- HDU3567 Eight II —— IDA*算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others) ...
- The Rotation Game(IDA*算法)
The Rotation Game Time Limit : 30000/15000ms (Java/Other) Memory Limit : 300000/150000K (Java/Othe ...
- UVA-1343 The Rotation Game (IDA*)
题目大意:数字1,2,3都有八个,求出最少的旋转次数使得图形中间八个数相同.旋转规则:对于每一长行或每一长列,每次旋转就是将数据向头的位置移动一位,头上的数放置到尾部.若次数相同,则找出字典序最小旋转 ...
- [poj2286]The Rotation Game (IDA*)
//第一次在新博客里发文章好紧张怎么办 //MD巨神早已在一个小时前做完了 The Rotation Game Time Limit: 15000MS Memory Limit: 150000K To ...
- 7-12 The Rotation Game IDA*
状态搜索题目 一开始打算用bfs 但是图给的不是矩形图 有点难以下手 参考了 lrj 将图上所有的点进行标号 直接一个一维数组就解决了图的问题 并且明确了每个点的标号 处理起来十分方 ...
- POJ2286 The Rotation Game[IDA*迭代加深搜索]
The Rotation Game Time Limit: 15000MS Memory Limit: 150000K Total Submissions: 6325 Accepted: 21 ...
- 八数码(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 ...
随机推荐
- LaTeX 中插入数学公式
一.常用的数学符号 1.小写希腊字母 \alpha \nu \beta \xi \gamma o \delta \pi \epsilon \rho \zeta \sigma \eta \tau \th ...
- VS2015 Cordova Ionic移动开发(二)
一.创建空白Cordova应用 打开VS,选择[新建项目],选择其它语言JavaScript或者TypeScript,语言的话就按个人喜好,喜欢JS就用JS,喜欢TS就用TS,推荐使用TS书写,代码结 ...
- java simple check whether a file or directory.
Ref: check whether a file or directory First, make sure the path exists by using: new File(path).ex ...
- 函数对象的prototype总结
通过看 http://www.cnblogs.com/mindsbook/archive/2009/09/19/javascriptYouMustKnowPrototype.html 该文章和对代码的 ...
- 工欲善其事必先利其器之Xcode高效插件和舒适配色
功能强大的Xcode再配上高效的插件,必会让你的开发事半功倍.直接进入正题. Xcode插件安装方式: 1.github下载插件然后用xcode打开运行一遍,然后重启xcode. 2.安装插件管理Al ...
- 【转】 iOS开发之手势gesture详解
原文:http://www.cnblogs.com/salam/archive/2013/04/30/iOS_gesture.html 前言 在iOS中,你可以使用系统内置的手势识别 (Gesture ...
- iOS单例的两种实现
单例模式算是开发中比较常见的一种模式了.在iOS中,单例有两种实现方式(至少我目前只发现两种).根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_o ...
- cocos2d中如何使用图片纹理图集的加载来实现一个动画的功能
cocos2d中要实现一个动画,一般采用纹理图集的方式,也就是说把几个连续动作的图片挨个显示切换这样就是动画 一: 首先先看下今天要实现的具体的目的,打飞机的时间屏幕上会有一个喷火的小飞机,飞机的尾部 ...
- STL库list::sort()实现深度解析
原创,转载请注明出处:STL库list::sort()实现深度解析 list模板的定义以及一些基本成员函数的实现这里我就不赘述了,还不清楚的同学可以到网上查找相关资料或者直接查看侯捷翻译的<ST ...
- java获取数据库数据表的元数据
Connction conn; DatabaseMetaData dmd=conn.getMetaData();//获取数据库元数据 PreparedStatment ps; ps.getParame ...