zoukankan      html  css  js  c++  java
  • [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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    es6简述
    vue梳理
    webpack常用插件
    JS知识点
    CSS知识点
    224646
    223301
    图书馆 摘 1
    消息队列高手课 笔记6
    消息队列高手课 笔记5
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7412325.html
Copyright © 2011-2022 走看看