题目描述
美丽的牛家庄受到了外星人的侵略, 勇敢的妞妞要上战场抵御侵略。
在妞妞上战场前, 村长牛牛给了妞妞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 <bits/stdc++.h>
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<n;i++)
{
scanf("%d%d%d%d%d",&a[i][0],&a[i][1],&a[i][2],&a[i][3],&a[i][4]);
for(int j=0;j<5;j++)r[j]=max(r[j],a[i][j]);
}
if(k>=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<n;j++)//第j个装备的
{
sum=0;
for(int v=0;v<5;v++)//五个属性
{
int s=1<<v;//将第(v+1)个属性置为1其余为0
//只有状态i中为1的位置才与s位与 不为0
if((i&s)!=0)
{
sum+=a[j][v];
}
}
//只有一个装备 取 只对应状态属性的属性和
//如dp[1][1]; 0 0 0 0 1 只去第一个属性和最大的 一个装备
//dp[3][1]; 0 0 0 1 1 只取 第一和第二和属性和最大的 一个装备
dp[i][1]=max(dp[i][1],sum);
}
ans=max(ans,dp[i][1]);
}
for(int v=2;v<=k;v++)
{
for(int i=0;i<32;i++)
{
for(int j=0;j<32;j++)
{
if((i&j)==0) //i与j的状态 即没有同一种属性取两次
{
//两种状态相加后的 v个装备
dp[i|j][v]=max(dp[i|j][v],dp[i][v-1]+dp[j][1]);
ans=max(ans,dp[i|j][v]);
}
}
}
}
printf("%d\n",ans);
}
}
在牛家庄遭受外星人侵袭的背景下,妞妞需从N件装备中选择K件以最大化战斗力。通过动态规划算法,考虑装备间属性影响,计算最优装备组合以提升妞妞的战斗能力。
284

被折叠的 条评论
为什么被折叠?



