您的位置:首页 > 其它

ZOJ 3769 Diablo III(分组背包)

2017-07-25 08:43 375 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3769

题意:
有13种装备,每种装备值可以穿戴一种,特殊的就是双手武器和单手武器,双手武器和单手武器+盾只能选择一种,戒指可以双手各戴一个。每个装备都有一个攻击值和防御值,现在要在防御值至少到达m的情况下可以达到的最大攻击力。

思路:
分组背包题目。

把单手武器和盾组合起来放到双手武器当中,戒指也需要两两组合。

接下来就是一个分组背包了,比较重要的是这道题目需要开二维数组,因为题目要求的是至少要达到m的容量,如果超过了m容量,就需要按m来算。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = 400 + 5;

int n,m;
int d[15][50005];
vector<pll> v[15];
map<string,int> ID;

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

bool cmp(const vector<pll> a, const vector<pll> b)
{
return a.size()>b.size();
}

int main()
{
//freopen("in.txt","r",stdin);
init();
int T;
scanf("%d",&T);
while(T--)
{
for(int i=1;i<13;i++)  v[i].clear();

scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
int D,T; string s;
cin>>s>>D>>T;
v[ID[s]].push_back(make_pair(D,T));
if(ID[s]==11 || ID[s]==12)  v[13].push_back(make_pair(D,T));
}

//合并单手武器和盾牌
for(int i=0;i<v[11].size();i++)
{
for(int j=0;j<v[12].size();j++)
{
v[13].push_back(make_pair(v[11][i].first+v[12][j].first,v[11][i].second+v[12][j].second));
}
}

v[11].clear();
v[12].clear();

//合并戒指并且储存在v[10]中
int len=v[10].size();
for(int i=0;i<len;i++)
{
for(int j=i+1;j<len;j++)
{
v[10].push_back(make_pair(v[10][i].first+v[10][j].first,v[10][i].second+v[10][j].second));
}
}

memset(d,-1,sizeof(d));
sort(v+1,v+14,cmp);

d[0][0]=0;
for(int i=1;i<=11;i++)
{
for(int j=0;j<=m;j++)
{
d[i][j]=max(d[i][j],d[i-1][j]);  //第i组的状态有第i-1组状态而来
if(d[i-1][j]==-1)  continue;
for(int k=0;k<v[i].size();k++)
{
int tmp=min(v[i][k].second+j,m);  //如果容量超过了m,那么就按m来算
d[i][tmp]=max(d[i][tmp],d[i-1][j]+v[i][k].first);  //由第i-1组更新
}
}
}
printf("%d\n",d[11][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: