• P4447 [AHOI2018初中组]分组


    P4447 [AHOI2018初中组]分组

    贪心

    原本考虑一口气连到底,但是只有60

    举个反例: 1 2 3 3 4 5

    一口气连到底的话就会出现:(1 2 3 4 5)(3),但最优解为(1 2 3)(3 4 5)

    正解:

    ①考虑: 。。。6 6 7 7 7 。。。

    ‘6’有2个,‘7’有3个

    所以最优方案中一定会出现一个‘7’开头的组:(7 。。)

    碰到这种情况直接开一个新组

    ②考虑:。。。 6 6 6 7 7 。。。

    ‘6’有3个,‘7’有2个

    所以最优方案中一定会出现一个‘6’结尾的组:(。。6 )

    已知目前到‘6’为止(。。。6 6 6)的最优解一定有3个以‘6’结尾的组

    我们把较短的两组各加上一个‘7’,这样就达成让最短的组尽量长的目的

     

    用两个数组分别储存各组的长度和末尾元素

    对所有元素从小到大排序

    每次添加元素时找到最短的可以连上的组就可以了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,a[100005],l=1,r,b[100005],lb[100005];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        for(int i=1;i<=n;++i){
            int p=0;
            for(int j=r;j>=l;--j){
                if(b[j]+1<a[i]) l=j+1; //优化
                if(b[j]+1==a[i]){ //在所有可以连上的组中,后开的组长度一定比较短
                    ++b[j]; ++lb[j];
                    p=1; break;
                }
            }
            if(!p) b[++r]=a[i],++lb[r];
        }
        int M=1e9;
        for(int i=1;i<=r;++i)
            M=M<lb[i]?M:lb[i]; //找最短长度
        printf("%d",M);
        return 0;
    }

     

  • 相关阅读:
    Word Puzzles [POJ 1204]
    set用法
    FOJ有奖月赛2012年11月
    BerDonalds
    POJ1469 匈牙利算法
    后缀数组
    ZOJ Monthly, January 2013
    算法导论<一>
    Yell Classico
    点聚 WebOffice 编辑辅助控件 WebOffice.OCX
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/14979099.html
Copyright © 2020-2023  润新知