Pixiv - KiraraShss
539 字
3 分钟
背包问题
01背包
题目描述

输入样例
4 51 22 43 44 5输出样例:
8分析

第一版
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;int v[N], w[N];
int f[N][N];
int main(){ cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) { f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i-1][j - v[i]] + w[i]); }
cout << f[n][m] << endl;
return 0;}但是由于f[i][j]的状态转移方程都是由[i-1]层决定,所以第一维实际上可以省略。但是省略之后需要将j倒过来遍历,因为没有降维之前状态转移方程为:
我们需要使用到前一层的,所以要保证此时的仍然是上一层计算出来的值,而不是,又因为小于,所以只能倒序才能让在之后更新。
第二版
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;int v[N], w[N];
int f[N];
int main(){ cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i ++ ) for (int j = m; j >= v[i]; j -- ) f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl;
return 0;}完全背包

输入样例
4 51 22 43 44 5输出样例:
10分析
由于物品可以选无数个,所以我们可以从~个不断尝试,找到最大的价值。
可以写出状态转移方程:
我们还观察到:
所以
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;int v[N], w[N];int f[N];
int main(){ cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = 1; i <= n; i ++ ) for (int j = v[i]; j <= m; j ++ ) f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl; return 0;}多重背包
基础
数据范围小,普通DP即可
分组背包
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
最后更新于 2025-04-27,距今已过 362 天
部分内容可能已过时
printsdf's Blog