编辑
2023-10-27
算法题
00
请注意,本文编写于 561 天前,最后修改于 559 天前,其中某些信息可能已经过时。

背包问题

image.png

image.png

01背包

特点:每个物品仅能使用一次

重要变量&公式解释

f[i][j]:表示所有选法集合中,只从前i个物品中选,并且总体积≤≤j的选法的集合,它的值是这个集合中每一个选法的最大值.

状态转移方程

f[i][j] = max(f[i-1][j], f[i-1][j-v[i]]+w[i])

f[i-1][j]: 不选第i个物品的集合中的最大值

f[i-1][j-v[i]]+w[i]: 选第i个物品的集合,但是直接求不容易求所在集合的属性,这里迂回打击一下,先将第i个物品的体积减去,求剩下集合中选法的最大值.

cpp
#include<bits/stdc++.h> using namespace std; const int MAXN = 1005; int v[MAXN]; // 体积 int w[MAXN]; // 价值 int f[MAXN][MAXN]; // f[i][j], j体积下前i个物品的最大价值 int main() { int n, m; 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++) { // 当前背包容量装不进第i个物品,则价值等于前i-1个物品 if(j < v[i]) f[i][j] = f[i - 1][j]; // 能装,需进行决策是否选择第i个物品 else f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]); } cout << f[n][m] << endl; return 0; } // 滚动优化#include<bits/stdc++.h> using namespace std; const int MAXN = 1005; int f[MAXN]; // int main() { int n, m; cin >> n >> m; for(int i = 1; i <= n; i++) { int v, w; cin >> v >> w; // 边输入边处理 for(int j = m; j >= v; j--) f[j] = max(f[j], f[j - v] + w); } cout << f[m] << endl; return 0; }

01背包

image.png

cpp
class Solution { public: int maxSatisfaction(vector<int>& satisfaction) { int n = satisfaction.size(); vector<vector<int>> dp(n + 1, vector<int>(n + 1)); sort(satisfaction.begin(), satisfaction.end()); int res = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { dp[i][j] = dp[i - 1][j - 1] + satisfaction[i - 1] * j; if (j < i) { dp[i][j] = max(dp[i - 1][j], dp[i][j]); } res = max(res, dp[i][j]); } } return res; } };

完全背包 image.png

image.png

cpp
#include<iostream> using namespace std; const int N = 1010; int n, m; int f[N][N], v[N], w[N]; int main(){ cin >> n >> m; for(int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for(int i = 0; i <= m; i++)//初始化 { f[0][i] = 0; } for(int i = 1; i <= n; i ++ ) for(int j = 0; j <= m; j ++ ) for(int k = 0; k * v[i] <= j; k ++ ) f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);//求出每一个 f[i][j] cout << f[n][m] << endl; } // 优化 #include<iostream> using namespace std; const int N = 1010; int f[N]; int v[N],w[N]; int main() { int n,m; 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; }

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!