题目描述
易大师又在偷龙了,他有n个技能,每个技能都只能用一次,消耗不同的魔法值,造成不同的伤害。大龙共有x点血量,易大师也只有m点魔法值。
由于敌人已经复活了,所以在使用第i个技能前,至少要剩余qi点魔法值,来准备抢龙。
请问能不能偷掉大龙,如果不能,输出最多造成多少伤害。
输入
【输入格式】
第一行 三个整数n,m,x;
第二到n+1行 每行三个整数w,d,q,表耗费,至少剩余多少魔法值才能使用,伤害。
输出
【输出格式】
如果能偷掉,输出“Q”及大龙血量
不然 输出“B”,后一行输出最高伤害。
样例输入
2 4 1
10 15 10
5 10 5
样例输出
B
0
首先什么大龙血量就不扯了,这就是一个DP背包问题,还是一维的,但是有一个问题:
”至少剩余多少魔法值”:这个限制其实是这个题的精髓,
这个限制使得这个问题有了后效性,
为啥?
想一想,设最后一件被选中的物品为第x件,每件物品耗费pi,至少要qi
所以至少需要的背包容量M=p1+p2+…+pn+(qx-px);
而x可以换,则qx-px也可能会变小,换个物品顺序可能出答案,也可能爆0…
所以我们必须排序。
根据之前的例子:
Mmin=p1+p2+…+pn+min(qx-px)
所以最后选qx-px最小的物品,所以从(q-p)大到小排序.
不过打住,01背包问题是倒推的,所以应该从小到大排。
AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int getint(){
int ans=0,flag=0;
char c;
while(1){
c=getchar();
if(c<='9'&&c>='0')
{
ans=ans*10+c-'0';
flag=1;
}
else if(flag) return ans;
}
}
struct node{
int w,d,q;
bool operator <(const node next)const{
return (q-w)<(next.q-next.w);
}
}t[12001];
int n,m,x,f[100001];
int main(){
n=getint(),m=getint(),x=getint();
for(int i=1;i<=n;i++){
t[i].w=getint(),t[i].q=getint(),t[i].d=getint();
if(t[i].q>m||t[i].w>m) i--,n--;
}
sort(t+1,t+1+n);
for(int i=1;i<=n;i++){
for(int j=m;j>=t[i].q;j--)
f[j]=max(f[j],f[j-t[i].w]+t[i].d);
if(f[m]>=x){ printf("Q\n%d",x);return 0; }
}
printf("B\n%d",f[m]);
}