zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    计算机网络学习笔记:第九章.无线网络
    计算机网络学习笔记:第七章.网络安全与攻防
    seq命令的使用
    rm--删除文件或目录
    tar命令-解压和压缩文件
    CentOS最小化安装后找不到ifconfig命令
    shell 字符菜单管理
    linux passwd批量修改用户密码
    Linux shell 判断字符串为空等常用命令
    Linux 中find命令
  • 原文地址:https://www.cnblogs.com/lirh04/p/12899550.html
Copyright © 2011-2022 走看看