ZOJ - 3769 Diablo III 分组背包

 题意:

有13种装备,每种装备只能选一个,每种装备有一个伤害值和防御值,其中如果选Two-Handed的话就不能选Shield和

Weapon,Finger可以选两个。求怎样选择,使得在防御值达最小到m的情况下,伤害总值最大。

分析:

将限制条件进行合并那么这就是一道分组背包的问题,同时因为防御最小为m,所以将防御大于m的时候看成等于m进行计算就方便了很多,那么在递推的时候也要注意,类似于push,而不是pull,因为push正好解决了大于m的情况。

#include<bits/stdc++.h>

using namespace std;

struct node{
    int dam,tou;
    node(int dam,int tou):dam(dam),tou(tou){}
    node(){}
};

map<string,int> mp;
vector<node> g[15];

void init(){
    mp["Weapon"] = 1;
    mp["Shield"] = 2;
    mp["Two-Handed"] = 3;
    mp["Finger"] = 4;
    mp["Feet"] = 5;
    mp["Legs"] = 6;
    mp["Waist"] = 7;
    mp["Wrist"] = 8;
    mp["Hand"] = 9;
    mp["Torso"] = 10;
    mp["Neck"] = 11;
    mp["Shoulder"] = 12;
    mp["Head"] = 13;
}

char s[50];

int dp[15][50005];

int main(){
    int T;
    init();
    scanf("%d",&T);
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=13;i++) g[i].clear();
        for(int i=1;i<=n;i++){
            int dam,tou;
            scanf("%s%d%d",s,&dam,&tou);
            g[mp[s]].push_back(node(dam,tou));
        }
//        cout<<"dasda  "<<g[3].size()<<endl;
        int len1=g[1].size();
        for(int i=0;i<len1;i++){
            g[3].push_back(g[1][i]);
        }
        int len2=g[2].size();
        for(int i=0;i<len2;i++){
            g[3].push_back(g[2][i]);
            for(int j=0;j<len1;j++){
                g[3].push_back(node(g[2][i].dam+g[1][j].dam,g[2][i].tou+g[1][j].tou));
            }
        }
        int len4=g[4].size();
        for(int i=0;i<len4;i++){
            for(int j=i+1;j<len4;j++){
                g[4].push_back(node(g[4][i].dam+g[4][j].dam,g[4][i].tou+g[4][j].tou));
            }
        }
        memset(dp,-1,sizeof dp);
        dp[2][0]=0;
        for(int k=3;k<=13;k++){
            for(int i=0;i<=m;i++){
                dp[k][i]=max(dp[k-1][i],dp[k][i]);
                if(dp[k-1][i]==-1) continue;
                int len=g[k].size();
                for(int j=0;j<len;j++){
                    int tmp=min(m,g[k][j].tou+i);
                    dp[k][tmp]=max(dp[k-1][i]+g[k][j].dam,dp[k][tmp]);
                }
            }
        }
        printf("%d\n",dp[13][m]);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值