DP - 倍增优化多重背包 - Cash Machine - POJ - 1276
题意:
多 组 测 试 用 例 , 每 组 包 括 价 值 上 限 m , 物 品 种 类 n , n 种 物 品 的 数 量 s 和 价 值 w e 。 多组测试用例,每组包括价值上限m,物品种类n,n种物品的数量s和价值we。 多组测试用例,每组包括价值上限m,物品种类n,n种物品的数量s和价值we。
要 求 在 物 品 总 价 值 不 超 过 m 的 情 况 下 , 从 n 种 物 品 选 择 使 得 体 积 最 大 。 要求在物品总价值不超过m的情况下,从n种物品选择使得体积最大。 要求在物品总价值不超过m的情况下,从n种物品选择使得体积最大。
Sample Input:
735 3 4 125 6 5 3 350
633 4 500 30 6 100 1 5 0 1
735 0
0 3 10 100 10 50 10 10
Sample Output:
735
630
0
0
数据范围:
0 < = m < = 100000 , 0 < = n < = 10 , 0 < = s , w e < = 1000 。 T i m e l i m i t : 1000 m s , M e m o r y l i m i t : 10000 k B 0<=m<=100000,0<=n<=10,0<=s,we<=1000。\\Time\ limit:1000 ms,Memory\ limit:10000 kB 0<=m<=100000,0<=n<=10,0<=s,we<=1000。Time limit:1000ms,Memory limit:10000kB
题解:
将 价 值 上 限 视 作 背 包 体 积 , 物 品 价 值 同 样 视 作 物 品 体 积 , 那 么 问 题 就 转 化 为 多 重 背 包 问 题 : 计 算 从 n 种 物 品 当 中 选 择 总 体 积 不 超 过 m 的 物 品 的 最 大 收 益 。 将价值上限视作背包体积,物品价值同样视作物品体积,那么问题就转化为多重背包问题:\\计算从n种物品当中选择总体积不超过m的物品的最大收益。 将价值上限视作背包体积,物品价值同样视作物品体积,那么问题就转化为多重背包问题:计算从n种物品当中选择总体积不超过m的物品的最大收益。
朴 素 的 多 重 背 包 O ( n m s ) 的 时 间 复 杂 度 显 然 容 易 出 事 , 这 里 用 倍 增 优 化 到 O ( n m l o g s ) 就 够 了 。 朴素的多重背包O(nms)的时间复杂度显然容易出事,这里用倍增优化到O(nmlogs)就够了。 朴素的多重背包O(nms)的时间复杂度显然容易出事,这里用倍增优化到O(nmlogs)就够了。
——《背包问题模板》
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=100010;
int n,m,v[N],w[N],f[N];
int main()
{
while(cin>>m>>n)
{
memset(f,0,sizeof f);
int idx=0;
for(int i=1;i<=n;i++)
{
int we,s;
cin>>s>>we;
int k=1;
while(k<=s)
{
idx++;
w[idx]=we*k;
s-=k;
k*=2;
}
if(s>0)
{
idx++;
w[idx]=we*s;
}
}
n=idx;
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+w[i]);
cout<<f[m]<<endl;
}
return 0;
}