[ZJOI2006]皇帝的烦恼

题目:codevs1513、BZOJ1863。

题目大意:有n个人围成一个圈,每个人需要$a[i]$个颜色不同的勋章,且相邻两个人不能拿到同样颜色的勋章。求至少需要准备多少种不同颜色的勋章。

解题思路:首先我们可以二分答案,但如何判断答案的正确性呢?我们可以用dp。

设$f[i]$表示第i个人在不与前一个人冲突的情况下,与第1个人最多冲突的个数,$g[i]$表示第i个人在不与前一个人冲突的情况下,与第一个人最少冲突的个数,可得

$f[i]=min(a[i],a[1]-g[i-1])$

$g[i]=max(0,a[i]+a[i-1]+a[1]-f[i-1]-x)(x为当前二分到的答案)$

最后如果g[n]不为0则答案有效。

C++ Code:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[20005],f[20005],g[20005];
bool ok(int x){
	f[1]=g[1]=a[1];
	for(int i=2;i<=n;++i){
		f[i]=min(a[i],a[1]-g[i-1]);
		g[i]=max(0,a[i]+a[i-1]+a[1]-f[i-1]-x);
	}
	return !g[n];
}
int main(){
	scanf("%d",&n);
	int s=0;
	for(int i=1;i<=n;++i)scanf("%d",&a[i]),s+=a[i];
	int l=0,r=s,ans=s;
	for(int i=1;i<n;++i)l=max(l,a[i]+a[i+1]);
	while(l<=r){
		int mid=(l+r)>>1;
		if(ok(mid)){
			r=mid-1;
			ans=mid;
		}else
		l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

 

posted @ 2017-08-22 16:39  Mrsrz  阅读(213)  评论(0编辑  收藏  举报