题意:
有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;
}