• #状压dp,贪心#CF1316E Team Building


    题目

    为了组织一支排球队,你需要为队伍里的(p)个不同的位置,从(n)个人中选出(p)个人,
    且每个位置上都恰好有一个人。另外还需要从剩下的人中选出恰好(k)个人作为观众。
    对于第(i)个人,已知他作为观众时能为队伍增加(a_i)点力量,
    还有他在队伍的第(j)个位置上时能为队伍增加(s_{i,j})点力量。
    请问这只排球队力量的最大值是多少?


    分析

    由于(p)很小,考虑状压dp,
    (dp[i][s])表示前(i)个人选取为队员的状态为(s)时产生的最大力量
    为了让观众力量更大,按照贪心思想肯定要先按观众力量从大到小排序,
    还要保证选取的观众人数恰好等于(k),最后输出(dp[n][2^p-1])


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=100011; typedef long long lll;
    struct rec{int w,z[7];}a[N];
    int n,m1,m2,al,xo[N]; lll dp[128];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    bool cmp(rec x,rec y){return x.w>y.w;}
    inline void Max(lll &a,lll b){a=a>b?a:b;}
    signed main(){
    	n=iut(),m1=iut(),m2=iut(),al=1<<m1;
    	for (rr int i=1;i<al;++i) xo[i]=xo[i&(i-1)]+1;
    	for (rr int i=1;i<=n;++i) a[i].w=iut();
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=0;j<m1;++j)
    	    a[i].z[j]=iut();
    	sort(a+1,a+1+n,cmp);
    	memset(dp,0xcf,sizeof(dp)),dp[0]=0;
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=al-1;~j;--j){
    		if (dp[j]>=0) dp[j]+=a[i].w*(i-xo[j]<=m2);
    		for (rr int p=0;p<m1;++p) if ((j>>p)&1)
    		    Max(dp[j],dp[j^(1<<p)]+a[i].z[p]);
    	}
    	return !printf("%lld",dp[al-1]);
    }
    
  • 相关阅读:
    JAVA基础——编程练习(二)
    JAVA基础——面向对象三大特性:封装、继承、多态
    JVM内存
    50. Pow(x, n) (JAVA)
    47. Permutations II (JAVA)
    46. Permutations (JAVA)
    45. Jump Game II (JAVA)
    43. Multiply Strings (JAVA)
    42. Trapping Rain Water (JAVA)
    41. First Missing Positive (JAVA)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13529415.html
Copyright © 2020-2023  润新知