多重背包问题

5. 多重背包问题 II - AcWing题库

AC代码:

#include <iostream>
#include<cstring>
#include <algorithm>

using namespace std;

const int N = 12010;
int v[N],w[N];
int f[2][N];
int cnt;
int main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int a,b,s;cin>>a>>b>>s;
        int k=1;
        while ( k<=s )
        {
            cnt++;
            v[cnt]=a*k;
            w[cnt]=b*k;
            s-=k;
            k*=2;
        }
        if(s>0)
        {
            cnt++;
            v[cnt]=a*s;
            w[cnt]=b*s;
        }
    }
    n=cnt;
    int old=1,new1=0;
    for(int i=1;i<=n;i++)
    {
        swap(new1,old);
        for(int j=1;j<=m;j++)
        {
           f[new1][j]=f[old][j];
           if(j>=v[i])
           {
               f[new1][j]=max(f[new1][j],f[old][j-v[i]]+w[i]);
           }
        }
    }
    
    cout<<f[new1][m];
    
    return 0;
}

相关解释:

这里的话,我们直接按照01背包思路来写。但是这里我们不能把一个物品有多少份,而去给它分成多少份,这样的话,会mle。为什么呢?代码如下:
 

#include <iostream>
#include<cstring>
#include <algorithm>

using namespace std;

const int N = 2000010;
const int M = 2010;
int v[N],w[N];
int f[N][M];
int cnt=0;
int main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int a,b,s;cin>>a>>b>>s;
        int k=1;
        while ( k<=s )
        {
            cnt++;
            v[cnt]=a;
            w[cnt]=b;
            s-=k;
        }
    }
    n=cnt;
    for(int i=1;i<=n;i++)
    {

        for(int j=1;j<=m;j++)
        {
           f[i][j]=f[i-1][j];
           if(j>=v[i])
           {
               f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
           }
        }
    }
    
    cout<<f[n][m];
    
    return 0;
}

这里我们的物品的数量是2000*1000,那么空间复杂度2000*1000*2000*4显然大于64000000。数组太大了,那么我们可以用滚动数组优化一下。

代码如下:

#include <iostream>
#include<cstring>
#include <algorithm>

using namespace std;

const int N = 2000010;
const int M = 2010;
int v[N],w[N];
int f[2][M];
int cnt=0;
int main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int a,b,s;cin>>a>>b>>s;
        int k=1;
        while ( k<=s )
        {
            cnt++;
            v[cnt]=a;
            w[cnt]=b;
            s-=k;
        }
    }
    n=cnt;
    int old=1,new1=0;
    for(int i=1;i<=n;i++)
    {
        swap(old,new1);
        for(int j=1;j<=m;j++)
        {
           f[new1][j]=f[old][j];
           if(j>=v[i])
           {
               f[new1][j]=max(f[new1][j],f[old][j-v[i]]+w[i]);
           }
        }
    }
    
    cout<<f[new1][m];
    
    return 0;
}

那么就算你用滚动数组优化了导致不会mle,那么此时也会tle。为什么呢,因为2000*1000*2000>1e8,所以就会tle。那么就要按照AC代码进行二进制优化,优化完就是2000*log(2000)*1000=2000*1000*11<1e8。显然时间符合了,再进行滚动数组优化,就可以AC了。最后的空间应该是12010*2*4<64000000。不进行滚动的话,12010*2000*4>64000000。会mle,所以每次做动态规划应该考虑时间和空间限制。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值