ZOJ 3769 Diablo III(分组背包)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ 3769 Diablo III(分组背包)相关的知识,希望对你有一定的参考价值。
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3769
题意:
有13种装备,每种装备值可以穿戴一种,特殊的就是双手武器和单手武器,双手武器和单手武器+盾只能选择一种,戒指可以双手各戴一个。每个装备都有一个攻击值和防御值,现在要在防御值至少到达m的情况下可以达到的最大攻击力。
思路:
分组背包题目。
把单手武器和盾组合起来放到双手武器当中,戒指也需要两两组合。
接下来就是一个分组背包了,比较重要的是这道题目需要开二维数组,因为题目要求的是至少要达到m的容量,如果超过了m容量,就需要按m来算。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn = 400 + 5; 17 18 int n,m; 19 int d[15][50005]; 20 vector<pll> v[15]; 21 map<string,int> ID; 22 23 void init() 24 { 25 ID["Head"] = 1; ID["Shoulder"] = 2; ID["Neck"] = 3; 26 ID["Torso"] = 4; ID["Hand"] = 5; ID["Wrist"] = 6; 27 ID["Waist"] = 7; ID["Legs"] = 8; ID["Feet"] = 9; 28 ID["Finger"] = 10; ID["Shield"] = 11; ID["Weapon"] = 12; 29 ID["Two-Handed"] = 13; 30 } 31 32 bool cmp(const vector<pll> a, const vector<pll> b) 33 { 34 return a.size()>b.size(); 35 } 36 37 int main() 38 { 39 //freopen("in.txt","r",stdin); 40 init(); 41 int T; 42 scanf("%d",&T); 43 while(T--) 44 { 45 for(int i=1;i<13;i++) v[i].clear(); 46 47 scanf("%d%d",&n,&m); 48 for(int i=0;i<n;i++) 49 { 50 int D,T; string s; 51 cin>>s>>D>>T; 52 v[ID[s]].push_back(make_pair(D,T)); 53 if(ID[s]==11 || ID[s]==12) v[13].push_back(make_pair(D,T)); 54 } 55 56 //合并单手武器和盾牌 57 for(int i=0;i<v[11].size();i++) 58 { 59 for(int j=0;j<v[12].size();j++) 60 { 61 v[13].push_back(make_pair(v[11][i].first+v[12][j].first,v[11][i].second+v[12][j].second)); 62 } 63 } 64 65 v[11].clear(); 66 v[12].clear(); 67 68 //合并戒指并且储存在v[10]中 69 int len=v[10].size(); 70 for(int i=0;i<len;i++) 71 { 72 for(int j=i+1;j<len;j++) 73 { 74 v[10].push_back(make_pair(v[10][i].first+v[10][j].first,v[10][i].second+v[10][j].second)); 75 } 76 } 77 78 memset(d,-1,sizeof(d)); 79 sort(v+1,v+14,cmp); 80 81 d[0][0]=0; 82 for(int i=1;i<=11;i++) 83 { 84 for(int j=0;j<=m;j++) 85 { 86 d[i][j]=max(d[i][j],d[i-1][j]); //第i组的状态有第i-1组状态而来 87 if(d[i-1][j]==-1) continue; 88 for(int k=0;k<v[i].size();k++) 89 { 90 int tmp=min(v[i][k].second+j,m); //如果容量超过了m,那么就按m来算 91 d[i][tmp]=max(d[i][tmp],d[i-1][j]+v[i][k].first); //由第i-1组更新 92 } 93 } 94 } 95 printf("%d\n",d[11][m]); 96 } 97 return 0; 98 }
以上是关于ZOJ 3769 Diablo III(分组背包)的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ 3956 Course Selection System 背包DP