题意:
总共有n个人,每个人可以当做观众或者球员,每个位置只有一个球员,给定每个人当观众的价值和每个人在每个位置的价值。其中共有p(p<=7)个球员和k个观众,求出怎么安排使得总价值最大。首先得贪心选择 将观众的价值从大到小排序 这样观众的选择可以保证最优
表示正在选第i个人 并且确定第i个人后球员的选择状态用二进制压缩的j来表示
那么如果我们不选第i个人
如果观众数还不足k 我们让第i人去当观众
如果第i人去当某个位置的球员
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int cnt[150];
const int N = 1e5+10;
ll dp[N][150];
int ct(int x){
int ret = 0;
while(x){
x-=x&-x;
ret++;
}
return ret;
}
struct node{
int a,s[8];
bool operator <(const node& b)const{
return a>b.a;
}
}q[N];
int main(){
int n,p,k;
scanf("%d%d%d",&n,&p,&k);
for(int i = 0; i < (1<<p); i++) cnt[i]=ct(i);
for(int i = 1; i <= n; i++) scanf("%d",&q[i].a);
for(int i = 1; i <= n; i++){
for(int j = 0; j < p; j++) scanf("%d",&q[i].s[j]);
}
sort(q+1,q+1+n);
for(int i = 0; i < (1<<p); i++) dp[0][i]=-1e18;
dp[0][0]=0;
for(int i = 1; i <= n; i++){
for(int j = 0; j < (1<<p); j++){
dp[i][j]=dp[i-1][j];
if(i-cnt[j]<=k) dp[i][j]=max(dp[i][j],dp[i-1][j]+q[i].a);
for(int x = 0; x < p; x++){
if((j>>x)&1)
dp[i][j]=max(dp[i][j],dp[i-1][j^(1<<x)]+q[i].s[x]);
}
}
}
printf("%lld\n",dp[n][(1<<p)-1]);
return 0;
}