美丽的牛家庄受到了外星人的侵略, 勇敢的妞妞要上战场抵御侵略。
在妞妞上战场前, 村长牛牛给了妞妞N件装备, 妞妞需要选择其中的K件,装备在身上提升自己的战斗力。每件装备有5种属性增幅值,对于第i件装备它的属性增幅值为(ri1, ri2, ri3, ri4, ri5), 分别代表该装备对不同的属性值增幅。
当妞妞装备多件装备的时候,由于装备之前会互相影响, 对于每种属性值的增幅并不是所有装备该属性值之和, 而是该种属性值下所有装备中最大的属性值。而妞妞最终增加的战斗力为这5种属性值增幅之和。
妞妞一定要保卫牛家庄, 所以她希望她能提升尽可能多的战斗力, 请你帮帮她计算她最多能增加多少战斗力。
输入包括N+1行,
第一行包括两个正整数N和K(1 <= N <= 10000, 1 <= K <= N), 分别表示一共有的装备数量和妞妞需要选择的装备数量。
接下来的N行,每行5个整数ri1, ri2, ri3, ri4, ri5 (0 <= ri1, ri2, ri3, ri4, ri5 <= 10000)表示第i件装备的5种属性值增幅。
输出一个整数,表示妞妞最多能增加的战斗力。
示例1
复制
4 2 30 30 30 30 0 50 0 0 0 0 0 50 0 50 10 0 0 50 0 20
复制
170
妞妞要从4件装备中选取2件, 如果妞妞选择第1件和第3件装备,那么增加的战斗力为30 + 50 + 30 + 50 + 10 = 170, 这是最大的方案。
思路:
将五个属性值压缩成2^5个状态,即
0 0 0 0 0;
0 0 0 0 1;
0 0 0 1 0;
0 0 0 1 1
……
1 1 1 1 1
意义为,1对应属性为有效属性(和最大),如00011为 第1和第2属性的和是最大值的物品;
令dp[1<<5][5](取i状态 的 j个装备);
如:其中dp[3][1] ;意义为 状态 0 0 0 1 1 只取 第1和第2属性的和最大的 一个装备
初始化1个装备的所有状态值。
两个装备的状态通过两个一个装备的状态和得到。
即:两个一个装备只取属性 1 1 1 0 0 & 0 0 0 1 1 可 得到五个属性 1 1 1 1 1 (要保证没有属性重复 )
那么上述可表示为 dp[31][2]=max(dp[31][2],dp[28][1]+dp[3][1])
(转移方程为dp[i|j][v]=max(dp[i|j][v],dp[i][v-1]+dp[j][1] ,其中v为装备数量(获得状态i的(v-1)个装备数量+获得状态j的1个装备))
求最后v个装备可获得的最大值
【因为dp学得不好,比较难缕思路,多多包涵】
代码:
#include
using namespace std;
const int maxn=10010;
int n,k;
int a[maxn][5];
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(a,0,sizeof(a));
int r[5]={0};
for(int i=0;i=5)
{
printf("%d\n",r[0]+r[1]+r[2]+r[3]+r[4]);
continue;
}
int sum,ans=0;
int dp[1<<5][5]={0};
dp[0][0]=0;
for(int i=0;i<32;i++)//第i种状态 0 0 0 0 0;0 0 0 0 1;0 0 0 1 0;0 0 0 1 1 …… 1 1 1 1 1
{
for(int j=0;j