这段代码实现了一个经典的0-1 背包问题的动态规划解法。0-1 背包问题是指给定一组物品,每个物品有其体积和价值,要求在不超过背包容量的情况下,选择物品使得总价值最大。以下是代码的详细思路解析:
1. 问题背景
给定 n 个物品,每个物品有其体积 v[i] 和价值 w[i],以及一个容量为 m 的背包。目标是选择物品使得总价值最大,同时总容量不超过背包的容量。
2. 动态规划的概念
动态规划是一种常用的算法技巧,用于解决具有重叠子问题和最优子结构的问题。在 0-1 背包问题中,动态规划通过维护一个二维数组 f 来记录不同状态下的最大价值。
3. 代码逻辑解析
(1) 输入数据
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i]; 
-  
用户输入物品数量
n和背包容量m。 -  
对于每个物品,输入其体积
v[i]和价值w[i]。 
(2) 动态规划状态转移
for (int i = 1; i <= n; i++)for (int j = 0; j <= m; j++){f[i][j] = f[i - 1][j];  // 不选择第 i 个物品if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);  // 选择第 i 个物品} 
-  
外层循环:
-  
遍历每个物品,从第 1 个到第
n个。 
 -  
 -  
内层循环:
-  
遍历背包的每个容量,从 0 到
m。 
 -  
 -  
状态转移:
-  
f[i][j]表示前i个物品在容量为j的背包下的最大价值。 -  
不选择第
i个物品:f[i][j] = f[i - 1][j],即前i-1个物品在容量为j的背包下的最大价值。 -  
选择第
i个物品:如果当前容量j大于等于第i个物品的体积v[i],则可以考虑选择第i个物品,更新f[i][j]为f[i - 1][j - v[i]] + w[i],即前i-1个物品在容量为j - v[i]的背包下的最大价值加上第i个物品的价值。 
 -  
 
(3) 输出结果
cout << f[n][m] << endl; 
-  
输出最终的最大价值,即
f[n][m]。 
4. 代码效率分析
-  
时间复杂度:
-  
两层循环遍历所有物品和所有容量,时间复杂度为 O(n × m)。
 
 -  
 -  
空间复杂度:
-  
使用了一个二维数组
f,空间复杂度为 O(n × m)。 
 -  
 
5. 示例运行
输入:
3 5
1 2
2 3
3 4 
运行过程:
-  
输入数据:
-  
n = 3, m = 5 -  
v = [1, 2, 3], w = [2, 3, 4] 
 -  
 -  
动态规划状态转移:
-  
初始化
f[0][j] = 0,表示没有物品时的最大价值为 0。 -  
对于第 1 个物品:
-  
f[1][0] = 0 -  
f[1][1] = 2 -  
f[1][2] = 2 -  
f[1][3] = 2 -  
f[1][4] = 2 -  
f[1][5] = 2 
 -  
 -  
对于第 2 个物品:
-  
f[2][0] = 0 -  
f[2][1] = 2 -  
f[2][2] = 3 -  
f[2][3] = 5 -  
f[2][4] = 5 -  
f[2][5] = 5 
 -  
 -  
对于第 3 个物品:
-  
f[3][0] = 0 -  
f[3][1] = 2 -  
f[3][2] = 3 -  
f[3][3] = 5 -  
f[3][4] = 6 -  
f[3][5] = 7 
 -  
 
 -  
 
输出:
7 
6. 总结
这段代码的核心思路是通过动态规划解决 0-1 背包问题。通过维护一个二维数组 f,记录不同状态下的最大价值,并通过状态转移方程更新最大价值,最终找到在给定背包容量下的最大价值。这种方法的时间复杂度为 O(n × m),适用于中等规模的 0-1 背包问题。
完整代码
#include<bits/stdc++.h>
using namespace std;// 定义数组的最大长度
const int N = 1010;
// n 表示物品的数量,m 表示背包的容量
int n, m;
// v 数组存储每个物品的体积,w 数组存储每个物品的价值
int v[N], w[N];
// f 数组是二维数组,f[i][j] 表示前 i 个物品,背包容量为 j 时能获得的最大价值
int f[N][N];int main()
{// 输入物品的数量 n 和背包的容量 mcin >> n >> m;// 循环读入每个物品的体积和价值for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];// 动态规划过程,外层循环遍历每个物品for(int i = 1; i <= n; i ++)// 内层循环遍历背包的所有可能容量for(int j = 0; j <= m; j ++){// 不选择第 i 个物品,那么前 i 个物品在容量为 j 的背包中的最大价值// 就等于前 i - 1 个物品在容量为 j 的背包中的最大价值f[i][j] = f[i - 1][j];// 如果当前背包的容量 j 大于等于第 i 个物品的体积 v[i]// 说明可以选择放入第 i 个物品if(j >= v[i]) // 比较不放入第 i 个物品和放入第 i 个物品两种情况下的最大价值// 放入第 i 个物品的价值为 f[i - 1][j - v[i]] + w[i]f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);}// 输出前 n 个物品,背包容量为 m 时能获得的最大价值cout << f[n][m] << endl;return 0;
}