ZOJ 3769-Diablo III(DP)

描述

Diablo III is an action role-playing video game. A few days ago, Reaper of Souls (ROS), the new expansion of Diablo III, has been released! On hearing the news, the crazy video game nerd Yuzhi shouted: "I'm so excited! I'm so excited! I wanna kill the Diablo once more!"

The ROS introduced a lot of new features and changes. For example, there are two new attributes for players in the game: Damage and Toughness. The attribute Damage indicates the amount of damage per second you can deal and the Toughness is the total amount of raw damage you can take.

To beat the Diablo, Yuzhi need to select the most suitable equipments for himself. A player can carry at most 13 equipments in 13 slots: Head, Shoulder, Neck, Torso, Hand, Wrist, Waist, Legs, Feet, Shield, Weapon and 2 Fingers. By the way, there is a special type of equipment: Two-Handed. A Two-Handed equipment will occupy both Weapon and Shield slots.

Each equipment has different properties on Damage and Toughness, such as a glove labeled "30 20" means that it can increase 30 Damage and 20 Toughness for the player who equips it in the Hand slot. The total Damage and Toughness is the sum of Damage and Toughness of all equipments on the body. A player without any equipments has 0 Damage and 0 Toughness.

Yuzhi has N equipments stored in his stash. To fight against the Diablo without lose the battle, he must have at least M Toughness. In addition, he want to finish the battle as soon as possible. That means the Damage should be as much as possible. Please help Yuzhi to determine which equipments he should take.

输入

There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:

The first line contains 2 integers N (1 <= N <= 300) and M (0 <= M <= 50000). The next N lines are the description of equipments. The i-th line contains a string Si and two integers Di and Ti (1 <= Di, Ti <= 50000). Si is the type of equipment in {"Head", "Shoulder", "Neck", "Torso", "Hand", "Wrist", "Waist", "Legs", "Feet", "Finger", "Shield", "Weapon", "Two-Handed"}. Di and Ti are the Damage and Toughness of this equipment.

输出

For each test case, output the maximum Damage that Yuzhi can get, or -1 if he can not reach the required Toughness.

样例输入

2
1 25
Hand 30 20
5 25
Weapon 15 5
Shield 5 15
Two-Handed 25 5
Finger 5 10
Finger 5 10

样例输出

-1
35

题意:给出13类装备,每种装备都有攻击力和防御值,每种装备只允许选择一个,13种装备里如果选择了双手装备,就不能选择武器和护盾了,还有戒指可以双手各带一个,求满足防御值至少在M的情况下,攻击力最大为多少。

解题思路:设dp[i][j]为前i种装备,防御值达到j的时候的最大攻击力。那么可以有dp[i][j + t] = max(dp[i][j + t], dp[i - 1][j] + d)这里dp[i - 1][j]不等于-1,也就是必须先能达到这个防御值。可以把武器和护盾单独作为一件双手装备或者把两者合起来组合成一个双手装备。选择单个戒指就相当于只有一只手戴戒指,把戒指两两组合起来也就相当于双手都带了戒指。不过这里的M比较大,直接从第一类装备开始递推可能会超时,由于种类之间没有关系所以从哪个种类开始递推都没有关系,所以可以倒着来推,把数量较大的种类作为递推起点,可以省下很多时间。还有这里用一维可能会出问题,代码中当k=m=kk时可能会同类取了多个

转载自博客:https://blog.csdn.net/a664607530/article/details/70216835

#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#define MAXN 310
using namespace std;

int n,m;
map< string , int > M;
int max(int a, int b){
    if(a>b)return a;
    else return b;
}
void init(){
    M["Head"]=0;
    M["Shoulder"]=1;
    M["Neck"]=2;
    M["Torso"]=3;
    M["Hand"]=4;
    M["Wrist"]=5;
    M["Waist"]=6;
    M["Legs"]=7;
    M["Feet"]=8;
    M["Shield"]=9;//finger
    M["Weapon"]=10;
    M["Finger"]=11;
    M["Two-Handed"]=12;
}
struct Node
{
    int d,t;
}nod;
vector<Node> V[13];//存储同类物品
int dp[13][50001];
int vd,vt;
void read(){
    int i,j,d,t;
    char ch[30];
    scanf("%d %d" ,&n ,&m);
    for(i=0; i<13; i++){
        V[i].clear();
    }
    for(i=0; i<n; i++){
        scanf("%s %d %d" ,ch , &d ,&t);
        int index=M[string(ch)];
        nod.d=d;
        nod.t=t;
        V[index].push_back( nod );
        if(index==9 || index==10){
            V[12].push_back( nod );
        }
    }
    //两只手的装备
    for(i=0; i<V[9].size(); i++){
        for(j=0; j<V[10].size(); j++){
            nod.d=V[9][i].d+V[10][j].d;
            nod.t=V[9][i].t+V[10][j].t;
            V[12].push_back( nod );  
        }
    }
    //存戒指
    V[9].clear();
    for(i=0; i<V[11].size(); i++){
        V[9].push_back( V[11][i] );
        for(j=i+1; j<V[11].size(); j++){
            nod.d=V[11][i].d+V[11][j].d;
            nod.t=V[11][i].t+V[11][j].t;
            V[9].push_back( nod );
        }
    }
    V[11].clear();
}

int main(){
    init();
    int t;
    int i,j,k;
    scanf("%d" ,&t);
    while( t-- ){
        read();
        memset(dp,-1,sizeof(dp));
        //12单独处理一下,存到9
        dp[10][0]=0;
        for(i=0; i<V[12].size(); i++){
            nod=V[12][i];
            if(nod.t>m){
                vt=m;
            }else{
                vt=nod.t;
            }
            vd=nod.d;
            dp[10][vt]=max( dp[10][vt] , vd );
        }
        for(k=9; k>=0; k--){
            for(j=0; j<=m; j++){
                dp[k][j]=max( dp[k][j],dp[k+1][j] );
                if( dp[k+1][j]==-1 )continue;
                /*
                    dp[k][j] 表示k件装备,它所用的防御是j的伤害
                    当前装备伤害+之前伤害最大值
                    dp[k][vt]=max( dp[k][vt], nod.d+dp[k+1][j] )
                */
                for(i=0; i<V[k].size(); i++){
                    nod=V[k][i];
                    if( nod.t +j > m ){
                        vt=m;
                    }else{
                        vt=nod.t +j;
                    }
                    dp[k][vt]=max( dp[k][vt], nod.d+dp[k+1][j] );
                }
            }
        }
        printf("%d\n" ,dp[0][m]);
    }
    return 0;
}

 




转载于:https://www.cnblogs.com/LJHAHA/p/10457519.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值