首页 > 其他分享 >2.16 背包学习

2.16 背包学习

时间:2023-02-16 22:34:48浏览次数:37  
标签:方案 cnt 背包 const int 学习 价值 2.16 include

11. 背包问题求方案数

思路

求最优方案数可以分成两步
第一步求出最优方案,也就是最大价值
第二部求最大价值下的方案数具体有多少种

而求出当前i,j下最大价值,然后求出相应的方案数即可一步步递推出最终结果

集合划分:
当前最大价值f[i, j]若是等于f[i - 1, j],那么相应方案一定从它转化而来,cnt += g[i - 1, j]
若是等于f[i - 1, j - v] + w,相应方案一定从它转化过来,cnt += g[i - 1, j - v]
若是两种价值相等,说明相应方案可以从这两种价值对应的方案同时转化过来也就可以两个同时加上

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

using namespace std;

const int N = 1010, mod = 1e9 + 7;
int f[N];                         //记录最大价值
int g[N];                         //记录方案数
int n, m;

int main() {
    cin >> n >> m;
    
    memset(f, -0x3f, sizeof f);
    f[0] = 0;
    //上面两行不加也可以,因为0就已经相当于没有价值,求最大值可以不用加上负无穷,但是求最小值必须赋值正无穷
    g[0] = 1;
    for (int i = 1; i <= n; i ++) {
        int v, w;
        cin >> v >> w;
        for (int j = m; j >= v; j --) {
            int maxv = max(f[j], f[j - v] + w);
            int cnt = 0;
            if (maxv == f[j]) cnt += g[j];
            if (maxv == f[j - v] + w) cnt += g[j - v];
            g[j] = cnt % mod;
            f[j] = maxv;
        }
    }
    
    int res = 0, cnt = 0;
    for (int i = 0; i <= m; i ++) res = max(res, f[i]);    //找到最优解
    for (int i = 0; i <= m; i ++) {
        if (res == f[i]) {
            cnt = (cnt + g[i]) % mod;                      //对最优解的方案数加和
        }
    }
    
    cout << cnt << endl;
    return 0;
}

\[\]

734. 能量石

思路

贪心 + dp
在dp之前,需要从题目中找到某些性质,可以使题目通过某种变化变成可以使用dp解决
本题性质为对于任意两个石头,si * li+1 < si+1 * li
然后就是01背包求最大价值
这题集合划分依据为恰好等于体积j的,所以需要赋值负无穷
因为不是最多为j的最大价值,所以需要遍历数组f,找到最大价值

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

using namespace std;

const int N = 100010, M = 110;
int f[N];

struct Stone {
    int s, e, l;
    bool operator < (const Stone &W) const {       //重载<运算符 令顺序为si * li+1 < si+1 * li
        return s * W.l < W.s * l;
    }
}stone[M];

int main() {
    int T;
    cin >> T;
    for (int H = 1; H <= T; H ++) {
        int n, m = 0;
        cin >> n;
        for (int i = 1; i <= n; i ++) {
            int s, e, l;
            cin >> s >> e >> l;
            stone[i] = {s, e, l};
            m += s;
        }
        
        sort(stone + 1, stone + 1 + n);
        memset(f, -0x3f, sizeof f);              //集合划分依据为恰好等于体积j的,所以需要赋值负无穷
        f[0] = 0;
        
        for (int i = 1; i <= n; i ++) {
            int s = stone[i].s, e = stone[i].e, l = stone[i].l;
            for (int j = m; j >= s; j --) {
                f[j] = max(f[j], f[j - s] + e - (j - s) * l);
            }
        }
        
        int res = 0;
        for (int i = 0; i <= m; i ++) res = max(res, f[i]);
        cout << "Case #" << H << ": " << res << endl;
    }
    
    return 0;
}

\[\]

6. 多重背包问题 III

思路

多重背包使用单调队列优化版

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

using namespace std;

const int N = 20010;

int n, m;
int f[N], g[N], q[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; i ++ )
    {
        int v, w, s;
        cin >> v >> w >> s;
        memcpy(g, f, sizeof f);
        for (int j = 0; j < v; j ++ )
        {
            int hh = 0, tt = -1;
            for (int k = j; k <= m; k += v)
            {
                if (hh <= tt && q[hh] < k - s * v) hh ++ ;
                while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w) tt -- ;
                q[ ++ tt] = k;
                f[k] = g[q[hh]] + (k - q[hh]) / v * w;
            }
        }
    }

    cout << f[m] << endl;

    return 0;
}

标签:方案,cnt,背包,const,int,学习,价值,2.16,include
From: https://www.cnblogs.com/lbzbk/p/17128316.html

相关文章

  • 【学习笔记】支配树
    先对自己说句话:你觉得没用的算法不一定没用,别太自以为是在那里一遍一遍叫"stoplearninguselessalgorithm",最useless的是你。支配给定一个有向图\(G\),有一个起点......
  • 多模态学习有哪些架构?MBZUAI最新《多模态表示学习》综述,29页详述多模态表示学习的演化
    前言本文回顾了深度多模态学习方法的演变,并讨论了使主干对各种下游任务具有鲁棒性所需的预训练的类型和目标。本文转载自专知 欢迎关注公众号CV技术指南,专注于计......
  • 2.16流程控制
      流程控制分支结构:分支结构就是根据条件判断的真假去执行不同分支对应的子代码注意事项: 1.根据条件的成立与否,决定是否执行if代码块 2.我们通过缩进代......
  • 传统图机器学习的特征工程
    特征工程的意义特征工程是传统图机器学习中的一个重要环节,它可以帮助我们更好地理解图中的节点、连接和全图,从而更好地构建有效的机器学习模型。特征工程可以帮助我们......
  • 数据结构刷题2023.02.16小记
    Hash函数冲突处理方式开放定址法再哈希法链地址法设置公共溢出区法不论线性表采用顺序存储结构还是链式存储结构,删除值为X的结点的时间复杂度均为O(n)。正确顺序......
  • spring security学习笔记
    1.创建springboot工程,添加lombok插件2.引入springsecurity包3.引入MybatisPuls和mysql驱动包 4.密码加密存储 5.PreAuthorize("hasAuthority('test'......
  • 【学习笔记】Spring之AOP
    Spring之AOP什么是AOPAOP(AspectOrientedProgramming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发......
  • QT基础学习 - 总结
    一、学习规划与必要知识点总结1、QT的下载与安装;1)下载:进入官网,下载QT在线下载工具(QT5.15后都必须在线下载):2)安装参考博客: a. (86条消息)Windows10在线安装Qt5.15和......
  • vue学习之-----组件递归调用
    1、关键点2、父组件<template><div><divclass="btn-title"><el-button@click="addRule(ruleDataList.id)">添加父节点</el-button>......
  • c++学习8 动态空间申请
    一动态分配内存的概述在数组一幕中,介绍过数组的长度是事先预定好的,在整个程序中固定不变。但是在实际的编程过程中,往往会发生这种情况:我们并不清楚到底需要多少数目的空......