01背包问题🌟🌟🌟🌟🌟
必看纠正
在视频中,我把 v[i] 和 w[i] 给搞反了,就是把 v[i] 看成了价值,把 w[i] 看成了体积。大家看的时候注意一下哈,因为寻思 v 就是 value,意思是价值,,,
01背包问题
有 N 件物品和一个容量是 V 的背包。每种物品只有一件。
第 i 件物品的体积是 V[i],价值是 W[i]。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
DP 三部曲
1、dp[i] [v]:在 0….i 中,体积为 v 的背包中,能够拿到的最大价值为 dp[i] [v]。
2、求关系式
dp[i] [v] dp[i-1] [v] dp[i] [v-x] 寻找一些关系式
dp[i] [v] =
(1)、对于第 i 件物品,如果不拿第 i 件物品,只剩下 0…i-1件物品=》dp[i] [v] = dp[i-1] [v],
(2)、对于第 i 件物品,如果 把它放进包里,那我们就能得到一个价值为 v[i] 的物品,
dp[i] [v] = dp[i-1] [v-w[i]] + v[i]。
最终公式:dp[i] [v] = max(dp[i-1] [v-w[i]] + v[i], dp[i-1] [v])
3、初始化条件
dp[0] [v] = 0
dp[i] [0] = 0
4、代码
代码实现
Java
import java.util.Scanner;
public class Main{
public static void main(String[] args) throws Exception {
// 读入数据的代码
Scanner reader = new Scanner(System.in);
// 物品的数量为N
int N = reader.nextInt();
// 背包的容量为V
int V = reader.nextInt();
// 一个长度为N的数组,第i个元素表示第i个物品的体积;
int[] v = new int[N + 1] ;
// 一个长度为N的数组,第i个元素表示第i个物品的价值;
int[] w = new int[N + 1] ;
for (int i=1 ; i <= N ; i++){
// 接下来有 N 行,每行有两个整数:v[i],w[i],用空格隔开,分别表示第i件物品的体积和价值
v[i] = reader.nextInt();
w[i] = reader.nextInt();
}
reader.close() ;
// 核心模式代码
int[][] dp = new int[N+1][V+1];
// 初始化
for(int i = 1; i <= N; i++){
for(int j = 0; j <= V; j++){
if(v[i] > j){
dp[i][j] = dp[i-1][j];
}else{
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]);
}
}
}
System.out.println(dp[N][V]);
}
}
Python
def main():
# 读入数据的代码
# 物品的数量为N
N, V = map(int, input().split())
# 一个长度为N的数组,第i个元素表示第i个物品的体积;
v = [0] * (N + 1)
# 一个长度为N的数组,第i个元素表示第i个物品的价值;
w = [0] * (N + 1)
for i in range(1, N + 1):
# 接下来有 N 行,每行有两个整数:v[i],w[i],用空格隔开,分别表示第i件物品的体积和价值
v[i], w[i] = map(int, input().split())
# 核心模式代码
dp = [[0 for _ in range(V + 1)] for _ in range(N + 1)]
# 初始化
for i in range(1, N + 1):
for j in range(V + 1):
if v[i] > j:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i])
print(dp[N][V])
if __name__ == "__main__":
main()
C++
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 读入数据的代码
int N, V;
cin >> N >> V;
vector<int> v(N + 1), w(N + 1);
for (int i = 1; i <= N; i++) {
// 接下来有 N 行,每行有两个整数:v[i],w[i],用空格隔开,分别表示第i件物品的体积和价值
cin >> v[i] >> w[i];
}
// 核心模式代码
vector<vector<int>> dp(N + 1, vector<int>(V + 1, 0));
// 初始化
for (int i = 1; i <= N; i++) {
for (int j = 0; j <= V; j++) {
if (v[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);
}
}
}
cout << dp[N][V] << endl;
return 0;
}
Go
package main
import (
"fmt"
)
func main() {
// 读入数据的代码
var N, V int
fmt.Scan(&N, &V)
v := make([]int, N+1)
w := make([]int, N+1)
for i := 1; i <= N; i++ {
// 接下来有 N 行,每行有两个整数:v[i],w[i],用空格隔开,分别表示第i件物品的体积和价值
fmt.Scan(&v[i], &w[i])
}
// 核心模式代码
dp := make([][]int, N+1)
for i := 0; i <= N; i++ {
dp[i] = make([]int, V+1)
}
// 初始化
for i := 1; i <= N; i++ {
for j := 0; j <= V; j++ {
if v[i] > j {
dp[i][j] = dp[i-1][j]
} else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]]+w[i])
}
}
}
fmt.Println(dp[N][V])
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
评论(1)
讲解里的公式v[i](体积)和w[i](价值)写反了,如果拿的时候公式应该是:dp[i][v] = dp[i-1][v-v[i]] + w[i]