题目链接:
多重背包:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
有两种思路,其中一种是转换为01背包,还有一种就是转换为01背包和完全背包。
转换为01背包代码:
//转换为01背包的代码#include#include #include using namespace std;const int N=105;const int MAXW=4005;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=0; i >w[i]>>v[i]>>num[i]; memset(dp,0,sizeof(dp)); for(int i=0; i =w[i]; k--) dp[k]=max(dp[k],dp[k-w[i]] +v[i]); cout< <
多重背包转换成完全背包和01背包:
0--N中的任何一个数都可以用N的二进制的位数个数表示,这些数分别是1....1<<i untile 1<<i < N && 1<<(i+1) >N 另外一个是N-前面所有二进制数的总和。
所以多重背包转换成完全背包和01背包的过程中01背包的部分可以用二进制优化。
代码:
#include#include #include #include using namespace std;#define ll long longint p[205],w[205],c[205];int dp[105];int main(){ int T; cin>>T; while(T--) { int n,m; cin>>n>>m; for(int i=1; i<=m; i++) cin>>p[i]>>w[i]>>c[i]; memset(dp,0,sizeof(dp)); for(int i=1; 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=1; for(int j=1; c[i]>0; j<<=1) { 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< <