您的位置:首页 > 其它

HDU 1085 多重背包转化为0-1背包问题

2014-12-24 10:52 225 查看
题目大意:

给定一堆1,2,5价值的硬币,给定三个数表示3种价值硬币的数量,任意取,找到一个最小的数无法取到

总价值为M = v[i]*w[i](0<=i<3)

那么在最坏情况下M个数都能取到 , M+1必然取不到

所以给M+1个背包,往里面塞东西,最后由前往后检测,找到第一个无法取满的背包的体积

这道题目里,每一种物品的v*w必然小于M+1,所以不出现完全背包的情况,全部采用多重背包转化为0-1背包解决问题即可

#include <cstdio>
#include <cstring>

using namespace std;
#define max(a,b) a>b?a:b
const int N = 10000;

int dp
, a[3] , M;
int v[3] = {1 , 2 , 5};
void zeroPack(int w , int v)
{
for(int i = M ; i >= w ; i--)
dp[i] = max(dp[i-w]+v , dp[i]);
}

void multiPack(int n , int w , int v)
{
int t = 1;
while(n > t){
zeroPack(t*w , t*v);
n -= t;
t <<= 1;
}
if(n > 0) zeroPack(n*w , n*v);
}

int main()
{
while(1){
M = 0;
for(int i = 0 ; i<3 ; i++){
scanf("%d" , a+i);
M += a[i] * v[i];
}
if(M == 0) break;
//这里加一表示可能你加起来的总值都能够取到,但是多加个一,那么必然会有一个最大值取不到
M += 1;
memset(dp , 0 ,sizeof(dp));
for(int i = 0 ; i<3 ; i++){
multiPack(a[i] , v[i] , v[i]);
}

int k = 0;
while(dp[k] == k) k++;
printf("%d\n" , k);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: