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;
}
posted @ 2020-03-27 21:27  TheShadow  阅读(138)  评论(0编辑  收藏  举报