zoukankan      html  css  js  c++  java
  • CF1316E Team Building

    (CF1316E Team Building)

    Solution

    我们先考虑一个简单的暴力。

    我们设 (f_{i,j,T}) 表示前 (i) 个人,选择了其中 (j) 个作为观众,队伍中的人选择情况(状压)。

    转移比较显然:

    [f_{i,j,T}=max (f_{i-1,j,T},f_{i-1,j-1,T}+a_i)\\ f_{i,j,T}=max_{k=1}^p(f_{i-1,j,T Xor 2^{k-1}}+s_{i,k}) ]

    时间复杂度是 (O(2^nnkp))

    但是,我们发现,当确定了哪些人进入排球队时,观众一定是选 (a_i) 最大的 (k) 个。

    我们将所有人按 (a_i) 从大到小排序。

    (f_{i,T}) 表示前 (i) 个人,队伍哪些人确定。

    那么显然,我们已经确定作为观众的人数是 (min(k,i-1-popcnt(T)))

    那么转移就是:

    [f_{i,T}=f_{i-1,T}\\ f_{i,T}=f_{i-1,T}+a_i ,i-popcnt(T)leq k\\ f_{i,T}=max_{j=1}^m (f_{i-1,j,T Xor 2^{j-1}}+s_{i,j}) ]

    Code

    #include<bits/stdc++.h>
    #define del(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mid ((l+r)>>1)
    #define lowbit(x) (x&(-x))
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>il read(T &x){
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=x*10+k-'0';
    	x*=f;
    }
    template<class T>il _print(T x){
    	if(x>=10) _print(x/10);
    	putchar(x%10+'0');
    }
    template<class T>il print(T x){
    	if(x<0) putchar('-'),x=-x;
    	_print(x);
    }
    ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
    it qpow(int x,int k,int mod){
    	int res=1,bas=x;
    	while(k){
    		if(k&1) res=1ll*res*bas%mod;
    		bas=1ll*bas*bas%mod,k>>=1;
    	}
    	return res;
    }
    const int N = 1e5+5;
    int n,m,k,cnt[1<<7];
    struct Node{
    	int val,cost[8];
    	bool operator < (const Node &t) const {
    		return val>t.val;
    	}
    }node[N];
    ll f[N][1<<7];
    il chk_max(ll &x,ll y){x=x>=y?x:y;}
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n),read(m),read(k);
    	for(ri i=1;i<=n;++i) read(node[i].val);
    	for(ri i=1;i<=n;++i) for(ri j=1;j<=m;++j) read(node[i].cost[j]);
    	sort(node+1,node+1+n);
    	del(f,-0x3f),f[0][0]=0;
    	int S=1<<m;
    	for(ri T=0;T<S;++T) for(ri i=1;i<=m;++i) cnt[T]+=(T&(1<<(i-1)))?1:0;
    	for(ri i=1;i<=n;++i)
    		for(ri T=0;T<S;++T){
    			f[i][T]=f[i-1][T];
    			if(cnt[T]>i) continue;
    			if(i-cnt[T]<=k) chk_max(f[i][T],f[i-1][T]+node[i].val);
    			if(T){
    				for(ri j=1;j<=m;++j) if(T&(1<<(j-1)))
    					chk_max(f[i][T],f[i-1][T^(1<<(j-1))]+node[i].cost[j]);
    			}
    		}
    	print(f[n][S-1]);
    	return 0;
    }
    
  • 相关阅读:
    最小乘积(基本型)
    删除数组零元素
    大小写转换
    矩阵乘法
    字串统计
    出现次数最多的整数
    Anagrams问题
    前缀表达式
    2的次幂表示
    POJ
  • 原文地址:https://www.cnblogs.com/TheShadow/p/12584479.html
Copyright © 2011-2022 走看看