zoukankan      html  css  js  c++  java
  • bzoj1863[Zjoi2006] trouble 皇帝的烦恼(二分+dp)

    这里写图片描述

    分析:
    提示都说是二分了
    肯定就是二分一个种类数
    现在问题是,我们怎么判断该种方案是否可行呢

    我们选择dp
    为什么是dp呢
    因为dp比较diao
    先看比较简单的,如果n是偶数,那么我们就可以把所有将士分成两部分
    同一部分可以拥有颜色一样的徽章,那么答案就是相邻两个的加和最大值

    那要是n为奇数呢,我们就不能这么simple了
    这个时候第n个分到哪一部分无法立刻确定
    那么关键问题就出现在第1个和第n个的冲突上
    所以我们考虑用dp来递推最小和最大的冲突数量
    maxn[i]表示在不与i-1发生冲突的前提下,与1号的最大冲突
    minn[i]表示在不与i-1发生冲突的前提下,与1号的最小冲突

    等一下,什么叫两者之间的冲突呢
    其实每个人自己的勋章颜色各不同,不管他人,可能会重复的颜色

    maxn[i]=min(a[i],a[1]-minn[i-1])

    (minn[i-1]的颜色我们一定不能用,否则会和i-1冲突,a[1]剩下的颜色,最坏情况就是我用的都是这一部分的颜色)

    因为要使i和1冲突尽可能大,而又不能与i-1冲突,
    所以我们令i-1与1的冲突尽可能小,除去minn[i-1],a[1]中的点都可以选,所以上面的式子得证。

    minn[i]=max(0,a[i]-(x-a[i-1]-a[1]+maxn[i-1))

    (尽量不冲突,也就是说x种颜色尽量少的分配给了i-1和1的冲突部分之后,剩下的如果不够a[i],那么i和1一定会发生冲突)

    我们希望冲突尽可能的小,那么也就是除了不得不冲突的情况,其他的都不冲突
    那么如果计算不得不冲突的情况呢?
    我们一共有x种颜色,x-a[i-1]-a[1]+maxn[i-1]表示x中除去与i-1冲突的,除去与1冲突的
    (令i-1和1冲突最大,能保证剩下的点最多)所能选取的点,如果点数不足a[i],那么必然要与1发生冲突。

    最后判断是否可行,只需要判断minn[n]是否为0即可,因为推得时候保证与前一个不冲突。

    注意二分答案的最小值不能是1,因为我们推的时候保证i不与i-1冲突,
    所以最小值应该是相邻两个加和的最大值。

    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=100001;
    int n,limit=0,sum=0;
    int a[N],minn[N],maxx[N];
    
    int pd(int x)
    {
        minn[1]=maxx[1]=a[1];
        for (int i=2;i<=n;i++)
        {
            maxx[i]=min(a[1]-minn[i-1],a[i]);
            minn[i]=max(0,a[i]-(x-a[i-1]-a[1]+maxx[i-1]));
        }
        if (!minn[n]) return 1;
        else return 0;
    }
    
    int main()
    {
        scanf("%d",&n);
        a[0]=0;
        for (int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i],limit=max(limit,a[i]+a[i-1]);
        limit=max(limit,a[1]+a[n]);
        int l=limit,r=sum;
        int mid,ans=0x33333333;
        while (l<=r)
        {
            mid=(l+r)>>1;
            if (pd(mid))
            {
                ans=min(ans,mid);
                r=mid-1; 
            }
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    ASP.NET Routing Debugger
    浏览器 CSS & JS Hack 手册
    基于vmWare5.5环境的VxWorks系统安装总结
    TFS 迁移到 Git
    关于websocket
    自定义单一模块Model类
    学习 C++的用途
    Navigation Controllers and Table Views(中)
    Mac环境下svn的使用
    减少.NET应用程序内存占用的一则实践
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673207.html
Copyright © 2011-2022 走看看