三种解法:多重背包转化为完全背包和01背包;多重背包通过二进制化化为01背包;通过计数法优化为2重循环。
code1: 47MS
#include <cstdio>
#include <cstring>
#define Max(a,b) (a) >(b)?(a):(b)
int dp[100005], Cost[11], Count[11], cash;
void ZeroOnePack(int cost)
{
int i;
for(i=cash; i>=cost; --i)
dp[i] = Max(dp[i], dp[i-cost]+cost);
}
void CompletePack(int cost)
{
int i;
for(i=cost; i<=cash; ++i)
dp[i] = Max(dp[i], dp[i-cost]+cost);
}
void MultiplePack(int cost, int count)
{
if(cost*count > cash)
CompletePack(cost);
else
{
int k=1;
while(k < count)
{
ZeroOnePack(k*cost);
count -= k;
k <<=1;
}
ZeroOnePack(count*cost);
}
}
int main()
{
int n, i, j, k;
while(~scanf("%d%d",&cash,&n))
{
for(i=1; i<=n; ++i)
scanf("%d%d",&Count[i],&Cost[i]);
memset(dp, 0, sizeof dp );
for(i=1; i<=n; ++i)
MultiplePack(Cost[i], Count[i]);
printf("%d\n", dp[cash]);
}
return 0;
}
code2: 110MS
#include <cstdio>
#include <cstring>
#define Max(a,b) (a) >(b) ? (a):(b)
int dp[100010];
int n[230], w[230], v, N;
int b[11] = {1,2,4,8,16,32,64,128,256,512,1024};
int main()
{
int i, j, cash, Count, k;
int nn, ww;
while(~scanf("%d%d",&cash,&N)) {
Count = 1;
for(i=1; i<=N; ++i) {
scanf("%d%d",&nn,&ww);
if(nn!=0) {
for(j=10; j>=0; --j)
if(nn-b[j]+1>0)
break;
for(k=0; k<=j-1; ++k) {
n[Count] = b[k];
w[Count] = ww*b[k];
Count++;
}
n[Count] = nn-b[j]+1;
w[Count]=ww*(nn-b[j]+1);
Count++;
}
}
Count--;
memset(dp, 0, sizeof dp );
for(i=1; i<=Count; ++i)
for(v=cash; v>=0; --v)
if(v-w[i]>=0)
dp[v] = Max(dp[v], dp[v-w[i]] + w[i]);
printf("%d\n", dp[cash]);
}
return 0;
}
//1、可以采有计数的方法代替单调队列将时间复杂度降到o(vn)
//注:计数的这种方法解决多重背包时有限制,只能解决体积与价值相等的情况
#include <cstdio>
#include <cstring>
int main()
{
int i, j, cash, n, v[15], nums[15];
int opt[100010];
int cnt[100010];
while(~scanf("%d%d",&cash,&n)) {
for(i=0; i<n; ++i)
scanf("%d%d",&nums[i],&v[i]);
for(i=0; i<=cash; ++i)
opt[i] = 0;
for(i=0; i<n; ++i) {
memset(cnt, 0, sizeof(int)*(cash+1));
for(j=v[i]; j<=cash; ++j) {
if(opt[j] <opt[j-v[i]]+v[i]&&cnt[j-v[i]]<nums[i]) {
cnt[j] = cnt[j-v[i]]+1;
opt[j] = opt[j-v[i]] + v[i];
}
}
}
printf("%d\n",opt[cash]);
}
return 0;
}
本文介绍了多重背包问题的三种高效解法:通过转化成完全背包和01背包问题、利用二进制化技术减少状态数量以及采用计数法优化算法至两重循环。提供了三种不同思路的代码实现。
738

被折叠的 条评论
为什么被折叠?



