• UVA11212 EditingaBook ( IDA*搜索)


    首先说说IDS,就DFS限定一个层数上限maxd,如果在maxd范围内没有找到解,就增加maxd,继续搜索。

    当访问到当前结点u时,估计还要搜索h(u)层,如果h(u)+当前层数d>maxd的时候就剪枝,这就是IDA*。

    IDA*属于DFS,当状态空间某一层的结点数无穷大时,BFS失效,只能DFS。

    相比BFS,它的空间占用少(不需要判重复),时间效率也不低。

    注意:A*的关键在于选取估价函数h()。

    ----------------------------------分割线-------------------------------------------------------------

    来说说 UVA11212 EditingaBook

    缩小搜索空间的策略有

    策略1:只剪切连续的数字片段。

    策略2:剪切的片段头为a尾为b,要么粘贴到a-1的后面,要么粘贴到b+1前面。

    策略3:不要破坏已经连续的片段。

    但是策略1和策略2并能保证正解:如5 4 3 2 1 —》 3 2 5 4 1 —》 3 4 1 2 5 -》 1 2 3 4 5。

    策略1,2出错主要是因为忽略了后效性,策略3是可以的,把连续的片段看成整体,拆开它一定是比不拆它的步数要少。

    下面寻找估价函数

    由于每次剪切最多更改3个数字的前继(或后继),所以统计前继不对的数字个数为n个那么只少还要搜n/3层。如果d+n/3>maxd即3*d+n>maxd就剪枝。

    还有一个剪枝是:移动片段b1~b2到b2+1~c后面,相当于移动b2+1~c到b1~b2前面,所以只要枚举把片段往后移动就行了。

    //Rey
    #include<bits/stdc++.h>
    
    const int maxn = 9;
    
    int n,a[maxn];
    
    inline bool End()
    {
        for(int i = 1; i < n; i++){
            if(a[i] <= a[i-1]) return false;
        }
        return true;
    }
    
    inline int h()
    {
        int cnt = 0;
        for(int i = 1; i < n; i++)
            if(a[i] != a[i-1]+1) cnt++;
        return cnt;
    }
    
    int maxd;
    const int intsz = sizeof(int);
    const int asz = sizeof(a);
    bool dfs(int d)
    {
        if(3*d + h() > 3*maxd) return false;
        if(End()) return true;
    
        int old[maxn];//保存a
        memcpy(old,a,asz);
        int b[maxn];//剪切板
    
        for(int i = 0; i < n; i++) if( i == 0 || old[i] != old[i-1] + 1) //策略3 选择尽量长的连续片段 剪切的起点
        for(int j = i; j < n; j++) { //终点 和 策略2不同选取片段可以不连续
            while(j+1 < n && old[j+1] == old[j] + 1)j++;//策略3
            memcpy(b,old+i,intsz*(j-i+1));
            //剪切移动片段
            for(int k = j+1;k < n;k++){//由于对称性,只要往后贴就行了
                while(k+1 < n && old[k+1] == old[k] + 1)k++;//策略3 不破坏
                memcpy(a+i,old+j+1,intsz*(k-j));
                memcpy(a+i+k-j,b,intsz*(j-i+1));
                if(dfs(d+1))return true;
                //恢复
                memcpy(a,old,asz);
            }
        }
        return false;
    }
    
    inline int solve()
    {
        if(End())return 0;
        for(maxd = 1; maxd < 5 ;maxd++)
            if(dfs(0)) return maxd;
        return 5;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int Cas = 0;
        while(~scanf("%d",&n)&&n) {
            for(int i = 0; i < n; i++)
                scanf("%d",a+i);
            int ans = solve();
            printf("Case %d: %d
    ",++Cas,ans);
        }
        return 0;
    }
  • 相关阅读:
    Notepad++可以结合命令行来搭建各种编程环境
    installshield中如何执行批处理 还有设置环境变量
    intallshield各种控制语句
    实际应用中installshield的事件处理
    intallshield各种控制语句
    java 沙箱
    手写installshield入门
    installshield安装程序自注册dll
    实际应用中installshield的事件处理
    installshield中如何执行批处理 还有设置环境变量
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4629805.html
Copyright © 2020-2023  润新知