UVa11212(IDA*)

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;
}
posted @ 2025-08-07 21:49  雾岛春颂  阅读(8)  评论(0)    收藏  举报