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 ...
随机推荐
- Registry 类
提供表示 Windows 注册表中的根项的 RegistryKey 对象,并提供访问项/值对的 static 方法. 继承层次结构 System.Object Microsoft.Win32.Re ...
- StarUML启动报RPC服务器不可用错误
有很多人说启动 Remote Procedure Call (RPC) 服务即可,还是我试过了没有起作用,后来网友说,启动Print Spooler就可以了,暂时解决了问题.
- clientX 属性.
Syntax: event.clientX The clientX event attribute returns the horizontal coordinate (according to th ...
- 安装SQL Server2008时 检测时有“重启计算机”失败
第一种解决方案: 在学校的时候 遇到这种问题的解决办法是: 卸载VS,先安装SQL Server 2008 再安装VS 就行了: 第二种解决方案: 如果已经安装过VS,在安装SQL Server200 ...
- java 保留小数点后N位数(若干位),几种实现的方式总结
import java.math.BigDecimal;import java.text.DecimalFormat;import java.text.NumberFormat;/** * java ...
- javascript——迭代方法
<script type="text/javascript"> //五个迭代方法 都接受两个参数:要在每一项上运行的函数 和 运行该函数的作用域(可选) //every ...
- 第四篇、Tomcat 集群
1. 前言 该篇中测试的机器发生了变更,在第一篇中设置的Apache DocumentRoot "d:/deployment"修改为了DocumentRoot d:/clust ...
- OC文件操作(2)
NSFileManager 文件管理器完成文件的创建.移动.拷贝等管理操作 1.查询文件和目录 OC中查询路径下的目录主要分为浅度遍历和深度遍历. 浅度遍历 NSFileManager * ma ...
- CSS3的过渡效果(transition)与动画(animation)
1.Transition Transition是一种直观上的效果,让DOM元素的某个属性在固定时间内从一旧值到一新值.目前Firefox.Opera.Safari和Chrome都支持transitio ...
- php基础知识【函数】(8)xml和变量函数
一.XML函数 参数类型 data --string,需要解析的数据集. parser --resource,一个指向要取得字节索引的 XML 解析器的引用. 1.创建和释放XMl解析器 ...