背包问题-动态规划

 

背包问题

容量有限的背包,给很多商品,商品有相应的体积与价值

01背包问题

一个背包 每个物品只有一个

 

最终状态方程

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

推导过程

由上一层推导过来

选择拿不拿i

最终代码

#include<iostream>
#include<vector>
using namespace std;
// 1 2 3 4 5 分别代表商品编号
int bag_01(int n,int b,vector<int> &v,vector<int> &w)
{
    // b 代表bag v代表价值 w代表weight
    vector<vector<int>> dp(n+1,vector<int>(b+1));
    //int dp[v.size()+1][b+1]; // 代表选完i产品,背包有b容积 能获得的最大价值
    
    // 当i=0时
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=b;j++)
        {
            // 等于在背包容积允许的情况下给背包加了重量,同时也加入了价值
            dp[i][j]=dp[i-1][j];
            if(j>=w[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);
        }
    }
    return dp[n][b];
}

int main()
{
    // dp[i][j] i 表示第i次选择 j表示剩余的体积
    int n=0;
    cin>>n;
    vector<int> v(n+1);
    vector<int> w(n+1);
    int b=0;
    cin>>b;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i]>>v[i];
    }
    cout<<bag_01(n,b,v,w)<<endl;
}

完全背包问题

每个商品无限个

 

最终状态方程

dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+v[i])

推导过程

每个物品无限个,尝试为每个产品都尝试塞进去

for(int i=1;i<=n;i++)
{
	for(int j=0;j<=b;j++)
	{
			for(int k=0;j*w[i]<=j;k++)
			{
				dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
			}
	}
}

可以转化为2维,[i][j]中与[i][j-w[i]] 有很相似的部分

[i][j]=max([i-1][j],[i-1][j-w]+v,[i-1][j-2w]+2v,[i-1][j-3w]+3v....)
[i][j-w]=max([i-1][j-w],[i-1][j-2w]+v,[i-1][j-3w]+2v....). 
[i][j]=max([i-1][j],[i][j-w]+v)

最终代码

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int whole_bag(int n,int b,vector<int> &v,vector<int> &w)
{
    //cout<<"进入"<<endl;
    vector<vector<int> > dp(n+1,vector<int>(b+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=b;j++)
        {
            dp[i][j]=dp[i-1][j];
            if(j>=w[i])
            {
                dp[i][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
            }
        }
    }
    return dp[n][b];
}
int main()
{
    int n=0;
    cin>>n;
    vector<int> v(n+1);
    vector<int> w(n+1);
    int b=0;
    cin>>b;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i]>>v[i];
    }
    cout<<whole_bag(n,b,v,w)<<endl;
}

多重背包问题

每个物品数量不一样

 

推导过程

朴素解法,给k的数目加上一个限制

for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=b;j++)
        {
            for(int k=0;k*w[i]<=j&&k<=s[i];k++)
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
            }
        }
    }

看能否采用完全背包的优化方法呢?

[i][j]=max([i-1][j],[i-1][j-w]+v,[i-1][j-2w]+2v,[i-1][j-3w]+3v+...+[i-1][j-sw]+sw)
[i][j-w]=max([i-1][j-w],[i-1][j-2w]+v,[i-1][j-3w]+2v....+[i-1][j-sw]+(s-1)w+[i-1][j-(s+1)w]+sw). 
会发现[i][j-w] 多了一项,这就无法用max

采用二进制方法优化,将 多重背包问题 转化成 01背包问题

如一个商品有100个

1 个 作为一个商品

2 个 作为一个商品

4 个 作为一个商品

8 个 作为一个商品

.. 最后一个商品用剩余的数目当成整体商品

512 个 作为一个商品

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int bag_01(int n,int b,vector<int>&w,vector<int>&v)
{
    vector<vector<int> > dp(n+1,vector<int>(b+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=b;j++)
        {
            dp[i][j]=dp[i-1][j];
            if(j>=w[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);
        }
    }
    return dp[n][b];
}

int main()
{
    int n_fake=0;
    cin>>n_fake;
    int b=0;
    cin>>b;
    int n=0;
    vector<int> v;
    vector<int> w;
    v.push_back(-1);
    w.push_back(-1);
    for(int i=1;i<=n_fake;i++)
    {
        int l1,l2,l3;
        // l1 是 体积
        // l2 是 价值
        // l3 是 个数
        cin>>l1>>l2>>l3;
        int k=1;
        while(k>=l3)
        {
            l3-=k;
            v.push_back(l2*k);
            w.push_back(l1*k);
            n+=1;
            k*=2;
        }
        if(l3!=0)
        {
            v.push_back(l2*k);
            w.push_back(l1*k);
        }
    }
    cout<<bag_01(n,b,w,v)<<endl;

}

分组背包问题

 

物品有n组,每组物品有若干个,每组最多选一个

分组背包问题

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i,k]]+v[i,k])

