/*
Name:多重背包 二进制优化 (DP)
Actor:HT
Time:2015年11月2日
Error Reporte:
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#define N 10010
using namespace std;
int dp[100];
int value[N];
int cost[N];
int size[N]; //数量
int n, m; //n个宝石 m大小背包
int main()
{
int t, i, j, k;
int temp;
while (scanf("%d %d", &n,&m) != EOF)
{
for (i = 0; i < n; i++)
{
scanf("%d %d %d", &value[i], &cost[i], &size[i]);
}
for (i = 0; i < m; i++)
{
dp[i] = 0; //初始化
}
for (i = 0; i < n; i++)
{
if (size[i] * cost[i] >= m) //如果个数足够多,当做完全背包处理
{
for (j = cost[i]; j <= m; j++)
{
dp[j] = (dp[j]>dp[j - cost[i]] + value[i]) ? dp[j] : dp[j - cost[i]] + value[i];
}
}
else //不够多,那就二进制拆成01背包吧
{
int div1, div2; //div1是已经看了的小堆(1、2、4...),div2是剩余所有量
div1 = 1;
div2 = size[i];
while (div1 < div2)
{
for (j = m; j >= div1*cost[i]; j--)
{
dp[j] = dp[j]>dp[j - div1*cost[i]] + div1*value[i] ? dp[j] : (dp[j - div1*cost[i]] + div1*value[i]);
}
div2 -= div1;
div1 *= 2;
}
for (j = m; j >= div2*cost[i]; j--) //剩余的量再补一次
{
dp[j] = dp[j]>dp[j - div2*cost[i]] + div2*value[i] ? dp[j] : (dp[j - div2*cost[i]] + div2*value[i]);
}
}
}
printf("%d\n", dp[m]);
}
return 0;
}
//dp[j] = (隐含:看了i个宝石,)背包剩余空间j
//dp[j] = max{dp[j] , dp[j-c[i]] + v[i]}
//后记:二进制思想
//假设有1000个苹果,现在要取n个苹果,如何取?
//正常的做法应该是将苹果一个一个拿出来,直到n个苹果被取出来。
//又假设有1000个苹果和10只箱子,如何快速的取出n个苹果呢?
//可以在每个箱子中放 2^i (i<=0<=n)个苹果,也就是 1、2、4、8、16、32、64、128、256、489(最后的余数)
//相当于把十进制的数用二进制来表示,取任意n个苹果时,只要推出几只箱子就可以了。
//二进制优化的思路,就是将M个相同物品,堆分成1、2、4、8、...这“几个”大小不等的物品
//通过对这几个堆的取舍,来完成达到拿走n个物品的的最优情况
[算法]动态规划 多重背包 二进制优化
最新推荐文章于 2022-11-25 14:34:24 发布