首页 > 其他分享 >多重背包例题:庆功会

多重背包例题:庆功会

时间:2022-10-28 21:35:20浏览次数:66  
标签:多重 cnt 例题 int 背包 include 优化 庆功会

多重背包例题:庆功会

朴素版,二进制优化,单调队列优化三种写法。

原题链接:https://www.acwing.com/problem/content/1021/

补充

我的二进制优化博客

彩色铅笔大佬的多重背包III(单调队列优化)博客

dp思路

多重背包dp

dp 
状态表示
    集合:f[i][j]表示从前i种物品中选,价格不超过j的所有方案的集合
    属性:max 最大价值
状态转移
    [0,1,2,...,s[i]]
    
    0 <= k <= s[i]
    f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i])

代码

普通多重背包

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 510,M = 6010;
int v[N],w[N],s[N];
int n,m;
int f[N][M];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i ++) cin >> v[i] >> w[i] >> s[i];
    
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 1; j <= m;j ++)
        {
            for(int k = 0; k * v[i] <= j && k <= s[i]; k ++) // 这里k*v[i] <= j && k<=s[i]两个条件容易写出错
                f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
        }
    }
    cout << f[n][m];
    
    return 0;
}

二进制优化多重背包

#include<iostream>
#include<algorithm>
using namespace std;
const int M = 60100;
int v[M],w[M],cnt;
int n,m;
int f[M];

int main()
{
    scanf("%d%d",&n,&m);
    
    for(int i = 1;i <= n;i ++)
    {
        int a,b,s; // 物品体积 价值 数量
        scanf("%d%d%d",&a,&b,&s);
        // 将这s个物品拆开成logs组(二进制优化法):1 2 4 8 16... ...
        int k = 1;
        while(k < s)
        {
            cnt ++;
            v[cnt] = k * a;
            w[cnt] = k * b;
            s -= k; // 记得从s中减去k
            k *= 2;
        }
        if(s > 0)
        {
            cnt ++;
            v[cnt] = s * a;
            w[cnt] = s * b;
        }
    }
    
    n = cnt; // 其实物品数量变成了cnt个
    // 01背包
    for(int i = 1;i <= n;i ++)
    {
        for(int j = m; j >= v[i]; j --)
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }
    
    cout << f[m];
    
    return 0;
}

单调队列优化多重背包

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510,M = 6010;

int v[N],w[N],s[N];
int f[M],g[M];
int q[M]; // 队列长度一定要开成体积大小(j的范围此题中是价格的范围)
int n,m;

int main()
{
    scanf("%d%d",&n,&m);
    
    for(int i = 1;i <= n;i ++) cin >> v[i] >> w[i] >> s[i];
    

    for(int i = 1;i <= n;i ++)
    {
        memcpy(g,f,sizeof g);
        for(int r = 0; r < v[i]; r ++)
        {
            int head = 0,tail = -1;
            for(int j = r; j <= m;j += v[i])
            {
                // 判断队头是否滑出
                if(head <= tail && q[head] < j-s[i]*v[i]) head ++;
                // 保证模拟队列递减(队头为最大值)
                while(head <= tail && g[q[tail]]+(j-q[tail])/v[i]*w[i] <= g[j]) tail --;
                q[++ tail] = j;
                f[j] = max(f[j],g[q[head]] + (j-q[head])/v[i]*w[i]);
            }
        }
    }
    printf("%d",f[m]);
    return 0;
}

标签:多重,cnt,例题,int,背包,include,优化,庆功会
From: https://www.cnblogs.com/rdisheng/p/16837561.html

相关文章

  • A*算法 详解与例题
    ......
  • 完全背包问题 —— 贪心优化 DP 范围
    题意:现在有\(2n+1\)个物品(\(n\le300\)),体积分别为\(-n,-n+1,\dots,-1,0,1,\dots,n\),第\(i\)个物品有\(a_i\)个,求选出恰好\(S\)的总体积最多能选几个物品。第一......
  • ac 5 多种背包问题
    输入是45123241343452实际上把他边成45121241241341681451451全部是一就变成01背包问题了#include<bits/stdc++.h>usingname......
  • ac 3完全背包问题
    #include<bits/stdc++.h>usingnamespacestd;constintN=1010;intn,m;intv[N],w[N];intf[N];intmain(){cin>>n>>m;for(inti=1;i<=......
  • 完全背包:数组组合,买书
    数字组合原题链接:https://www.acwing.com/problem/content/280/思路可以看出是一个完全背包,下面来分析完全背包dp状态表示集合:f[i][j]表示从前i个选,数字总和为j的方......
  • DP--背包问题
    小明同学在参加一场考试,考试时间2个小时。试卷上一共有n道题目,小明要在规定时间内,完成一定数量的题目。  考试中不限制试题作答顺序,对于 i 第道题目,小明有三种不同的策......
  • 0-1背包判断物品能否组合问题
    题目描述小米之家是成人糖果店。里面有很多便宜,好用,好玩的产品。中秋节快到了,小米之家想给米粉们准备一些固定金额大礼包。对于给定的一个金额,需要判断能不能用不同种产品(一......
  • 多重背包III
    多重背包III(单调队列优化)原题链接:https://www.acwing.com/problem/content/6/回忆一下完全背包优化多重背包III思路彩色铅笔大佬的题解补充:代码二维#include<......
  • 【算法学习】完全背包问题公式记录
    朴素f[i][j]=max(f[i-1][j],f[i-1][j-v]+w,f[i-1][j-2v]+2w,...)f[i][j-v]=max(f[i-1][j-v],f[i-1][j-2v]+w,...)=>f[i][j]=max......
  • 背包问题的倒序枚举与正序枚举
    这可能是困扰很多人很长时间的问题吧。先把各个变量列出来体积为的背包,有个物品,每个物品的体积为,价值为,每个物品装一次,求最大价值来这看的肯定都是学习过基础背包的人,如果没......