迭代加深搜索算法:

对于可以用回溯法解决,但是解答树结点数大的恐怖的问题的一种解决办法,有的问题甚至用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题解的更多相关文章

  1. 埃及分数问题(带乐观估计函数的迭代加深搜索算法-IDA*)

    #10022. 「一本通 1.3 练习 1」埃及分数 [题目描述] 在古埃及,人们使用单位分数的和(形如 $\dfrac{1}{a}​$​​ 的,$a$ 是自然数)表示一切有理数.如:$\dfrac{ ...

  2. 人工智能搜索算法(深度优先、迭代加深、一致代价、A*搜索)

    搜索算法问题求解 一.需求分析 分别用深度优先.迭代加深.一致代价.A*搜索算法得到从起始点Arad到目标点Bucharest的一条路径,即为罗马尼亚问题的一个解,在求解的过程中记录每种算法得到的解, ...

  3. 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 ...

  4. 7-10Editing aBook uva11212(迭代加深搜索 IDA*)

    题意:  给出n( 2<=n<=9) 个乱序的数组  要求拍成升序  每次 剪切一段加上粘贴一段算一次  拍成1 2 3 4 ...n即可     求排序次数 典型的状态空间搜索问题   ...

  5. uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索

    迭代加深搜索 自己看的时候第一遍更本就看不懂..是非常水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题而且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的 ...

  6. 算法复习——迭代加深搜索(骑士精神bzoj1085)

    题目: Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相 ...

  7. POJ1129Channel Allocation[迭代加深搜索 四色定理]

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14601   Accepted: 74 ...

  8. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

  9. 迭代加深搜索 POJ 1129 Channel Allocation

    POJ 1129 Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14191   Acc ...

随机推荐

  1. linux教程:配置Tomcat开机启动

    我们在linux下安装好tomcat之后:经常是需要配置到开机启动的: 这样的话就不需要我们每次重启linux服务器之后自己在登陆运行startup.sh文件启动tomcat了 本次的演示环境是在ce ...

  2. 记一次网站服务器迁移(my)

    遇到的难题: 基本没有遇到太大的问题,因为服务器环境是配好的阿里云环境,最后再nginx的rewrite配置遇到了一点问题,最后也算解决. 收获小点: 1) vim替换命令: 利用 :s 命令可以实现 ...

  3. PV、UV、IP的区别

    网站推广需要一个网站访问统计工具,常用的统计工具有百度统计.51la.量子恒道统计等.网站访问量常用的指标为PV.UV.IP.那么什么是PV.UV和IP,PV.UV.IP的区别是什么? --首先来看看 ...

  4. Xaml中的资源(1 样式)

    <Window x:Class="MyResoures.MainWindow" xmlns="http://schemas.microsoft.com/winfx/ ...

  5. qrcode-php生成二维码

    调用PHP QR Code非常简单,如下代码即可生成一张内容为"http://www.baidu.com"的二维码. include 'phpqrcode.php'; QRcode ...

  6. 深入理解ReentrantLock

    在Java中通常实现锁有两种方式,一种是synchronized关键字,另一种是Lock.二者其实并没有什么必然联系,但是各有各的特点,在使用中可以进行取舍的使用.首先我们先对比下两者. 实现: 首先 ...

  7. Vijos1675 NOI2005 聪聪和可可 记忆化搜索

    简单题,结果因为理解错题意懵逼了好久…… moveTo[x][y]表示聪聪在节点x,可可在节点y时,聪聪下一步应到达哪一个节点 dp[x][y]表示聪聪在节点x,可可在节点y,且轮到可可行动时,所需时 ...

  8. 深度探索va_start、va_arg、va_end

    采用C语言编程的时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数.但在某些情况下希望函数的参数个数可以根据需要确定.典型的例子有大家熟悉的函数printf().s ...

  9. SGU 130.Circle

    答案为Catalan数C(2k, k)/(k+1) #include <stdio.h> using namespace std; int k; int main() { scanf(&q ...

  10. centos安装nodejs和mongodb

    安装nodejs: Run as root on RHEL, CentOS or Fedora, for Node.js v4 LTS Argon: curl --silent --location ...