UVa11212,Editing a Book

正如书上所说,本题需要用IDA*算法求解

启发函数是3d+h>3maxd(d为当前操作步骤数,h为当前逆序对数,maxd为当前枚举的最大步骤数)

可见迭代递归的核心思想是枚举ans去dfs是否可行,相反常规搜索是dfs去需找ans。

一开始卡在状态图的转移与回溯上,参考(http://blog.csdn.net/sssogs/article/details/8836606)大神的代码后得到启发,可以将图或是表直接写成结构体或是类跟着递归走(当然,图或是表不能很大,比较大的话应该还是用回溯比较好吧)

#include <iostream>

#include <cstring>

#include <cstdio>

#include <string>

#include <algorithm>

#define maxn 20

using namespace std;

int maxd,cnt;

class MyClass{

    public:

        int map[maxn];

        int h,n;

        void move(int s,int e,int k){

            int t[maxn];

            for (int i=0;i<k;i++){

                t[i]=map[i];

            }

            for (int i=s;i<=e;i++){

                t[k+i-s]=map[i];

            }

            int top=k+e-s;

            for (int i=k;i<n;i++){

                if (i<s||i>e) t[++top]=map[i];

            }

            memcpy(map,t,sizeof(t));

        }

        void move2(int s,int e,int k){

            int t[maxn],i,j;

            for (i=0; i<s; i++)

            {

                t[i]=map[i];

            }

            for (j=e+1; j<k; j++,i++)

            {

                t[i]=map[j];

            }

            for (j=s; j<=e; j++,i++)

            {

                t[i]=map[j];

            }

            for (j=k; j<n; j++,i++)

            {

                t[i]=map[j];

            }

            memcpy(map,t,sizeof(t));

        }

        int getH(){

            h=0;

            for (int i=0;i<n-1;i++)

                if (map[i]+1!=map[i+1]) h++;

            if (map[n-1]!=n) h++;//经过测试,这一句减掉了60%的搜索量.......之前一直TLE,天呢,又是一下午 

            return h;

        }

        bool init(){

            cin>>n;

            if (n==0) return false;

            for (int i=0;i<n;i++){

                cin>>map[i];

            }

            return true;

        }

};

int IDAdfs(int d,MyClass c){

    c.getH();

    MyClass tc;

    cnt++;

    if (c.h==0) return 1;

    //if (d==maxd&&c.h>0) return 0;

    if (3*d+c.h>3*maxd) return 0;

    for (int i=0;i<c.n;i++)

        for (int j=i;j<c.n;j++){ 

            for (int k=0;k<i;k++){

                tc=c;

                tc.move(i,j,k);

                if (IDAdfs(d+1,tc)) return 1;

            }

            for (int k=j+2; k<c.n; k++)

            {

                tc=c;

                tc.move(i,j,k);

                if (IDAdfs(d+1,tc) == true)

                    return true;

            }

        } 

    return 0;

}

int main()

{

    MyClass b;

    int prob;

    prob=1;

    while (b.init() == true)

    {

        cnt=0;

        for (maxd=0; ; maxd++)

        {

            if (IDAdfs(0,b) == true)

                break;

        }

        printf("Case %d: %d\n",prob,maxd);

        prob++;

        //cout<<cnt<<endl;

    }

}
View Code

 

你可能感兴趣的:(uva)