-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathknapsack_problem_0_1.sf
76 lines (68 loc) · 1.76 KB
/
knapsack_problem_0_1.sf
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
#!/usr/bin/ruby
#
## https://rosettacode.org/wiki/Knapsack_problem/0-1
#
var raw = <<'TABLE'
map, 9, 150
compass, 13, 35
water, 153, 200
sandwich, 50, 160
glucose, 15, 60
tin, 68, 45
banana, 27, 60
apple, 39, 40
cheese, 23, 30
beer, 52, 10
suntancream, 11, 70
camera, 32, 30
T-shirt, 24, 15
trousers, 48, 10
umbrella, 73, 40
waterproof trousers, 42, 70
waterproof overclothes, 43, 75
note-case, 22, 80
sunglasses, 7, 20
towel, 18, 12
socks, 4, 50
book, 30, 10
TABLE
struct KnapsackItem {
String name,
Number weight,
Number value,
}
var items = []
raw.each_line{ |row|
var fields = row.split(/\s*,\s*/)
items << KnapsackItem(
name: fields[0],
weight: fields[1].to_n,
value: fields[2].to_n,
)
}
var max_weight = 400
var p = [
items.len.of { [[0, []], max_weight.of(nil)...] }...,
max_weight.inc.of {[0, []]}
]
func optimal(i, w) {
if (!defined p[i][w]) {
var item = items[i];
if (item.weight > w) {
p[i][w] = optimal(i.dec, w)
}
else {
var x = optimal(i.dec, w)
var y = optimal(i.dec, w - item.weight)
if (x[0] > (y[0] + item.value)) {
p[i][w] = x;
}
else {
p[i][w] = [y[0] + item.value, [y[1]..., item.name]]
}
}
}
return p[i][w]
}
var sol = optimal(items.end, max_weight)
say "#{sol[0]}: #{sol[1].join(' ')}"