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
[]
= "KnapsackSlice selects optimally where greedy would not"
= "slicing"
= "knapsack"
# Budget: 300 tokens, bucket_size: 100
# This is a case where knapsack differs from greedy.
#
# Items:
# "big": tokens=250, score=0.7 → value=7000, dw=ceil(250/100)=3
# "small-a": tokens=150, score=0.5 → value=5000, dw=ceil(150/100)=2
# "small-b": tokens=150, score=0.45 → value=4500, dw=ceil(150/100)=2
#
# Capacity = floor(300/100) = 3
#
# Greedy (by density):
# big: 0.7/250 = 0.0028
# small-a: 0.5/150 ≈ 0.00333
# small-b: 0.45/150 = 0.003
# → small-a first (dw=2, remaining=1), small-b next (dw=2 > 1, skip),
# big (dw=3 > 1, skip). Only "small-a" selected. Total value = 5000.
#
# Knapsack DP:
# At capacity 3, can fit big (dw=3, value=7000) or small-a (dw=2, value=5000).
# big at w=3: dp[3-3]+7000 = 7000 > 0 → dp[3]=7000, keep[0][3]=true
# small-a at w=3: dp[3-2]+5000 = 5000 < 7000 → no change
# small-a at w=2: dp[2-2]+5000 = 5000 > 0 → dp[2]=5000, keep[1][2]=true
# small-b at w=3: dp[3-2]+4500 = dp[1]+4500 = 4500 < 7000 → no change
# small-b at w=2: dp[2-2]+4500 = 4500 < 5000 → no change
#
# Reconstruct from capacity=3: keep[2][3]=false, keep[1][3]=false, keep[0][3]=true → "big"
# → Knapsack selects "big" (value 7000 > 5000)
[]
= 100
[]
= 300
[[]]
= "big"
= 250
= 0.7
[[]]
= "small-a"
= 150
= 0.5
[[]]
= "small-b"
= 150
= 0.45
[]
= ["big"]