uva 11212 Editing a Book

https://vjudge.net/problem/UVA-11212

题意:

n个数的排列,每次操作可以移动连续的一段

最问少移动多少次使这n个数升序排列

IDA*

估价函数:

考虑后即不正确的数字个数sum

每次移动最多使sum减少3

所以如果剩余递归层数*3<sum ,剪枝

#include<cstdio>
#include<cstring>
using namespace std;
int n,T,maxd;
bool stop;
bool check(int *a)
{
    bool p=true;
    for(int i=1;i<=n;i++)
     if(a[i]!=i)  { p=false; break; }
    return p;
}
void dfs(int now,int *a)
{
    if(stop) return;
    if(now==maxd+1) 
    { 
        if(check(a))  stop=true; 
        return;
    }
    int sum=0;
    for(int i=1;i<n;i++) if(a[i+1]!=a[i]+1) sum++;
    if((maxd-now+1)*3<sum) return;
    int tmp[10];
    memcpy(tmp,a,sizeof(*tmp)*(n+1));
    for(int len=1;len<n;len++)
      for(int s=2;s+len-1<=n;s++)
       for(int pos=1;pos<s;pos++)
        {
            for(int i=1;i<=len;i++) a[pos+i-1]=tmp[s+i-1];
            for(int i=pos,j=1;i<s;i++,j++) a[pos+len-1+j]=tmp[i];
            dfs(now+1,a);
            memcpy(a,tmp,sizeof(*a)*(n+1)); 
        }    
}
int main()
{
    int a[10]; 
    while(scanf("%d",&n)==1)
    {
        if(!n) return 0;
        T++; bool ok=true; stop=false;
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&a[i]);
            if(a[i]<a[i-1]) ok=false;
        }
        if(ok) { printf("Case %d: 0
",T); continue; }
        for(maxd=1;maxd<=n;maxd++)
        {
            dfs(1,a);
            if(stop) { printf("Case %d: %d
",T,maxd); break; }
        }
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7282164.html