传送门:HDU 5410
题目大意:
你有M单位的钱,有N种东西,每种东西的花费为 Wi,每种东西买 x 个可以获得 Ai * x + Bi 的奖励,问最多可以获得的奖励是多少。
Sample Input
1 100 2 10 2 1 20 1 1
Sample Output
21
思路:
这个题是一看题一脸懵逼,然后一看题解觉得特别对,特别简单的题……感觉就是用到了抽象思维,不要去关注各种背包的原理和代码实现,而是去关注各种背包能做什么。我们发现无论买多少个同种物品都只加1个Bi,所以,可以把它看成买第1个的时候的奖励为 Ai + Bi,其他时候的奖励为 Ai。
具体实现:
所以抽象到具体做法上就是对于每个物品先放入1个看看能导致的最大奖励值,然后再在放入1个的基础上放入多个,也就是先跑一遍01背包,再跑一遍完全背包。你可能会说,也可能在01背包的时候这种物品没放入,而在完全背包的时候放入这件物品了啊,这样就少加了个 Bi,其实这种情况是不可能的,只放一个的时候获得的奖励肯定比放入多个的时候更优,所以不放入第一个就放入第多个是不可能的。
#include<stdio.h>
#include<string.h>
int max(int a,int b)
{
if(a>b) return a;
else return b;
}
int main()
{
int i,j,t,m,n,w[1010],a[1010],b[1010],dp[2010];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++) scanf("%d%d%d",&w[i],&a[i],&b[i]);
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=m;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+a[i]+b[i]);
for(j=w[i];j<=m;j++) dp[j]=max(dp[j],dp[j-w[i]]+a[i]);
}
printf("%d\n",dp[m]);
}
return 0;
}