简单背包dp新手易懂

背包 DP - OI Wiki

如果看不懂不妨看看下面的

[NOIP2005 普及组] 采药 - 洛谷

#include<bits/stdc++.h>
using namespace std;
int w[105] = { 0 }, va[105] = { 0 }, f[1005] = {0};
int main() {
	int t, n;
	cin >> t >> n;
	for (int i = 1; i <= n; i++) 
		cin >> w[i]>>va[i];
	for (int i = 1; i <= n; i++)//从第一件物品开始转移
		for (int j= t;j>=w[i];j--)
			f[j] = max(f[j],f[j-w[i]]+va[i]);
	cout << f[t];
	return 0;
}

如何理解

for (int i = 1; i <= n; i++)//从第一件物品开始转移
		for (int j= t;j>=w[i];j--)
			f[j] = max(f[j],f[j-w[i]]+va[i]);

f [ i ] 为在 i 时刻你采了多少价值的药,假设你有6秒时间采药,一开始你看着药草傻站着,什么都没采,所以在第0,1,2,3,4,5,6秒你采的药的价值都为0,假设你采了第一个药,第一个药草价值为2,花时为3,在第0秒采的话, 那你就用你在第0秒采的药的价值加上假设采了第一个药的价格来更新在第三秒采的药的价格很明显第0所采的药的价格为0f[3]=max(f[0]+3,f[3])=3,如果你 是从前往后更新 就会在f[6]时,f[6]=max(f[6],f[3]+3), 就是你用第三秒采药的价格来更新第六秒所采药草的价格,而这是在 第一个药草这里,即第一轮更新,这样导致你第三秒采了一个然后接着第三秒又花了三秒来采第一个药草,就是重复采药,不符合题意,但这是完全背包的写法

后来你又采第二个药价值为3,花时为1,为了从前往后更新,那你就先用你在第3秒采的药的价值加上假设采了第二个药的价格来更新在第4秒采的药的价格f[4]=max(f[3]+3,f[4])=6

然后假设后面你发现有两个草第三个药草价值为2,花时为4,第4个药草价值为5,花时为2

在第三轮首先第6秒会被第四秒的价格更新f[6]=max(f[4]+4,f[6])=10

第5秒会被第3秒的价格更新f[5]=max(f[3]+4,f[5])=7

第2秒会被第0秒的价格更新f[2]=max(f[0]+4,f[2])=4

在第三轮首先第6秒会被第四秒的价格更新f[6]=max(f[4]+5,f[6])=11

第5秒会被第3秒的价格更新f[5]=max(f[3]+4,f[5])=8

第2秒会被第0秒的价格更新f[2]=max(f[0]+4,f[2])=5

然后最大值就是11

完全背包就不讲了,就是对任意一个物品,可以无限取,就是更新变成了从前往后

for (int i = 1; i <= n; i++)//从第一件物品开始转移
		for (int j= 0;j<=t;j++)
			f[j] = max(f[j],f[j-w[i]]+va[i]);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值