算法学习17-动态规划01:背包问题

这篇具有很好参考价值的文章主要介绍了算法学习17-动态规划01:背包问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

算法学习17:背包问题(动态规划)



前言

动态规划 背包问题,算法学习,算法,学习,动态规划,笔记


提示:以下是本篇文章正文内容:

一、01背包问题:


1.朴素版:(二维)

动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



// 例题:有n件物品,和一个容量是m的背包,每件物品只能使用一次。
// 第i件物品的体积是vi,价值是wi,
// 求将哪些物品装入背包,可以使总价值最大。
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];// v:体积, w:价值
int f[N][N];// 从前i件物品中取,放到容量为j的背包中,最大的价值。 

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
	
	for(int i = 1; i <= n; i ++)
		for(int j = 0; j <= m; j ++)
		{
			f[i][j] = f[i - 1][j];// 不取 
			if(j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);// 取 
		}
		
	cout << f[n][m] << endl;
	return 0;
 } 


动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



2.优化版:(一维)

// 优化版:
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];// v:体积, w:价值 
int f[N];// 从i件物品中去,放到容量为j的背包,最大的价值。
// 注意要执行i轮循环 

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
	
	for(int i = 1; i <= n; i ++)
		// 注意1:如果这里不是倒着遍历,那么可能存在,在前面的时候,i物品已经被放进背包了 
		// 从大到小,保证前面的“状态”,还没有更新过。 
		for(int j = m; j >= v[i]; j --)
			// 不取 和 取 
			f[j] = max(f[j], f[j - v[i]] + w[i]);
		
	cout << f[m] << endl;
	return 0;
 } 


二、完全背包

1.朴素版:(3重for)



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



// 例题:有n种物品,容量为m的背包,“每种物品都有无限件可用”。
// 第i件物品的体积是vi,价值是wi,
// 求将哪些物品装入背包,可以使总价值最大,输出最大价值。
#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N][N];

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
	
	// 3重for循环: 
	for(int i = 1; i <= n; i ++) 
		for(int j = 0; j <= m; j ++)
			for(int k = 0; k * v[i] <= j; k ++)
			 f[i][j] = max(f[i][j], f[i - 1][j - v[i] * k] + w[i] * k);
			 
	cout << f[n][m] << endl;
	return 0;
}


动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



2.稍微优化版:(二维)

动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N][N];

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];

	for(int i = 1; i <= n; i ++) 
		for(int j = 0; j <= m; j ++)
			{
			// 这样就和01背包问题有点像了 
			// 不同的是:f[i - 1][j - v[i]] + w[i] 
			f[i][j] = f[i - 1][j]; 
			// 注意1:要加一个判断条件 (否者越界) 
		 	if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
			}
		
			 
	cout << f[n][m] << endl;
	return 0;
}


3.完全背包问题模版:(最终优化版)

#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N];

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];

	for(int i = 1; i <= n; i ++) 
		// 为什么是从前往后遍历,因为每件物品可以使用无限次,不存在重复问题 
		for(int j = v[i]; j <= m; j ++)
		 	f[j] = max(f[j], f[j - v[i]] + w[i]);
		
	cout << f[m]<< endl;
	return 0;
}

三、多重背包

1.朴素版:()



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



2.多重背包问题的“二进制优化”:

动态规划 背包问题,算法学习,算法,学习,动态规划,笔记



/*
多重背包问题的“二进制优化”: 
请先记住:二进制数的组合可以表示一个0~s范围内的十进制数
那么我们将总数量为s的一个“大包裹”转换为“1 2 4 8 16 32 64 .......”这样的小包裹

然后对于:这些小包裹,我们选择“取或者不取”,这样就把“多重背包问题”转换为“01背包问题” 
*/
/*
注意:为什么要优化?
第一种也可以使用,但是当数据范围大的时候就是出现Time Limit Exceed问题。
(1)0< n, m <100   0< vi, wi, si <100
(2)0 < n <1000 0 < m < 2000 0 < vi, wi, si <2000
const int N = 25000 是如何得到的?1000 * log2(2000) = 1000 * 11 = 22000
*/
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 25000, M = 2010;

int n, m;
int v[N], w[N];
int f[N];

int main()
{
	cin >> n >> m;
	int cnt = 0;// 标记 :作为打包后的总数量 
	for(int i = 1; i <= n; i ++)
	{
		int a, b, s;// 体积,容量,数量 
		cin >> a >> b >> s;
		int k = 1;
		while(k <= s)
		{
			cnt ++;
			v[cnt] = a * k;// 打包后的体积 
			w[cnt] = b * k;// 打包后的容量 
			s -= k;// 剩余的总数量 
			k *= 2;// 打包的件数 
		}
		if(s > 0)// 多了 
		{
			cnt ++;
			v[cnt] = a * s;
			w[cnt] = b * s;
		}
	}
	
	n = 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] << endl;	
	return 0;
 } 


四、分组背包



动态规划 背包问题,算法学习,算法,学习,动态规划,笔记

