POJ 2286 搜索 (IDA*)
2015-10-07 20:06
218 查看
题意:
旋转游戏在一个井字形的棋盘上进行,棋盘上有 24 块,每块都标着 1, 2, 3 中的一个,并且对于每个数字,恰好有 8 块标着它。
一开始,所有的块是随机码放在棋盘上的。你的任务即为移动这些块,使得包围着正中心空格的 8 块都标有同样的数字。
移动的方式只有一种,即为“旋转”井字形四列中的一列。所谓“旋转”就是指,将这一列中的所有块向两个方向之一移动一格,并将移出棋盘的那一块放置到这一列的最后。所以,共有 8 种旋转的方式,分别标为 A 到 H。
图(见poj原题中0.0)中标明了两步,从初始状态进行 A, C 两步移动即可满足要求。你的任务即为解决这一谜题。
这道题帮助我进一步理解了IDA*。不过是靠着刘汝佳叔叔的代码自己才A的这道题。而且还白痴地因为在不需要移动的情况时只输出了`No moves needed’ 而没输出中心的数字而W好多次。不是这个细节就可以1A..T^T
这个题就是搜到第一个有解的情况的那一种搜索,而我们控制搜索顺序使得搜到的第一个解为最优解(最短且字典序最小)。
不知道为什么我的代码跑的比刘汝佳叔叔的快而且内存还小,我为了省事,使用了很不提倡的做法:函数传递数组+每层递归里新开一个数组。保险一点的做法还是像刘汝佳叔叔一样再写一个rerotate数组。
h函数使用的比较“保守”,最多只能估测不到8层——在我们不知道最长的答案是多少的情况下。一开始我开的1005,之后又换成105交了一次仍然可以,再换成25还是可以(逗X在自娱自乐)。这么看来,这个h函数性能还是很好的。就是h() = min(dif(1), dif(2), dif(3))。dif(i)表示中心8个数字中与i不同的数字。含义就是,当前中心8个数字中最多的是i,有k个,假设我们每旋转一次就使得k++,h()返回还需要旋转的次数。很显然,真实情况是不会小于h()返回的这个值的,所以正确性得证。
旋转游戏在一个井字形的棋盘上进行,棋盘上有 24 块,每块都标着 1, 2, 3 中的一个,并且对于每个数字,恰好有 8 块标着它。
一开始,所有的块是随机码放在棋盘上的。你的任务即为移动这些块,使得包围着正中心空格的 8 块都标有同样的数字。
移动的方式只有一种,即为“旋转”井字形四列中的一列。所谓“旋转”就是指,将这一列中的所有块向两个方向之一移动一格,并将移出棋盘的那一块放置到这一列的最后。所以,共有 8 种旋转的方式,分别标为 A 到 H。
图(见poj原题中0.0)中标明了两步,从初始状态进行 A, C 两步移动即可满足要求。你的任务即为解决这一谜题。
这道题帮助我进一步理解了IDA*。不过是靠着刘汝佳叔叔的代码自己才A的这道题。而且还白痴地因为在不需要移动的情况时只输出了`No moves needed’ 而没输出中心的数字而W好多次。不是这个细节就可以1A..T^T
这个题就是搜到第一个有解的情况的那一种搜索,而我们控制搜索顺序使得搜到的第一个解为最优解(最短且字典序最小)。
不知道为什么我的代码跑的比刘汝佳叔叔的快而且内存还小,我为了省事,使用了很不提倡的做法:函数传递数组+每层递归里新开一个数组。保险一点的做法还是像刘汝佳叔叔一样再写一个rerotate数组。
h函数使用的比较“保守”,最多只能估测不到8层——在我们不知道最长的答案是多少的情况下。一开始我开的1005,之后又换成105交了一次仍然可以,再换成25还是可以(逗X在自娱自乐)。这么看来,这个h函数性能还是很好的。就是h() = min(dif(1), dif(2), dif(3))。dif(i)表示中心8个数字中与i不同的数字。含义就是,当前中心8个数字中最多的是i,有k个,假设我们每旋转一次就使得k++,h()返回还需要旋转的次数。很显然,真实情况是不会小于h()返回的这个值的,所以正确性得证。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; char ans[1005]; int pos, maxd, beg[24]; int center[9] = {0, 6, 7, 8, 11, 12, 15, 16, 17}; int r[8][24] = { {2, 1, 6, 3, 4, 5, 11, 7, 8, 9, 10, 15, 12, 13, 14, 20, 16, 17, 18, 19, 22, 21, 0, 23}, {0, 3, 2, 8, 4, 5, 6, 7, 12, 9, 10, 11, 17, 13, 14, 15, 16, 21, 18, 19, 20, 23, 22, 1}, {0, 1, 2, 3, 10, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 19, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23}, {0, 23, 2, 1, 4, 5, 6, 7, 3, 9, 10, 11, 8, 13, 14, 15, 16, 12, 18, 19, 20, 17, 22, 21}, {22, 1, 0, 3, 4, 5, 2, 7, 8, 9, 10, 6, 12, 13, 14, 11, 16, 17, 18, 19, 15, 21, 20, 23}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 13, 20, 21, 22, 23}, {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, }; int h(int *n){ int res = 8; for(int end = 1; end <= 3; end++){ int t = 0; for(int i = 1; i <= 8; i++){ t += end != n[center[i]]; } res = min(res, t); } return res; } bool ok(int *n){ pos = n[center[1]]; for(int i = 1; i <= 8; i++){ if(n[center[i]] != pos) return 0; } return 1; } bool dfs(int *n, int ed){ if(ed + h(n) > maxd) return 0; if(ok(n)){ ans[ed] = '\0'; printf("%s\n", ans); return 1; } for(int i = 0; i < 8; i++){ ans[ed] = 'A' + i; int k[24]; for(int j = 0; j < 24; j++){ k[j] = n[r[i][j]]; } if(dfs(k, ed+1)) return 1; } return 0; } int main() { while(scanf("%d", beg) && beg[0]){ for(int i = 1; i < 24; i++){ scanf("%d", beg + i); } if(ok(beg)){ puts("No moves needed"); printf("%d\n", pos); continue; } for(maxd = 1; ; maxd++){ if(dfs(beg, 0)){ printf("%d\n", pos); break; } } } }
相关文章推荐
- 搜狗百度360市值齐跌:搜索引擎们陷入集体焦虑?
- 本人即将筹备败家日志,敬请期待!
- IE:使用搜索助手
- C++深度优先搜索的实现方法
- 基于文本的搜索
- php实现搜索一维数组元素并删除二维数组对应元素的方法
- 使用Sphinx对索引进行搜索
- asp 多关键词搜索的简单实现方法
- C#使用foreach语句搜索数组元素的方法
- JavaScript中数组的排序、乱序和搜索实现代码
- C#编程实现Excel文档中搜索文本内容的方法及思路
- sqlserver中在指定数据库的所有表的所有列中搜索给定的值
- 可以用来搜索当前页面内容的js代码
- 全文搜索和替换
- javascript搜索自动提示功能的实现第1/3页
- mysql 模糊搜索的方法介绍
- C#搜索文字在文件及文件夹中出现位置的方法
- 基于ASP.NET的lucene.net全文搜索实现步骤
- 做个自己站内搜索引擎
- PHP查找与搜索数组元素方法总结