首页 > 代码库 > ZOJ 3769 Diablo III(分组背包)

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(分组背包)