选择第k个商品

类似多重背包问题的朴素写法,非常符合逻辑


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int group_bag(int n,int b,vector<vector<int> >& w,vector<vector<int> >& v)
{
    vector<vector<int> > dp(n+1, vector<int>(b+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=b;j++)
        {
            dp[i][j]=dp[i][j-1];
            for(int l=0;l<v[i].size();l++)
            {
                if(w[i][l]<=j) dp[i][j]=max(dp[i][j],dp[i-1][j-w[i][l]]+v[i][l]);
            }
        }
    }
    return dp[n][b];
}
int main()
{
    vector<vector<int> > w;
    vector<vector<int> > v;
    int n=0;
    int b=0;
    cin>>n>>b;
    w.push_back(vector<int>(1));
    v.push_back(vector<int>(1));
    for(int i=1;i<=n;i++)
    {
        int n1=0;
        cin>>n1;
        vector<int> v1(n1);
        vector<int> w1(n1);
        for(int j=0;j<n1;j++)
        {
            int a=0;
            int b=0;
            cin>>a>>b;
            w1.push_back(a);
            v1.push_back(b);
        }
        w.push_back(w1);
        v.push_back(v1);
    }
    cout<<group_bag(n,b,w,v)<<endl;
}

欢迎大家 star ✨ GitHub - stolendance/acwing

正在更新算法模板   写上去就能用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/9843.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前段时间面了10多个人,发现这些测试人都有个通病......

前段时间面了15个人&#xff0c;怎么说呢&#xff0c;基本上没有符合要求的&#xff0c;其实一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。 看简历很多都是3年工作经验&am…

GitHub标星15w,如何用Python实现所有算法?

学会了 Python 基础知识&#xff0c;想进阶一下&#xff0c;那就来点算法吧&#xff01;毕竟编程语言只是工具&#xff0c;结构算法才是灵魂。 新手如何入门 Python 算法&#xff1f; 几位印度小哥在 GitHub 上建了一个各种 Python 算法的新手入门大全。从原理到代码&#xf…

数据 数据元素 数据项 数据对象

文章目录数据、数据元素、数据项和数据对象数据数据元素数据对象数据元素和数据对象数据结构数据结构包括以下三个方面的内容逻辑结构物理结构&#xff08;存储结构&#xff09;逻辑结构与存储结构的关系逻辑结构的种类集合结构线性结构树型结构图状结构或网状结构四种基本的存…

webgl-根据鼠标点击而移动

html <!DOCTYPE html> <head> <style> *{ margin: 0px; padding: 0px; } </style> </head> <body> <canvas id webgl> 您的浏览器不支持HTML5,请更换浏览器 </canvas> <script src"./main.js"></script&g…

【NAS群晖drive异地访问】远程连接drive挂载电脑硬盘「内网穿透」

文章目录前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用3. 结语转发自CSDN远程穿透的文章&#xff1a;【群晖…

[C语言]string.h常用字符串库函数详解+模拟实现

目录 字符串函数 strlen strcpy strcat strcmp strstr 内存函数 memcpy memmove 人生百态&#xff0c;苦事之多。烦恼穿心&#xff0c;何来解脱&#xff1f;打开博客&#xff0c;吸取干货。 以码消愁&#xff0c;以串解忧。泱泱年轮&#xff0c;唯有生活。一起撸串&a…

〖Python网络爬虫实战⑩〗- 正则表达式实战(一)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付费…

2023 年男生还推荐报计算机专业吗?

计算机专业确实是一个非常热门的专业&#xff0c;就业前景也很广阔。 但是&#xff0c;近些年随着各个大学对计算机专业及其相关专业疯狂扩招&#xff0c;而且每年的毕业人口都在增多&#xff0c;行业是根本容纳不下的&#xff0c;就业竞争力度也急剧上升。因此&#xff0c;选…

Mac平台上有哪些好用的常用软件?

