01背包问题(go实现)

1.问题

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值。

输入格式

​ 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

​ 接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

​ 输出一个整数,表示最大价值。

数据范围

​ 0<N,V≤1000

​ 0<vi,wi≤1000

2.解题思路及代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main

import (
"fmt"
)

func main() {
/*
问题:
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000

*/
optimize()
// simplicity()
}

func max(x, y int) int {
if x < y {
return y
} else {
return x
}
}

func simplicity() {
/*
思路:
1、朴素实现
f[i][j]:表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。

转移方程:
1.不选第i件物品。
f[i][j]=f[i-1][j]

2.选择第i件物品。
f[i][j]=f[i-1][j-v[i]]+w[i]

汇总:
f[i][j]=max{f[i-1][j],f[i-1][j-v[i]]+w[i]}

复杂度:
时间和空间复杂度均为O(N*V)

*/
const N = 1010

var n, m int
var v, w [N]int
var f [N][N]int

fmt.Scanf("%d %d\n", &n, &m)

for i := 1; i <= n; i++ {
fmt.Scanf("%d %d\n", &v[i], &w[i])
}

for i := 1; i <= n; i++ {
for j := 0; 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])
}
}
}
fmt.Println(f[n][m])
}

func optimize() {
/*
1、优化空间复杂度
f[j]:表示容量为j的背包可以获得的最大价值。

转移方程:
1.不选第i件物品。
f[j]=f[j]

2.选择第i件物品。
f[j]=f[j-v[i]]+w[i]

汇总:
f[j]=max{f[j],f[j-v[i]]+w[i]}

复杂度:
时间复杂度均为O(N*V)
空间复杂度均为O(V)

*/
const N = 1010
var n, m int
var v, w [N]int
var f [N]int

fmt.Scanf("%d %d\n", &n, &m)
for i := 1; i <= n; i++ {
fmt.Scanf("%d %d\n", &v[i], &w[i])
for j := m; j >= v[i]; j-- {
f[j] = max(f[j], f[j-v[i]]+w[i])
}
}
fmt.Println(f[m])
}