简单问题不懂的可以看我上篇博客,写了好久,个人绝对很好 动态规划从入坟走向入坑-优快云博客
嘿嘿,我不说这篇是我的会不会有更多的人点赞
采药
原题在这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里面
关键点:
- 当
j < w[i]
时,循环直接跳过这些j
值,根本不会进入循环体。 - 因此
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;
}
这道题只能半对,不会写,以后再改吧(如有大佬写出来,可以发在评论区,弱鸡不会写
#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;
}
觉得好的可以点赞,主播好不骄傲,开个玩笑!!嘻嘻!