题目描述
现在 absi2011 拿出了 xx 个迷你装药物(嗑药打人可耻…),准备开始与那些人打了。
由于迷你装药物每个只能用一次,所以 absi2011 要谨慎的使用这些药。悲剧的是,用药量没达到最少打败该人所需的属性药药量,则打这个人必输。例如他用 22 个药去打别人,别人却表明 33 个药才能打过,那么相当于你输了并且这两个属性药浪费了。
现在有 nn 个好友,给定失败时可获得的经验、胜利时可获得的经验,打败他至少需要的药量。
要求求出最大经验 ss,输出 5s5s。
输入格式
第一行两个数,nn 和 xx。
后面 nn 行每行三个数,分别表示失败时获得的经验 lose_ilosei,胜利时获得的经验 win_iwini 和打过要至少使用的药数量 use_iusei。
输出格式
一个整数,最多获得的经验的五倍。
样例输入
6 8 21 52 1 21 70 5 21 48 2 14 38 3 14 36 1 14 36 2
样例输出
1060
问题提示
- 对于 10\%10% 的数据,保证 x=0x=0。
- 对于 30\%30% 的数据,保证 0\le n\le 10,0\le x\le 200≤n≤10,0≤x≤20。
- 对于 60\%60% 的数据,保证 0\le n,x\le 1000≤n,x≤100, 10<lose_i,win_i\le 10010<losei,wini≤100,0\le use_i\le 50≤usei≤5。
- 对于 100\%100% 的数据,保证 0\le n,x\le 10^30≤n,x≤103,0<lose_i\le win_i\le 10^6,0\le use_i\le 10^30<losei≤wini≤106,0≤usei≤103。
这就是01背包的变形,可用二维数组,也可用滚动数组优化
二维
#include<bits/stdc++.h>
using namespace std;
int n,x;
long long use[1100],dp[1100][1010],lose[1010],win[1010];
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>lose[i]>>win[i]>>use[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=x;j++)
{
if(j>=use[i])
{
dp[i][j]=max(dp[i-1][j]+lose[i],dp[i-1][j-use[i]]+win[i]);
}
else
{
dp[i][j]=dp[i-1][j]+lose[i];
}
}
}
cout<<dp[n][x]*5;
return 0;
}
滚动数组优化
#include<bits/stdc++.h>
using namespace std;
int n,x;
long long use[1100],dp[1100],lose[1010],win[1010];//dp[j]表示 背包容量为j时获得的经验
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>lose[i]>>win[i]>>use[i];
}
for(int i=1;i<=n;i++)//枚举药物
{
for(int j=x;j>=0;j--)
{
if(j>=use[i])
dp[j]=max(dp[j]+lose[i],dp[j-use[i]]+win[i]);
else
dp[j]=dp[j]+lose[i];
}
}
cout<<dp[x]*5;
return 0;
}