背包问题——01背包

背包问题——01背包

01背包作为动态规划(dynamic programing)中最基础的问题,需要我们彻底理解其中的原理,为以后解决更难的动态规划问题打下良好的基础。

这里拟定一个01背包问题:
有四件不同的物品,一个体积为8的背包,将四件物品中的任意件装入背包,求背包的最大价值。(注意每件物品有且仅有一件)

为便于观察,右表中颜色分别与对应左表对应,而灰色部分会在稍后作出解释。
在这里插入图片描述
先上代码,通过代码和图片联系的方式理解01背包问题

#include<bits/stdc++.h>
using namespace std;
#define N 1010
int a[N],b[N],dp[N],n,v;

int main() {
	cin>>n>>v;
	for(int i=1; i<=n; i++) {
		cin>>a[i]>>b[i];
		for(int j=1; j<=v; j++) {
			dp[j]=0;
		}
	}
	for(int i=1; i<=n; i++) {
		for(int j=v; j>=a[i]; j--) {
			dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
		}
	}
	cout<<dp[v]<<endl;
}

代码运行的过程中dp每行更新的状态(从后往前更新,即每行由8到1遍历)
在这里插入图片描述
代码核心:状态转移方程

for(int i=1; i<=n; i++) {
		for(int j=v; j>=a[i]; j--) {
			dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
		}
	}

接下来具体描述代码的运行过程:
首先我们要明白代码是从红色标记的(1,8)开始的,而且灰色部分在每轮的 i 循环中是不会被访问的
在这里插入图片描述
原因在这里:

for(int j=v; j>=a[i]; j--)

不难看出每次的 j 循环都是从最大体积 v(8)开始的,当体积变量 j < a[ i ]时背包无法装下当前物品,相当于没有进去入新的物品的可能性,不予处理。

由于第一行只有一个体积为2价值为3的物品,所以第一行(j >= a[ 1 ])的情况下,dp[ j ]从后到前最大值一直是3。
在这里插入图片描述
在第二行的开始(j = 8 处),我们可以看到dp[ j ]提高到了7,这个7是怎么来的呢?
在这里插入图片描述
回到状态转移方程:

			dp[j]=max(dp[j],dp[j-a[i]]+b[i]);

将实时变量带入:

			dp[8]=max(dp[8],dp[8-3]+4);

而其中的dp[ 8 - 3 ]就是图中第一行的紫色块,它存的值为3,3+4=7, 7从此来,我们继续往前遍历,保证 dp 数组得到及时更新。

在经过多次 i 循环之后,在dp[ v ]即dp[ 8 ]处得到结果10。
在这里插入图片描述
以上即为一个简单01背包问题代码的大致运行过程,希望大家可以从中有所收获。加油!代码人!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值