您的位置:首页 > 其它

UVa 11212 Editing a Book

2016-06-17 11:57 471 查看
title: ‘UVa 11212 Editing a Book’

categories: UVa

date: 2015-12-16 20:30:00

tags: [IDA*]

Description

You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the order

of 1, 2, … , n. With the help of a clipboard, you can easily do this: Ctrl-X (cut) and Ctrl-V (paste) several times. You cannot cut twice before pasting, but you can cut several contiguous paragraphs at the same time - they’ll be pasted in order.

For example, in order to make {2, 4, 1, 5, 3, 6}, you can cut 1 and paste before 2, then cut 3 and

paste before 4. As another example, one copy and paste is enough for {3, 4, 5, 1, 2}. There are two ways to do so: cut {3, 4, 5} and paste after {1, 2}, or cut {1, 2} and paste before {3, 4, 5}.

Input

The input consists of at most 20 test cases. Each case begins with a line containing a single integer n

(1 < n < 10), thenumber of paragraphs. The next line contains a permutation of 1, 2, 3, … , n. The

last case is followed by a single zero, which should not be processed.

Output

For each test case, print the case number and the minimal number of cut/paste operations.

Sample

input.txt

6

2 4 1 5 3 6

5

3 4 5 1 2

0

output.txt

Case 1: 2

Case 2: 1

Solution

n不是特别大,所以可以乱搞,这个剪切和粘贴的操作,我直接O(n^4)来搞的也没什么问题。至于剪枝,比如永远不破坏已经拼好的一段连续序列是很显然的,这个用来剪枝效果还不错。

当然比较神的是这个A*,我们发现每次剪切最多只能减少三个不正确的后继,所以我们可以先统计出当前状态有多少不正确的后继h,d为当前深度,maxd为深度上限,若3*d+h>3*maxd,则可以剪枝了。

Code

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

#define maxn 10+5

using namespace std;

int s[maxn];
int n;

int check(){
int res=0;
for(int i=1;i<n;i++)
if(s[i]!=s[i+1]-1) res++;
return res;
}

bool dfs(int t,int lim){
int c=check();
if(c==0) return true;
if(3*t+c>3*lim) return false;
int tmp[maxn],temp[maxn]={0};
memcpy(tmp,s,sizeof(s));
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
if(s[j+1]!=s[j]+1 && s[i-1]!=s[i]-1){
for(int k=0;k<i-1;k++){
int tail=0;
for(int l=1;l<=k;l++) temp[++tail]=s[l];
for(int l=i;l<=j;l++) temp[++tail]=s[l];
for(int l=k;l<i;l++) temp[++tail]=s[l];
for(int l=j+1;l<=n;l++) temp[++tail]=s[l];
for(int l=1;l<=n;l++) s[l]=temp[l];
bool ctrl=dfs(t+1,lim);
memcpy(s,tmp,sizeof(tmp));
if(ctrl) return true;
}
for(int k=j+1;k<=n;k++){
int tail=0;
for(int l=1;l<i;l++) temp[++tail]=s[l];
for(int l=j+1;l<=k;l++) temp[++tail]=s[l];
for(int l=i;l<=j;l++) temp[++tail]=s[l];
for(int l=k+1;l<=n;l++) temp[++tail]=s[l];
for(int l=1;l<=n;l++) s[l]=temp[l];
bool ctrl=dfs(t+1,lim);
memcpy(s,tmp,sizeof(tmp));
if(ctrl) return true;
}
}
return false;
}

int main(){
int T=0;
while(scanf("%d",&n)==1 && n!=0){
printf("Case %d: ",++T);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]);
bool f=true;
for(int i=1;i<n;i++)
if(s[i]!=s[i+1]-1){
f=false;
break;
}
if(f){
puts("0");
continue;
}
for(int lim=1;23333;lim++){
if(dfs(0,lim)){
printf("%d\n",lim);
break;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息