分析:本题可以用迭代加深搜索算法。令最大搜索深度为maxd,当前搜索深度为d,则每次搜索都是从序列中截取一部分进行“剪贴复制”操作;考虑后继不正确的数字个数为h,可以证明每次剪切时h最多减少3
证明:设当前有四个数字 a b c d ,如果把b移到c后面,则改变了a、b、c三个数的后继
所以每次搜索前,当h>(maxd-d)*3 时剪枝,这里maxd-d即剩余搜索次数;
搜索的核心就是截取 [i, j] 插入剩余序列的第k个数字前
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 9;
int a[maxn], n;
int h()
{
int cnt = 0;
for(int i=0; i<n-1; i++)
if(a[i+1] != a[i]+1) cnt++;
if(a[n-1] != n) cnt++;
return cnt;
}
bool is_sort()
{
for(int i=0; i<n-1; i++) {
if(a[i+1] <= a[i]) return false;
}
return true;
}
bool dfs(int d, int maxd)
{
if(h() > (maxd-d)*3) return false;
if(is_sort()) return true;
int olda[maxn], b[maxn];
memcpy(olda, a, sizeof(a));
for(int i=0; i<n; i++)
for(int j=i; j<n; j++) {
//cut [i,j] ; b[] is the left
int cnt = 0;
for(int k=0; k<n; k++)
if(k<i || k>j) b[cnt++] = a[k];
//insert [i,j] into position k
for(int k=0; k<=cnt; k++) {
int cnt2 = 0;
for(int p=0; p<k; p++) a[cnt2++] = b[p];
for(int p=i; p<=j; p++) a[cnt2++] = olda[p];
for(int p=k; p<cnt; p++) a[cnt2++] = b[p];
if(dfs(d+1, maxd)) return true;
memcpy(a, olda, sizeof(a));
}
}
return false;
}
int solve()
{
int maxd;
if(is_sort()) return 0;
for(maxd = 1; ; maxd++) {
if(dfs(0, maxd)) break;
}
return maxd;
}
int main()
{
int kase = 0;
while(scanf("%d", &n), n) {
for(int i=0; i<n; i++) scanf("%d", &a[i]);
printf("Case %d: %d\n", ++kase, solve());
}
return 0;
}