IDA*

引言:

  上次讲到的估价函数 f 与带二叉堆的bfs结合形成了astar算法;

  那么,f 函数能不能与dfs结合?

  

dfs是深度优先搜索,即一直向一个方向搜索,搜索完毕就返回;

但其实这样直接与估价函数结合可能会导致出错;

一旦估价函数出错,那么我们可能向下搜索一个不会出答案的分支;

导致浪费时间,导致超时;

 

所以我们最终选择将估价函数与 迭代加深的dfs 相结合;

f 为每个状态到目标状态的需要的步数。

当然 f 遵循 astar 中 f 定义的 估计值不大于实际步数 

深度限制回溯条件变为, 当前深度 + 估计值 > 深度限制 ,return;

这就是 IDAstar算法——迭代加深的Astar算法;

例题: booksort

题意:

给定n本书,编号为1-n,在初始状态下,书是任意排列的,在每一次操作中,可以抽取其中连续的一段,再把这段插入到其他某个位置。

我们的目标状态是把书按照1-n的顺序依次排列,求最少需要多少次操作。

若操作次数>=5,输出“5 or more”。

这道题别看他它只需要四步搜索,但它的搜索规模其实很大,粗摸估计一次搜索最坏要560;

四次就是560^4;

这个肯定无法承受;

所以我们采用idastar

定义一个玩意儿:

正确后继:指在目标状态中 i 后面应是 i+1 ,所以我们将 i+1 称为 i 的正确后继;

任意状态state;

我们设它的整个排列状况中错误后继的个数为 tot ;

我们可以发现:每次进行修改我们可以进行三个后继的修改、

设s[]为修改区间,从l~r

分别是: l-1、r、转移后的l'-1;

共有三个;

假如是理想状况下:每次都改对错误后继三个,那么我们的最小修改应是 tot/3(向上取整),所以根据我们 f 函数的定义,整个最小修改完全符合条件;

然后采用迭代加深的方法,若 当前步数+f(state)>k(当前限制),直接回溯;

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 const int N = 20;
 6 int n, a[N], dep;
 7 
 8 int gj() {//tot计算 
 9     int cnt = 0;
10     for (int i = 1; i < n; i++)
11         if (a[i] + 1 != a[i+1]) cnt++;
12     if (a[n] != n) return cnt + 1;
13     return cnt;
14 }
15 
16 void work(int l, int r, int t) {
17     int b[N], p = r;
18     for (int i = l; i <= t; i++) {
19         b[i] = a[++p];
20         if (p == t) p = l - 1;
21     }
22     for (int i = l; i <= t; i++) a[i] = b[i];
23 }
24 
25 bool dfs(int now) {
26     int cnt = gj();
27     if (!cnt) return 1;
28     if (3 * now + cnt > 3 * dep) return 0;
29     int c[N];
30     memcpy(c, a, sizeof(c));
31     for (int l = 1; l <= n; l++)
32         for (int r = l; r <= n; r++)
33             for (int t = r + 1; t <= n; t++) {
34                 work(l, r, t);
35                 if (dfs(now + 1)) return 1;
36                 memcpy(a, c, sizeof(a));//回溯 
37             }
38     return 0;
39 }
40 
41 void Booksort() {
42     cin >> n;
43     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
44     for (dep = 0; dep <= 4; dep++)
45         if (dfs(0)) {
46             cout << dep << endl;
47             return;
48         }
49     puts("5 or more");
50 }
51 
52 int main() {
53     int t;
54     cin >> t;
55     while (t--) Booksort();
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/lirh04/p/12899550.html