题意: 已知n个5元组,从中选出k组,使得这些组中5个位置,每个位置上最大数之和最大。
分析:当k>5时,就是n个5元组最大的数之和,当k<5时,就当做5元组,状态压缩,用00000表示未选出5个最大值,11111表示已经选出了5个最大值,那么情况就一共有32种,然后枚举每种情况更新f[i][j]数组,f[i][j]数组储存选i组情况是j的最大值之和是多少,结果就是f[k][31]。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int a[10010][6],f[6][40]; 8 9 int main() 10 { 11 int t,n,k; 12 scanf("%d", &t); 13 while(t--) 14 { 15 scanf("%d%d",&n,&k); 16 for(int i=0;i<n;++i) 17 for(int j=0;j<5;++j) 18 scanf("%d",&a[i][j]); 19 k=min(k,5); 20 memset(f,0,sizeof(f)); 21 for(int i=1;i<=k;++i) 22 for (int j=0;j<32;++j) 23 for(int x=j;x;x=(x-1)&j) 24 { 25 int tmp=j-x; 26 for(int l=0;l<n;++l) 27 { 28 int sum=0; 29 for(int m=0;m<5;m++) 30 if(x&(1<<m)) 31 sum+=a[l][m]; 32 f[i][j]=max(f[i][j],f[i-1][tmp]+sum); 33 } 34 } 35 printf("%d ",f[k][31]); 36 } 37 return 0; 38 }