原题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*算法的更多相关文章

  1. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  2. 【学时总结】 ◆学时·II◆ IDA*算法

    [学时·II] IDA*算法 ■基本策略■ 如果状态数量太多了,优先队列也难以承受:不妨再回头看DFS-- A*算法是BFS的升级,那么IDA*算法是对A*算法的再优化,同时也是对迭代加深搜索(IDF ...

  3. HDU3567 Eight II —— IDA*算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others)  ...

  4. The Rotation Game(IDA*算法)

    The Rotation Game Time Limit : 30000/15000ms (Java/Other)   Memory Limit : 300000/150000K (Java/Othe ...

  5. UVA-1343 The Rotation Game (IDA*)

    题目大意:数字1,2,3都有八个,求出最少的旋转次数使得图形中间八个数相同.旋转规则:对于每一长行或每一长列,每次旋转就是将数据向头的位置移动一位,头上的数放置到尾部.若次数相同,则找出字典序最小旋转 ...

  6. [poj2286]The Rotation Game (IDA*)

    //第一次在新博客里发文章好紧张怎么办 //MD巨神早已在一个小时前做完了 The Rotation Game Time Limit: 15000MS Memory Limit: 150000K To ...

  7. 7-12 The Rotation Game IDA*

    状态搜索题目  一开始打算用bfs  但是图给的不是矩形图  有点难以下手 参考了 lrj    将图上所有的点进行标号  直接一个一维数组就解决了图的问题  并且明确了每个点的标号  处理起来十分方 ...

  8. POJ2286 The Rotation Game[IDA*迭代加深搜索]

    The Rotation Game Time Limit: 15000MS   Memory Limit: 150000K Total Submissions: 6325   Accepted: 21 ...

  9. 八数码(IDA*算法)

    八数码 IDA*就是迭代加深和A*估价的结合 在迭代加深的过程中,用估计函数剪枝优化 并以比较优秀的顺序进行扩展,保证最早搜到最优解 需要空间比较小,有时跑得比A*还要快 #include<io ...

  10. HDU1560 DNA sequence —— IDA*算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Oth ...

随机推荐

  1. css-3列布局

    三列布局的步骤是,先定义左右两侧,然后定义中间,并设置'中间'部分的'margin'属性.并且'中间'部分不用设置'width'.例如: <!DOCTYPE html PUBLIC " ...

  2. if elsif;报错;new赋值

    1. IF INSERTING THEN          BEGIN 中间不能为空          END;ELSIF DELETING THEN         BEGIN          E ...

  3. Eclipse中看java源代码

    如何在Eclipse sdk中查看jar源代码如:*.jar 1.点 “window”-> "Preferences" -> "Java" -> ...

  4. idea配置tomcat.md

    [toc] 1.打开Edit Configurations,可以通过万能搜索快速进入!!! 2.添加服务器,在左上角找到Tomcat并添加 3.配置发布路径,Server标签页中填写完名称和路径,在D ...

  5. jQuery慢慢啃之事件(七)

    1.ready(fn)//当DOM载入就绪可以查询及操纵时绑定一个要执行的函数. $(document).ready(function(){ // 在这里写你的代码...}); 使用 $(docume ...

  6. python - StringIO文本缓冲

    参考:http://pymotwcn.readthedocs.org/en/latest/documents/StringIO.html 类StringIO提供了一个在内存中方便处理文本的类文件(读, ...

  7. Dev gridview 调整字体大小

    //调整表头字体大小 this.gridView1.Appearance.HeaderPanel.Font = new Font("Tahoma", 20, FontStyle.R ...

  8. 入门3:PHP环境开发搭建(windows)

    一.环境需要 硬件环境(最低配置): 双核CPU 8G内存 操作系统环境: Windows(64位)7+ Mac OS X 10.10+ Linux 64位(推荐Ubuntu 14 LTS) /**拓 ...

  9. PHP计划任务之关闭浏览器后仍然继续执行的函数 ignore_user_abort

    备忘一下这个函数: 函数名称:ignore_user_abort 本函数配置或取得使用端连接中断后,PHP 程序是否仍继续执行.默认值为中断连接后就停止执行.在 PHP 配置文件中 (php3.ini ...

  10. hdu 1229 超级大水题

      Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Desc ...