紫书的思路 主要一个是剪枝 一个是复制黏贴操作 经典的IDA*题 内附注释
#include<bits/stdc++.h>
using namespace std;
int n;
int maxd;
int a[15];
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_sorted() {
for(int i = 0; i < n-1; i++)
if(a[i] >= a[i+1]) return false;
return true;
}
bool dfs(int d,int maxd){
if(d*3 + h() > maxd*3) return false; //剪枝,由书上可以知道一次更改最多只能实现3个排序正确如果(maxd-h)*3>h()肯定就不行了剪掉
if(is_sorted()) return true;
int b[15],olda[15];
memcpy(olda,a,sizeof(a)); //把原始数据保护好
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int cnt=0;
for(int k=0;k<n;k++)
if(k<i||k>j)b[cnt++]=a[k]; //把要复制的内容放在b里面
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 1;
memcpy(a,olda,sizeof(a)); //取消这一次对其做出的更改,类似取消vis[i]=1 标记为vis[i]=0;实现全面搜索一遍
}
}
}
return 0;
}
int main(){
int kase=1;
while(scanf("%d",&n)==1&&n){
for(int i=0;i<n;i++)scanf("%d",&a[i]);
if(is_sorted()){
printf("Case %d: 0\n",kase++);
continue;
}
for(maxd=1;;maxd++){//不需要设置上限,因为是从小到大的,搜到了自然会break输出break就好了
if(dfs(0,maxd)){
break;
}
}
printf("Case %d: %d\n",kase++,maxd);
}
return 0;
}