UVa11212
![屏幕截图 2025-08-07 213641]()
解题思路: 本题n的规模最多为9,即答案最多为9,因此可以考虑迭代加深搜索,让深度d不断增大寻找答案。同时,观察发现,将任何一段连续序列拼接到另外某处,整个序列中最多只有3个元素的后继元素会发生改变,因此可以设计h()函数,求序列中的不符合目标答案顺序的个数,倘若3d+h() > 3maxd,则说明该深度搜索不到答案,可以直接剪枝,这里的h(),就是启发函数,解题中,只需要设计出h()来判断何种情况下一定无解即可,将上述二者相结合,就是IDA*算法。
// UVa11212 Chzm AC 2025/8/4 11:15
//#define LOCAL
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 9;
int n, a[maxn];
bool is_sorted(){
for(int i = 0; i < n-1; ++i)
if(a[i] >= a[i+1]) return false;
return true;
}
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 dfs(int d, int maxd){
if(d*3+h() > maxd*3) return false;
if(is_sorted()) return true;
int b[maxn],olda[maxn];
memcpy(olda,a,sizeof(a));
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j) {
int cnt = 0;
for(int k = 0; k < n; ++k)
if(k < i || k > j) b[cnt++] = a[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(){
if(is_sorted()) return 0;
int max_ans = 5;
for(int maxd = 1; maxd < max_ans; ++maxd)
if(dfs(0,maxd)) return maxd;
return max_ans;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int kase = 0;
while(scanf("%d",&n) == 1 && n) {
for(int i = 0; i < n; ++i) scanf("%d",&a[i]);
printf("Case %d: %d\n",++kase, solve());
}
return 0;
}