zoukankan      html  css  js  c++  java
  • E

    题意:给n个人,从中挑出p个参赛人,k个观众,每个人作为观众有对应的贡献,每个人作为参赛人在不同位置上也有对应的贡献,问最大贡献是多少?

    分析:考虑dp[i][j],表示前 i 个人选的参赛人状态为 j 的最大贡献( j 中状态为1 表示第 i 个人考虑作为参赛人)。

       假设我们已经选好了参赛人的贡献,那么观众是不是就是一定事选剩下人作为观众贡献最大的那一些人;

       明白了这一点后,我们必然先把n个人按照观众的贡献降序排起来;

       考虑转移,初始状态就是我把第1~k个人作为观众来加到初始贡献上,那么转移就是挑出一个作为参赛人,观众就变成了k-1个,那么得考虑加进来一个,那么加进来的那一个肯定是第k+1个人,如此推下去。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int M=1e5+5;
    const int maxn=130;
    ll dp[M][maxn],cnt[maxn];
    struct node{
        ll val,s[10];
        bool operator<(const node &b)const{
            return val>b.val;
        }
    }a[M];
    int n,p,k;
    ll cal(int cur,int c){
        if(k+c<=cur)
            return 0;
        return a[k+c].val-a[cur].val;
    }
    int main(){
        
        scanf("%d%d%d",&n,&p,&k);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i].val);
        }    
        for(int i=1;i<=n;i++)
            for(int j=0;j<p;j++)
                scanf("%lld",&a[i].s[j]);
        sort(a+1,a+1+n);
        memset(dp,172,sizeof(dp));
        dp[0][0]=0;
        for(int i=1;i<=k;i++)
            dp[0][0]+=a[i].val;
        int mx=1<<p;
        ///cnt[i]表示i的二进制位有多少 
        for(int i=0;i<mx;i++)
            cnt[i]=cnt[i>>1]+(i&1);
        for(int i=1;i<=n;i++)
            for(int j=0;j<mx;j++){
                dp[i][j]=dp[i-1][j];
                for(int k=0;k<p;k++){
                    if(j&(1<<k)){
                        dp[i][j]=max(dp[i][j],dp[i-1][j^(1<<k)]+a[i].s[k]+cal(i,cnt[j]));
                    }
                }
            }
        printf("%lld
    ",dp[n][mx-1]);
        return 0;
    }
    View Code
  • 相关阅读:
    QT之sqlite连接
    QT之QCustomPlot(二)
    QT之QCustomPlot(一)
    Qt第三方库QCustomPlot——QCustomPlot解读
    C++ 头文件系列(sstream)
    C++ 头文件系列(streambuf)
    C++ 头文件系列(iostream)
    C++ 头文件系列(ostream)
    C++ 头文件系列(istream)
    C++ 头文件系列(ios)
  • 原文地址:https://www.cnblogs.com/starve/p/12422320.html
Copyright © 2011-2022 走看看