迭代加深搜索算法总结 + Editing a Book UVa11212题解
迭代加深搜索算法:
对于可以用回溯法解决,但是解答树结点数大的恐怖的问题的一种解决办法,有的问题甚至用bfs连一层节点都遍历不完就超时了。具体方法就是依次枚举搜索层数,从1到一个上限。
结构:
int solve() {
for (int maxd = 1; maxd < MAXN; maxd++) {
if (dfs(0, maxd)) return maxd;
}
return MAXN;
}
优点:
相较于bfs老老实实的枚举解答树而言, 迭代加深搜索算法可以以深度优先搜索,也就是说可以第一时间到达最深层次进行搜索。平均时间上而言比bfs逐层搜索要快太多太多了,再配合回溯剪枝。优化效果相当可观!
举例:
UVa11212 Editing a Book
对于这道题, 0 < n < 10, 也就是总状态有9! = 362880个。 虽然看起来很少,但是每个结点可以扩展到的结点个数是 (n * (n/2) * (n/2)) = (n^3)/4 ≈ 183, 再加上对每个结点判重和剪枝计算,每个结点的计算量大概是 183 * 40 = 7290
所以对于一组n = 9的数据,最差情况的计算量是 n! * (n^3)/4 * 40 ≈ 26亿
然而测试数据一共有20组
也就是说 总计算量是 26亿 * 20 = 520亿
即便我用bfs+剪枝, 程序还是毫无悬念的超时了。
然而如果我用迭代加深搜索算法,20组数据运行时间总和是49ms, 快了2000倍!
UVa11212 Editing a Book 迭代加深搜索+剪枝(49ms, Ac)
#include <cstdio>
#include <cstring>
using namespace std; int n, idx, maxd, a[];
bool ok; void create(int start, int len, int k) {
int olda[];
memcpy(olda, a, sizeof(a));
int z = , i = ;
for (; z < k; z++) {
if (z >= start && z < start + len) { z += (len - ); continue;}
a[i++] = olda[z];
}
for (z = ; z < len; z++) a[i++] = olda[start + z];
for (z = k; z < n; z++) {
if (z >= start && z < start + len) { z += (len - ); continue;}
a[i++] = olda[z];
}
} int num_unordered() {
int cnt = ;
for (int i = ; i < n; i++) if (a[i - ] + != a[i]) cnt++;
cnt = cnt ? cnt + : ;
return cnt;
} bool success() {
for (int i = ; i < n - ; i++) if (a[i] + != a[i + ]) return false;
return true;
} bool dfs(int d) {
if (d * + num_unordered() > * maxd) return false;
if (success()) { ok = ; return true;}
int temp[];
memcpy(temp, a, sizeof(a));
for (int i = ; i < n; i++)
for (int j = i + ; j <= n; j++)
for (int k = ; k <= n; k++) {
if (k >= i && k <= j) { k = j; continue;}
create(i, j - i, k);
if (dfs(d + )) return true;
memcpy(a, temp, sizeof(a));
}
return false;
} int solve() {
if (success()) return ;
ok = ;
for (maxd = ; maxd < ; maxd++)
if (dfs()) return maxd;
return maxd;
} int main() {
int T = ;
while (scanf("%d", &n) == && n) {
printf("Case %d: ", ++T);
for (int i = ; i < n; i++) scanf("%d", &a[i]);
int ans = solve();
printf("%d\n", ans);
}
return ;
}
UVa11212 Editing a Book BFS搜索+剪枝 (估计耗时18s)
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std; const int MAXN = , MAXHASHSIZE = ;
int n, idx, target;
int a[], _head[MAXHASHSIZE], _next[MAXN], st[MAXN]; struct Node {
int arr[], dis, num;
Node (int d = ): dis(d) {}
void trans() {
num = ;
for (int i = ; i < n; i++) {
num *= ;
num += arr[i];
}
}
}; bool try_to_insert(Node &cur) {
int h = cur.num % MAXHASHSIZE;
int u = _head[h];
while (u) {
if (st[u] == cur.num) return false;
u = _next[u];
}
st[idx] = cur.num;
_next[idx] = _head[h];
_head[h] = idx++;
return true;
} void create(Node &from, Node &des, int start, int len, int k) {
int z = , i = ;
for (; z < k; z++) {
if (z >= start && z < start + len) { z += (len - ); continue;}
des.arr[i++] = from.arr[z];
}
for (z = ; z < len; z++) des.arr[i++] = from.arr[start + z];
for (z = k; z < n; z++) {
if (z >= start && z < start + len) { z += (len - ); continue;}
des.arr[i++] = from.arr[z];
}
} bool impossible(Node &cur) {
int cnt = ;
for (int i = ; i < n; i++) if (cur.arr[i - ] + != cur.arr[i]) cnt++;
cnt = cnt ? cnt + : ;
return cnt > * ( - cur.dis);
} int bfs() {
queue<Node> q;
Node start;
for (int i = ; i < n; i++) start.arr[i] = a[i];
start.trans();
try_to_insert(start);
q.push(start);
while (!q.empty()) {
Node cur = q.front(); q.pop();
cur.trans();
if (cur.num == target) return cur.dis;
for (int i = ; i < n; i++)
for (int j = i + ; j <= n; j++)
for (int k = ; k <= n; k++) {
if (k >= i && k <= j) { k = j; continue;}
Node nextn;
create(cur, nextn, i, j - i, k);
nextn.trans();
if (!impossible(nextn) && try_to_insert(nextn)) {
nextn.dis = cur.dis + ;
q.push(nextn);
}
}
}
return ;
} int main() {
int T = ;
while (scanf("%d", &n) == && n) {
printf("Case %d: ", ++T);
target = idx = ;
for (int i = ; i < n; i++) {
scanf("%d", &a[i]);
target *= ;
target += i + ;
}
memset(_head, , sizeof(_head));
int ans = bfs();
printf("%d\n", ans);
}
return ;
}
迭代加深搜索算法总结 + Editing a Book UVa11212题解的更多相关文章
- 埃及分数问题(带乐观估计函数的迭代加深搜索算法-IDA*)
#10022. 「一本通 1.3 练习 1」埃及分数 [题目描述] 在古埃及,人们使用单位分数的和(形如 $\dfrac{1}{a}$ 的,$a$ 是自然数)表示一切有理数.如:$\dfrac{ ...
- 人工智能搜索算法(深度优先、迭代加深、一致代价、A*搜索)
搜索算法问题求解 一.需求分析 分别用深度优先.迭代加深.一致代价.A*搜索算法得到从起始点Arad到目标点Bucharest的一条路径,即为罗马尼亚问题的一个解,在求解的过程中记录每种算法得到的解, ...
- UVA 11212 Editing a Book [迭代加深搜索IDA*]
11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange the ...
- 7-10Editing aBook uva11212(迭代加深搜索 IDA*)
题意: 给出n( 2<=n<=9) 个乱序的数组 要求拍成升序 每次 剪切一段加上粘贴一段算一次 拍成1 2 3 4 ...n即可 求排序次数 典型的状态空间搜索问题 ...
- uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索
迭代加深搜索 自己看的时候第一遍更本就看不懂..是非常水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题而且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的 ...
- 算法复习——迭代加深搜索(骑士精神bzoj1085)
题目: Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相 ...
- POJ1129Channel Allocation[迭代加深搜索 四色定理]
Channel Allocation Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14601 Accepted: 74 ...
- BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]
1085: [SCOI2005]骑士精神 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1800 Solved: 984[Submit][Statu ...
- 迭代加深搜索 POJ 1129 Channel Allocation
POJ 1129 Channel Allocation Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14191 Acc ...
随机推荐
- 微软企业库Microsoft Enterprise Library的相关文章链接
微软企业库4.1学习笔记 http://blog.csdn.net/anyqu/article/category/1228691/3 黄聪:Enterprise Library 5.0 系列教程 ww ...
- 利用Graphviz 画结构图[转]
转自:http://www.cnblogs.com/sld666666/archive/2010/06/25/1765510.html 利用Graphviz 画结构图 1. Graphviz介绍 ...
- iOS中ARC内部原理
ARC会自动插入retain和release语句.ARC编译器有两部分,分别是前端编译器和优化器. 1. 前端编译器 前端编译器会为“拥有的”每一个对象插入相应的release语句.如果对象的所有权修 ...
- 嵌入式css样式,写在当前的文件中
现在有一任务,把下面的“超酷的互联网”.“服务及时贴心”.“有趣易学”这三个短词文字字号修改为18px. 如果用内联式css样式的方法进行设置将是一件很头疼的事情(为每一个<span>标签 ...
- iOS9适配中出现的一些常见问题
本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版,随着有用户陆续升级 ...
- FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题
现在ios里使用的数据库一般都是Sqlite,但是使用Sqlite有个不太好的地方就是在多线程的时候,会出现问题,sqlite只能打开一个读或者写连结.这样的话多线程就会碰到资源占用的问题. 最开始是 ...
- linxu 挂载分区
1. 添加新硬盘 设置 -> Storage -> SATA控制器->右击,选择“添加虚拟硬盘” 然后,根据需求创建合适的硬盘 2. 重启虚拟机 查看现有系统的磁盘空间 sudo f ...
- sql语句复制表
1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表 这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete from newtable; ...
- html embed用法
(一).基本语法: embed src=url 说明:embed可以用来插入各种多媒体,格式可以是 Midi.Wav.AIFF.AU.MP3等等, Netscape及新版的IE 都支持.u ...
- 响应式设计的5个CSS实用技巧
正如我在教程响应式Web设计三步走当中所讲的,响应式的Web设计其实并不难,但是要让元素在布局切换时能够平滑过渡就比较考验技巧了.现在我分享在编码时常用的五个CSS技巧并举例说明.这些技巧都是使用简单 ...