Description
Krito为了打败第一层的boss - The eye of giant.SAO系统种一个人物可以装备4个物品,分别是左手武器,右手武器,首饰,盔甲,这些都可以增加一定的攻击力。注意每一种装备只能在所属的装备槽,双手武器会同时占用左手武器和右手武器的位置。还有有些首饰和特定的盔甲搭配可以产生不同的加成效果。在现在Krito有很多装备选择,当是他只有一定的金币,他想要获得最高的攻击力,问他应该怎么选择自己的装备才能使攻击力最高.
Input
第1行: 一个数T表示有多少个测试样例(T<=100)
对于每一个测试样例:
第1行:5个数m,a,b,c,d,表示Krito有m个金币,a种头盔,b种首饰,c种武器,d种双手武器(0<=m <=10000,0<=a,b,c,d<=100)
第2至2+a行: 表示可选的头盔,每行两个数,money,atk,表示这个物品的价格,和相应的攻击力加成(0<=money,atk<=100)
第3+a至3+a+b行:表示可选的首饰,每行四个数, money,atk,id,buff . id表示该件首饰如果和编号为id(从0开始)的头盔搭配可以获得buff的攻击力加成(|buff|<=100),id=-1和buff=-1表示没有加成效果
第4+a+b至4+a+b+c行: 表示可选的单手武器,可以装备在单手或者右手槽,注意每种武器只有一个,每行两个数,money,atk,表示这个物品的价格,和相应的攻击力加成(0<=money,atk<=100)
第5+a+b+c至5+a+b+c+d行: 表示可选的双手武器,每行两个数,money,atk,同上。
Output
输出能够获得的最大攻击力。
Sample Input
2
10 1 1 0 0
5 5
5 5 -1 -1
10 1 1 0 0
5 5
5 5 0 10
Sample Output
10
20
代码做了些优化,所以比较长,简单来说,思路就是:把{头盔,头盔+首饰,首饰}合成一组,{单手武器,两个单手武器,双手武器}合成一组。然后题目就变成有两组东西,每组最多只能选一种,问在只有m个金币的情况下,怎么选最优。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
#define UINF 18446744073709551615
#define MOD 1000000007
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int m,a,b,c,d;
int dp[405];
struct Head
{
int money;
int atk;
} head[105*105];
bool cmp2(Head a,Head b)
{
if(a.money==b.money)
return a.atk>b.atk;
return a.money<b.money;
}
struct Hand
{
int money;
int atk;
}hand[105*105];
bool cmp3(Hand a,Hand b)
{
return a.money<b.money;
}
bool cmp4(Hand a,Hand b)
{
if(a.money==b.money)
return a.atk>b.atk;
return a.money<b.money;
}
int main()
{
int t;
int money,atk,id,buff;
scanf("%d",&t);
while(t--)
{
int Count=0;
mem(dp,0);
scanf("%d %d %d %d %d",&m,&a,&b,&c,&d);
m=min(400,m);
for(int i=0; i<a; i++)
{
scanf("%d %d",&money,&atk);
head[Count].money=money;
head[Count++].atk=atk;
}
for(int i=0; i<b; i++)
{
scanf("%d %d %d %d",&money,&atk,&id,&buff);
if(money>m) continue;
for(int j=0; j<Count; j++)
{
head[a].money=money+head[j].money;
if(head[a].money>m) continue;
if(j==id)
head[a++].atk=head[j].atk+buff+atk;
else
head[a++].atk=head[j].atk+atk;
}
head[a].money=money;
head[a++].atk=atk;
}
sort(head,head+a,cmp2);
int now_Max=-1;
Count=0;
for(int i=0;i<a;i++)
{
if(head[i].atk>now_Max)
{
head[Count++]=head[i];
now_Max=head[i].atk;
}
}
a=Count;
Count=0;
for(int i=0;i<c;i++)
{
scanf("%d %d",&money,&atk);
if(money>m) continue;
hand[Count].money=money;
hand[Count++].atk=atk;
}
c=Count;
sort(hand,hand+c,cmp3);
for(int i=0;i<Count;i++)
{
for(int j=i+1;j<Count;j++)
{
hand[c].money=hand[i].money+hand[j].money;
if(hand[c].money>m) break;
hand[c++].atk=hand[i].atk+hand[j].atk;
}
}
for(int i=0;i<d;i++)
{
scanf("%d %d",&money,&atk);
if(money>m) continue;
hand[c].money=money;
hand[c++].atk=atk;
}
sort(hand,hand+c,cmp4);
now_Max=-1;
Count=0;
for(int i=0;i<c;i++)
{
if(hand[i].atk>now_Max)
{
hand[Count++]=hand[i];
now_Max=hand[i].atk;
}
}
c=Count;
for(int i=m;i>=0;i--)
{
for(int j=0;j<a;j++)
{
if(head[j].money<=i)
dp[i]=max(dp[i],dp[i-head[j].money]+head[j].atk);
else break;
}
}
for(int i=m;i>=0;i--)
{
for(int j=0;j<c;j++)
{
if(hand[j].money<=i)
dp[i]=max(dp[i],dp[i-hand[j].money]+hand[j].atk);
else break;
}
}
printf("%d\n",dp[m]);
}
return 0;
}
/**************************************************************
Language: C++
Time:28 ms
Memory:1740 kb
****************************************************************/