时间长不写代码,感觉变菜了。
整体优化思路和快速幂很相近
如果第i个物品有num[i]个,花费是 c[i] , 价值是 v[i]
那么我们可以把它拆分成数个物品。
比如某个物品数量是14 花费是cost 价值是value
1 2 4 7
就可以把14个相同物品看成 4 个不同的物品,
物品 | 数量 | 花费 | 价值 |
---|---|---|---|
第一个 | 1 | 1*cost | 1*value |
第二个 | 2 | 2*cost | 2*value |
第三个 | 4 | 4*cost | 4*value |
第四个 | 7 | 7*cost | 7*value |
上述四个物品,任意组合就可以组成1-14之间所有可能的取值
所以只要对这四个物品跑0-1背包得到的答案就是对的
我们可以看到,如果物品有1024个,拆分之后只有10个物品,这个优化还是很给力的。
# include <cstdio>
# include <cmath>
# include <algorithm>
using namespace std;
const int maxn = 1e5+10;
int c[maxn],v[maxn],num[maxn];
int dp[maxn];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%d %d %d",&c[i],&v[i],&num[i]);
}
for(int i = 1;i <= n;i++)
{
int k = 1;
while(num[i] >= k || num[i] > 0){
if(num[i] < k) k = num[i];
int cost = k*c[i];
int value = k*v[i];
for(int j = m;j >= cost;j--)
{
dp[j] = max(dp[j],dp[j-cost]+value);
}
num[i] -= k;
k *= 2;
}
}
printf("%d\n",dp[m]);
return 0;
}