• UVA 11212 Editing a Book 【IDA*】


    题目链接

    题意

    给一个n个数的全排列,可以进行将任意连续的一段截下来插入到任意位置的操作,问至少需要多少步这样的操作能够是序列变成递增的序列。

    分析

    题中n的最大值为9,状态数为9的阶乘,不过1e6左右,看似可以直接BFS。但是每一种状态后的决策数量太多了(任意位置的任意长度再插入到任意位置)
    考虑到n个数的全排列,要使之恢复递增的顺序,最多移动n-1次即可。这样层数有上限,尝试用DFS。然而直接DFS回溯次数太多了,于是考虑使用IDA*。

    寻找乐观估价函数,也就要寻找一个指标来反应这个序列有多“接近”单调递增。我们直接统计后继不正确的数的个数,如2,1,3,4中2和1的后继都不正确,所以不正确数为2。考虑每一步是把一个区间移到另一个位置,每次最多只会改变三个位置的后继。易知递增序列的后继不正确数为0,因此设后继不正确数为h,则乐观估价函数为g(h)=h/3,所以当3d+h>3maxd时剪枝

    注意此题有可能本身给的串就是递增的,所以DFS层数应该从0开始,这样就不会遗漏这种情况

    AC代码

    //UVA 11212 Editing a Book
    //AC 2016-7-25 18:36:25
    //IDA*
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define bug cout<<"here"<<endl;
    //#define debug
    
    int maxd=9;
    vector<int> org;
    
    vector<int> moveto(const vector<int> &opr,int beg,int endd,int pos)
    {
        vector<int> temp;
        for(int i=0;i<pos;++i)
            temp.push_back(opr[i]);
        for(int i=beg;i<=endd;++i)
            temp.push_back(opr[i]);
        for(int i=pos;i<beg;++i)
            temp.push_back(opr[i]);
        for(int i=endd+1;i<opr.size();++i)
            temp.push_back(opr[i]);
        return temp;
    }
    
    bool DFS(int d,vector<int> seq)
    {
        int h=0;
        for(int i=0;i<seq.size()-1;++i)
            if(seq[i]+1!=seq[i+1])
                ++h;
        //for(int i=0;i<seq.size();++i)
            //cout<<seq[i]<<" ";
        //cout<<h<<"---"<<d<<"**"<<maxd<<endl;
        //getchar();
        if(d==maxd)
            return !h;
        if(3*d+h>3*maxd)
            return false;
        bool res=0;
        for(int i=1;i<seq.size();++i)
            for(int j=i;j<seq.size();++j)
                for(int k=0;k<=i-1;++k)
                    if(DFS(d+1,moveto(seq,i,j,k)))
                        return true;
        return false;
    }
    
    int IDA_star()
    {
        for(maxd=0;maxd<=org.size();++maxd)
            if(DFS(0,org))
                return maxd;
    }
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        int n,a,cnt=1;
        while(cin>>n&&n)
        {
            org.clear();
            while(n--)
            {
                cin>>a;
                org.push_back(a);
            }
            printf("Case %d: %d
    ",cnt++,IDA_star());
        }
        return 0;
    }
    
  • 相关阅读:
    #Leetcode# 876. Middle of the Linked List
    #Leetcode# 237. Delete Node in a Linked List
    #Leetcode# 234. Palindrome Linked List
    #Leetcode# 149. Max Points on a Line
    #Leetcode# 152. Maximum Product Subarray
    #Leetcode# 228. Summary Ranges
    #Leetcode# 227. Basic Calculator II
    PAT 1089 狼人杀-简单版
    linux——web安全之sql注入【预习阶段】
    linux——攻防技术介绍|主动攻击|被动攻击
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580608.html
Copyright © 2020-2023  润新知