• 牛客月赛 乐团派对(dp)


    题目描述 

    音乐是带给大家快乐的存在,而你的目标就是组建若干支乐队,让世界听到你们的演奏!

    你目前有n位乐手,每位乐手只能进入一个乐队,但并不是每位乐手都能担大任,因此需要团队合作。第ii位乐手的能力值为a[i]a[i],表示该位乐手所在乐队的人数必须大于等于a[i]。在保证每位乐手都被分进一个乐队的情况下,乐队数量最多可以是多少?

    输入描述

    第一行一个正整数n,表示乐手人数,n1e5。

    第二行n个正整数a[i],表示每位乐手的能力值,a[i]1e9。

    输出描述

    输出最多的乐队数量。若无法保证每位乐手都被分进一个乐队,则输出-1。

    示例1

    输入

    2 1 2 1

    输出

    3

    思路

    贪心的思想是尽可能使a[i]值大的乐手组到一个乐队,按a[i]从小到大排序。构造一个dp数组,dp[i]表示当前人数i所能组成乐队的最大数量。

    有转移方程,当i<a[i]时,当前人数构不成乐队,dp[i]=0;当i>=a[i]时,dp[i]=max(dp[i-a[i]],dp[i-a[i]-1,......dp[0])+1;(因为多余的人可以加进本队中,目的是使人数转移到使乐队数最多的人数);

    再一边转移一边维护一个前缀max数组,max[i]=max(max[i-1],dp[i]);即当i>=a[i]时,dp[i]=max[dp[i-a[i]]+1;

    当dp[n]等于0时,证明无法保证所有人在一个乐队,输出-1。

    #include<bits/stdc++.h>
    using namespace std;
    int a[100005];
    int dp[100005];
    int maxx[100005];
    int main(){
        int n;cin>>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++){
            if(a[i]>i)dp[i]=0;
            else dp[i]=maxx[i-a[i]]+1;
            maxx[i]=max(dp[i],maxx[i-1]);
        }
        if(dp[n]==0){
            cout<<"-1"<<endl;
        }
        else cout<<dp[n]<<endl;
        return 0;
    }
  • 相关阅读:
    Karma: 3
    Karma:2. 集成 Karma 和 mocha 进行单元测试
    Android Eclipseproject开发中的常见调试问题(二)android.os.NetworkOnMainThreadException 异常的解决的方法
    CSDN日报20170226——《你离心想事成仅仅差一个计划》
    重装linuxserver简易流程
    移动端 h5开发相关内容总结——CSS篇
    Oracle学习笔记(6)——函数
    Spark学习
    Android教你怎样一步步打造通用适配器
    C语言学习
  • 原文地址:https://www.cnblogs.com/mohari/p/13549560.html
Copyright © 2020-2023  润新知