题目描述
/* 01背包问题
题目描述
一个旅行者有一个最大能装M公斤的背包,现在有N件物品,他们的重量分别是Wi,
价值分别是Vi,求旅行者能获得的最大总价值
输入
第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);
第2到 N+1 行: 每行两个整数W[i],V[i],表示每个物品的重量和价值
输出
仅一行,一个数,表示最大的总价值
测试样例
10 4
2 1
3 3
4 5
7 9
输出 -> 12
*/
分析
动态规划实现,详细分析教程移步下方传送门,讲得非常详细(就是时间有点儿长,55分钟)。
https://www.bilibili.com/video/BV1C7411K79w?from=search&seid=554744848366710695
核心在于,状态转移方程式的推算,01背包的状态转移方程式为:
dp[i][j] = max {dp[i-1][j],dp[i-1][j-W[i]] + V[i]}
其中,dp代表动态规划的二维表,i表示第几件物品,j表示当前背包总容量。
js代码
// 创建完全二维数组函数
const createFullTwoDimenArray = (len, width, num = '') => new Array(len).fill(num).map(item => new Array(width).fill(num))
// 基础解题,二维数组动态规划
const package_01 = (M, N, W, V) => {
// dp 数组 dp[i][0] = 0 dp[0][j] = 0 防止下标运算越界
const dp = createFullTwoDimenArray(N + 1, M + 1, 0)
for (let i = 1; i <= N; i++) {
for (let j = 1; j <= M; j++) {
if (j < W[i])
dp[i][j] = dp[i - 1][j]
else
dp[i][j] = dp[i - 1][j] >= dp[i - 1][j - W[i]] + V[i] ? dp[i - 1][j] : dp[i - 1][j - W[i]] + V[i]
}
}
return dp[N][M]
}
// 优化版本,一维滚动数组
// 因为后无效性原则:当前状态只与上一次的状态有关
// 其实每次只用到了上一次统计过的数据,所有可以讲二维表优化成为一维的数组不停的覆盖运算即可
const package_01_ScrollingArray = (M, N, W, V) => {
const dp = new Array(M + 1).fill(0)
for (let i = 1; i <= N; i++) {
for (let j = M; j >= 1; j--) {
if (j >= W[i])
dp[j] = dp[j] >= dp[j - W[i]] + V[i] ? dp[j] : dp[j - W[i]] + V[i]
}
}
return dp[M]
}
// 测试数据
// <详细输入太麻烦了,直接把测试数据写死了>
const W = [0, 2, 3, 4, 7] // 每个物品的重量,0位 置0
const V = [0, 1, 3, 5, 9] // 每个物品的价值,0位 置0
const M = 10 // 背包容量
const N = 4 // 物品数量
console.log('最大的总价值:', package_01(M, N, W, V))
console.log('最大的总价值:', package_01_ScrollingArray(M, N, W, V))
C++代码
#include <iostream>
using namespace std;
int dp[32][202]
int W[32],V[32]
int main(){
int m,n;
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>W[i]>>V[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if (j<W[i])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = max(dp[i-1][j],dp[i-1][j-W[i]] + V[i]);
}
}
cout<<dp[n][m];
return 0;
}
// 滚动数组
#include <iostream>
using namespace std;
int W[32],V[32],dp[202]
int main(){
int m,n;
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>W[i]>>V[i];
}
for(int i=1;i<=n;i++){
for(int j=w;j>=1;j--){
if (j>=W[i])
dp[j] = max(dp[j],dp[j-W[i]] + V[i]);
}
}
cout<<dp[m];
return 0;
}

1823

被折叠的 条评论
为什么被折叠?



