0-1背包问题(动态规划:详细解析过程、源码-java+C语言)

0-1背包问题(动态规划:详细解析过程、源码-java+C语言)


学习使用动态规划解决0-1背包问题,体会动态规划算法自底向上的计算过程。

问题描述

给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?(与完全背包问题的区别在于:完全背包问题的物品是可部分装入,但是0-1背包问题的物品是不能部分装入的)
其数学表达如下:
背包问题表达式
xi表示第i的物品的选中情况,当xi=1时,该物品被选中,vixi=物品的重量;当xi=0时,表示物品未选中,vixi=0;

最优子结构性质

在这里插入图片描述
在这里插入图片描述

递归关系的分析

在这里插入图片描述
在这里插入图片描述

状态转移方程的创建

根据上面的递归关系可以创建如下的状态转移方程:

1. m[i][0]=00=<i<=n (n是物品的数量,背包的容量是零,不能装入任何物品,总价值为零)   边界条件
2. m[0][j]=0,0=<j<=c(w是背包的容量,当前没有物品可装入,总价值为零)     边界条件 
3. m[i][j]=m[i-1][j]  当j<w[i]时,物品放不下
4. m[i][j]=MAX{
   m[i-1][j],m[i-1][j-w[i]+v[i]} 物品可以放得下的情况,要比较不包含当前物品背包的总价值和包含当前物品的背包的总价值的大小。
计算包含当前物品的背包总价值的方式:m[当前的物品编号-1][当前背包的容量-当前物品的重量]定位到不包含当前物品的的背包剩余容量的最大价值,最后再加上当前物品的价值。

可以通过以下表格理解该状态方程:
理解状态转移方程
通过表格可以得出计算顺序是:

1.边界值赋值
2.比较j和w[i]
3.比较m[i-1][j]和m[i-1][j-w[i]+v[i]的大小

算法代码

1.c语言代码

int x[4];
//动态规划法求解0-1背包问题,n表示物品的数量,c表示背包的容量
int knapsack(int n, int c) {
   
	//边界值赋值
	for (int i = 0; i < n + 1; i++)
		for (int j = 0; j < c + 1; j++)  m[i][j] = 0;
	//从1开始,注意边界条件
	for (int i = 1; i < n + 1; i++) {
   
		for (int j = 1; j < c + 1; j++) {
   
			//因为物品的编号是从1开始的,但是在数组中1号物品的重量存放在w[0]中,所以在表示重量时i要减去1
			if (j <= w[i-1]) {
   
				m[i][j] = m[i - 1][j];
			}
			else
			{
   
				//因为物品的编号是从1开始的,但是在数组中1号物品的价值存放在w[0]中,所以在表示价值时i要减去1
				int t = m[i - 1][j - w[i-1]] + v[i-1];
				if (m[i - 1][j] > t) {
   
					m[i][j] = m[i - 1][j];
				}
				else
				{
   
					m[i][j] 
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值