我大概分几类给你介绍一下吧。 一、办公类 1.微软的office系列&#xff0c;在mac平台也有office的全家桶&#xff0c;习惯用微软office的也可以安装。 2.wps office&#xff0c;wps可以说是国产最好用的office软件&#xff0c;最重要的是wps可以跨平台&#xff0c;并且云文档…

IT审计黄金标准“CISA”备考经验分享-529分成功上岸

激动的心&#xff0c;先晒下成绩单 考证建议以及职业规划 对于IT人士来说证书是一个非常有效的敲门砖&#xff0c;尤其是想跨到新的领域&#xff0c;一个证书往往能给自己在面试官留下一个深刻的印象&#xff0c;尤其是一些在专业领域含金量很高的证书。作为一个14年的IT人士&…

81-82-83-84-85-86 - 文件系统设计与实现

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;深入浅出操作系统 - 目录 文章目录1. 问题1.1 硬盘上最最最简单的文件系统支持方式1.2 改进思路1.3 更多细节问题1.4 文件系统概要设计1.5 硬盘数据逻辑示意图1.6 硬盘数据物理组…

​2023年十大目标检测模型!

“目标检测是计算机视觉中最令人兴奋和具有挑战性的问题之一&#xff0c;深度学习已经成为解决该问题的强大工具。”—Dr. Liang-Chieh Chen目标检测是计算机视觉中的基础任务&#xff0c;它涉及在图像中识别和定位目标。深度学习已经革新了目标检测&#xff0c;使得在图像和视…

微服务架构-服务网关(Gateway)-路由功能详解

路由功能详解 这一节我们看一看Gateway中的路由是怎么工作的&#xff1b;GateWay网关的路由功能可不是简简单单的 “转发" 请求&#xff0c;在请求到达网关要流转到指定服务之间发生了很多事儿&#xff0c;它不光可以拒绝请求&#xff0c;甚至可以"篡改” 请求的参数…

Java 在线编程编译工具上线,直接运行Java代码

前言 大家好&#xff0c;我是小哈~ 周末没出去浪&#xff0c;花了点时间&#xff0c;在我的个人网站上线了一款小工具。啥工具呢&#xff1f;一款可以在线编译 Java 代码并运行输出结果的小工具。 大家都知道&#xff0c;甲骨文刷 Java 版本号非常积极&#xff0c;这不上个月…

web综合

一&#xff0c;基于域名访问www.openlab.com 在文件当中写入IP与域名的映射关系 在windows中写入 也可以在客户端的/etc/hosts下写入映射关系 创建目录 [rootserver ~]# mkdir -pv /www/openlab 将所需要的内容写入对应目录当中 [rootserver ~]# echo welcome to openlab ! &…

大一被忽悠进了培训班

大家好&#xff0c;我是帅地。 最近我的知识星球开始营业&#xff0c;不少大一大二的小伙伴也是纷纷加入了星球&#xff0c;并且咨询的问题也是五花八门&#xff0c;反正就是&#xff0c;各种迷茫&#xff0c;其中有一个学弟&#xff0c;才大一&#xff0c;就报考培训班&#…

2023/4/6总结

题解 Problem - A - Codeforces 1.这道题很简单&#xff0c;找出将当前数字放入字符串的最大值。 2.分情况讨论&#xff0c;有俩种情况&#xff0c;一种是大于等于数字d&#xff0c;那么这个数字d需要插入到最后字符串的位置。否则这个数字需要插入到第一次比它小的位置。 …

2023年4月的编程语言排行榜,有你中意的开发语言吗?

编程世界变幻莫测&#xff0c;编程语言也是层出不穷&#xff0c;每隔一段时间就有新的风口出现。2023年的风口非人工智能莫属&#xff0c;人工智能领域中不可获取的编程语言就是Python&#xff0c;作为在算法、数据方面有独特优势的编程语言&#xff0c;从去年开始就展现了它不…

算法学习|动态规划 LeetCode 392.判断子序列 、115.不同的子序列

动态规划一、判断子序列思路实现代码二、不同的子序列思路实现代码(还是蛮开心的&#xff09; 一、判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相…

腾讯云8核16G18M轻量服务器CPU带宽流量性能测评

腾讯云轻量应用服务器8核16G18M带宽&#xff0c;18M公网带宽下载速度峰值可达2304KB/秒&#xff0c;相当于2.25M/s&#xff0c;系统盘为270GB SSD盘&#xff0c;3500GB月流量&#xff0c;折合每天116GB流量。腾讯云百科分享腾讯云轻量服务器8核16G18M配置、CPU型号、公网带宽月…
最新文章