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

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

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;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<n;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;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值