迭代加深搜索算法总结 + 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 ...
随机推荐
- static 方法.
If a subclass defines a static method with the same signature as a static method in the superclass, ...
- 【转】 UINavigationItem UINavigationBar 关系分析
原文:http://blog.csdn.net/luoyeffcs/article/details/16106707 目录 1.关系分析 2.关系综述 3.概念点 4.疑问 1.关系分析 UIBarI ...
- java——输入流FileInputStream
写一个简单的程序,实现从电脑中的一个盘里的文件中往程序中输入内容. package com.liaojianya.chapter5; import java.io.FileInputStream; i ...
- 1. mybatis批量插入数据
通过list <insert id="saveByList" useGeneratedKeys="true" parameterType="ja ...
- PHP 数组转JSON数据(convert array to JSON object);
<?php header('Content-type: appliction/json; charset=shift-JIS'); $data =array(); class Test { pu ...
- 『重构--改善既有代码的设计』读书笔记----Extract Class
在面向对象中,对于类这个概念我们应该有一个清晰的责任认识,就是每个类应该只有一个变化点,每个类的变化应该只受到单一的因素,即每个类应该只有一个明确的责任.当然了,说时容易做时难,很多人可能都会和我一样 ...
- [转]jQuery,javascript获得网页的高度和宽度
网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网页可见区域宽: document.body.offsetWi ...
- JQuery无法获取动态添加的图片宽度问题解决办法
$('.imgUl li,.v_img').click(function(){ var _left = 0; var _top = 0; $('body').append('<div class ...
- linux安装时提示发生不正常错误问题
跳过md5系统较检(每个系统版本都有一个md5编码唯一) 在安装CentOS时 提示 找不到磁盘,是否安装程序,选择安装程序进行"下一步" 提示: 发生不规则,不正常错误 原因:没 ...
- 安卓AVD使用建议
问题描述:之前在安装了Android开发环境后,一开始并没有直接在Android手机和平板上进行调试,是使用的AVD模拟器工具.由于电脑的配置不是特别好,总感觉AVD的使用速度太慢,包括启动的时候还有 ...