第一周分享题(混合背包)

原题链接
一道混合背包模板题,题目如下
第一周分享题(混合背包)_第1张图片
题解:
将多重背包采取二进制优化,将三类背包问题分为只有01背包和完全背包,[目的:将时间复杂度从O(NVS)优化到O(NVlogS)] 然后判断背包类型采取不同dp方式
时间复杂度:O(NVlogS)
参考代码如下(有注释)

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;i
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i
const ll mod=1e9+7;

bool shushu(int x)
{
    int flag=0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            flag=1;
            break;
        }
    }
    if(flag)
        return false;
    else
        return true;
}
int gcd(int x,int y)
{
    int t;
    while(y%x!=0)
    {
        t=y%x;
        y=x;
        x=t;
    }
    return x;
}
int lcm(int x,int y)
{
    return x/gcd(x,y)*y;
}
ll q_pow(ll a,ll b,int m)//
{
    ll r=1,base=a;
    while(b!=0){
        if(b%2)
          r*=base;
        r%=m;
        base*=base;
        base%=m;
        b/=2;
    }
    return r;
}


const int maxn=1e4+5;
int n,m,dp[maxn],w[maxn],v[maxn],s[maxn];

int main()
{
    cin>>n>>m;//物品种数和背包容积
    int ant=0;//优化后的物品种类数
    int x,y,z;
    for(int i=1;i<=n;i++)
    {
        cin>>x>>y>>z;
        if(z>1)//多重背包
        {
            //二进制优化
            for(int j=1;j<=z;j*=2)
            {
                w[++ant]=j*x;
                v[ant]=j*y;
                s[ant]=1;
                z-=j;
            }
            if(z>0)
            {
                w[++ant]=z*x;
                v[ant]=z*y;
                s[ant]=1;
            }
        }
         else// 01背包和完全背包  不做处理
        {
            w[++ant]=x;
            v[ant]=y;
            s[ant]=z;
        }   
    }
    for(int i=1;i<=ant;i++)
    {
        if(s[i]==0)//完全背包
        {
            for(int j=w[i];j<=m;j++)
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        }
        else//01背包
        {
            for(int j=m;j>=w[i];j--)
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    cout<<dp[m]<<endl;
    return 0;
}


你可能感兴趣的:(背包问题)