简单01背包问题+完全背包问题

简单问题不懂的可以看我上篇博客,写了好久,个人绝对很好 动态规划从入坟走向入坑-优快云博客​​​​​​

嘿嘿,我不说这篇是我的会不会有更多的人点赞

采药

原题在这P1048 [NOIP 2005 普及组] 采药 - 洛谷

 

 简单01背包问题,套上01背包倒叙输出直接秒杀

(说是秒杀,其实刚刚学还是要理解一会)

时间和价值和我上篇博客的重量和价值是一样的

#include <iostream>
using namespace std;
const int ma = 100000;

int value[ma];//价值
int weight[ma];
int w[ma];//时间开销
int dp[ma];

int main() {
	int t, m;
	cin >> t >> m;
	for (int i = 1; i <= m; i++) {
		cin >> w[i] >> value[i];
	}
	//倒叙理解一下
	//每次遍历都会更新后面的值,因为前面的值改变了
	for (int i = 1; i <= m; i++) {
		for (int j = t; j >=w[i]; j--) {
			dp[j] = max(dp[j], dp[j - w[i]] + value[i]);
		}
	}
	cout << dp[m] << endl;
	return 0;
}

 P1616 疯狂的采药 - 洛谷

 

题解:这题不同的是,它不是01背包,而是完全背包,完全背包与01背包不同的点,在于每个物品都可以选取无限多次

因此我们只需要把01背包的循环背包改为正序即可,这样就可以选取无限次了

 有的大佬可能会说

/*if (j < w[i])dp[j] = dp[j];
   else*/

为什么这些注释完,也能写对,因为for就以后保证了不在这个if里面

关键点

  1. 当 j < w[i] 时,循环直接跳过这些 j 值,根本不会进入循环体。
  2. 因此 if (j < w[i]) 的判断在循环设计中是完全冗余的,删除后不影响逻辑。

 代码如下

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
const int ma = 10000300;

long long value[ma];//价值
long long weight[ma];
long long w[ma];//时间开销
long long dp[ma];

int main() {
	long long t, m;
	scanf("%lld%lld", &t, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%lld%lld", &w[i], &value[i]);
	}

	for (int i = 1; i <= m; i++) {
		for (int j = w[i]; j <= t; j++) {
			/*if (j < w[i])dp[j] = dp[j];
			else*/ dp[j] = max(dp[j], dp[j - w[i]] + value[i]);
		}
	}
	printf("%lld", dp[t]);
	return 0;
}

P1439 【模板】最长公共子序列 - 洛谷

 

这道题只能半对,不会写,以后再改吧(如有大佬写出来,可以发在评论区,弱鸡不会写

#define _CRT_SECURE_NO_WARNINGS 
#include<bits/stdc++.h>
using namespace std;
const int ma = 10005;

int value[ma];//价值
int weight[ma];
int w[ma];//时间开销
int dp[ma][ma];

int main() {
	int t,maxm=0,k=0;
	cin >> t;
	for (int i = 1; i <= t; i++) scanf("%d", &w[i]);
	for (int i = 1; i <= t; i++) scanf("%d", &value[i]);

	for (int i = 1; i <= t; i++) {
		for (int j = 1; j <= t; j++) {
			if (w[i] == value[j]) 
				dp[i][j] = dp[i - 1][j - 1] + 1;
			else 
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	}
	cout <<dp[t][t];
	return 0;
}

觉得好的可以点赞,主播好不骄傲,开个玩笑!!嘻嘻!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值