2017Nowcoder Girl E - 勇敢的妞妞(状态压缩+dp)

题目描述 

美丽的牛家庄受到了外星人的侵略, 勇敢的妞妞要上战场抵御侵略。

 

在妞妞上战场前, 村长牛牛给了妞妞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


        

你可能感兴趣的:(Nowcoder,状态压缩,dp,Nowcoder,girl)