正文
hdu2191 多重背包
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2191
多重背包:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
有两种思路,其中一种是转换为01背包,还有一种就是转换为01背包和完全背包。
转换为01背包代码:
//转换为01背包的代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;const int N=;
const int MAXW=;
int v[N],w[N],num[N];
int dp[MAXW];int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=; i<m; i++)
cin>>w[i]>>v[i]>>num[i];
memset(dp,,sizeof(dp));
for(int i=; i<m; i++)
for(int j=; j<=num[i]; j++)
for(int k=n; k>=w[i]; k--)
dp[k]=max(dp[k],dp[k-w[i]] +v[i]);
cout<<dp[n]<<endl;
}
return ;
}
多重背包转换成完全背包和01背包:
0--N中的任何一个数都可以用N的二进制的位数个数表示,这些数分别是1....1<<i untile 1<<i < N && 1<<(i+1) >N 另外一个是N-前面所有二进制数的总和。
所以多重背包转换成完全背包和01背包的过程中01背包的部分可以用二进制优化。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define ll long longint p[],w[],c[];
int dp[];int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
for(int i=; i<=m; i++)
cin>>p[i]>>w[i]>>c[i];
memset(dp,,sizeof(dp));
for(int i=; i<=m; i++)
{
if(p[i]*c[i]>m)
{
for(int j=p[i]; j<=n; j++)
dp[j]=max(dp[j],dp[j-p[i]]+w[i]);
}
else
{
int k=;
for(int j=; c[i]>; j<<=)
{
int temp=min(j,c[i]);
for(int q=n; q>=temp*p[i]; q--)
dp[q]=max(dp[q],dp[q-p[i]*temp]+w[i]*temp);
c[i]-=j;
}
}
}
cout<<dp[n]<<endl;
}
return ;
}