动态规划 背包问题,算法学习,算法,学习,动态规划,笔记

// 有n组物品,容量为m的背包,
// 每组物品有若干个,同一组内的物品最多只能选一个
// 每件物品的体积是vij,价值是wij,其中i是组号,j是组内编号
// 求将哪些物品装入背包,可以使总价值最大,输出最大价值。

/*
输入:n,m
接下来n组数据:
第一行:s表示这一组物品的数量
接下来s行:v,w 
*/

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m;
int v[N][N], w[N][N], s[N];
int f[N]; 

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)
	{
		cin >> s[i];
		for(int j = 0; j <s[i]; j ++)
			cin >> v[i][j] >> w[i][j];
	}
	
	for(int i = 1; i <= n; i ++)
		// 像01背包:“取或不取”,只有一件,不可以重复,那么就倒着遍历,保证前面是未更新的 
		for(int j = m; j >= 0; j --)
			for(int k = 0; k < s[i]; k ++)
				if(v[i][k] <= j)
					f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
					
	cout << f[m] << endl;
	return 0;
 } 


动态规划 背包问题,算法学习,算法,学习,动态规划,笔记

总结

提示:这里对文章进行总结:
💕💕💕文章来源地址https://www.toymoban.com/news/detail-859676.html

到了这里,关于算法学习17-动态规划01:背包问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法分析与设计——动态规划求解01背包问题

    假设有四个物品,如下图,背包总容量为8,求背包装入哪些物品时累计的价值最多。 我们使用动态规划来解决这个问题,首先使用一个表格来模拟整个算法的过程。 表格中的信息表示 指定情况下能产生的最大价值 。例如, (4, 8)表示在背包容量为8的情况下,前四个物品的最

    2024年02月04日
    浏览(70)
  • 算法套路十四——动态规划之背包问题:01背包、完全背包及各种变形

    如果对递归、记忆化搜索及动态规划的概念与关系不太理解,可以前往阅读算法套路十三——动态规划DP入门 背包DP介绍:https://oi-wiki.org/dp/knapsack/ 0-1背包:有n个物品,第i个物品的体积为w[i],价值为v[i],每个物品至多选一个, 求体积和不超过capacity时的最大价值和,其中i从

    2024年02月10日
    浏览(60)
  • C++算法初级11——01背包问题(动态规划2)

    辰辰采药 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时

    2024年02月02日
    浏览(50)
  • 动态规划01背包问题-代码随想录-刷题笔记

    有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大。 二维dp数组01背包 确定dp数组以及下标的含义 是使用二维数组,即 dp[i][j] 表示从下标为[0-i]的物品里任意取,

    2024年02月07日
    浏览(58)
  • 【算法日志】动态规划刷题:01背包问题,多重背包问题(day37,day38)

    目录 前言 目标和(01背包) 一和零(01背包) 零钱兑换(多重背包) 排列总和(多重背包) 这两天都是背包问题,其中的01背包的一些应用问题需要一定的数学建模能力,需要i将实际问题简化成我们熟悉的背包问题;而这两天的多重背包问题还算比较基础,但也要我明白了

    2024年02月11日
    浏览(56)
  • 【算法|动态规划 | 01背包问题No.2】AcWing 423. 采药

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【AcWing算法提高学习专栏】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成

    2024年02月06日
    浏览(50)
  • 算法设计与分析实验二:动态规划法求解TSP问题和01背包问题

    【实验内容】 (1)tsp问题:利用动态规划算法编程求解TSP问题,并进行时间复杂性分析。 输入:n个城市,权值,任选一个城市出发; 输出:以表格形式输出结果,并给出向量解和最短路径长度。 (2)01背包问题:利用动态规划算法编程求解0-1背包问题,并进行时间复杂性分

    2024年02月03日
    浏览(58)
  • 力扣算法刷题Day42|动态规划:01背包问题 分割等和子集

    力扣题目:01背包问题(二维数组) 刷题时长:参考题解 解题方法:动态规划 + 二维dp数组 复杂度分析 时间 空间 问题总结 理解递推公式困难 本题收获 动规思路:两层for循环,第一层i遍历物品,第二层j枚举背包容量以内所有值 确定dp数组及下标的含义:dp[i][j] 表示从下标

    2024年02月13日
    浏览(62)
  • 算法基础复盘笔记Day09【动态规划】—— 背包问题

    ❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于 Java后端开发 ,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得 关注 、 点赞 、 收藏 、 评论 ⭐️⭐️⭐️ 📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉 1. 题目

    2023年04月22日
    浏览(51)
  • Acwing-基础算法课笔记之动态规划(背包问题)

    01背包中的0和1指的是放与不放,而且不能出现放多个的情况,背包只能放相同物品中的一个; 首先是对 d [ i ] [ j ] d[i][j] d [ i ] [ j ] 数组的解释,该数组表示的是只看前 i i i 个物品,总体积是 j j j 的情况下,总价值最大是多少; 不选第 i i i 个物品,只考虑前 i − 1 i-1 i −

    2024年04月17日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包