Ga naar hoofdinhoud

Er gaat iets mis — top-3 fouten

Leerdoel: je herkent de drie klassieke valkuilen bij de tabel-aanpak van knapsack.

Off-by-one in tabel-grootte​

Foutmelding: IndexError: list index out of range of een tabel die te klein is.

Oorzaak: vergeet de +1 bij rijen of kolommen. De tabel heeft (n + 1) × (capaciteit + 1) cellen, niet n × capaciteit. Die extra rij is voor "geen items" (basisgeval); die extra kolom is voor "lege rugzak".

# FOUT
tabel = []
for _ in range(n):
tabel.append([0] * capaciteit)

# Probleem: tabel[n][capaciteit] bestaat niet → crash bij return.

Oplossing:

# GOED
tabel = []
for _ in range(n + 1):
tabel.append([0] * (capaciteit + 1))

Vuistregel: als je naar een cel [i][w] wilt kunnen met i = n én w = capaciteit, heb je n + 1 rijen en W + 1 kolommen nodig.

i-loop start bij 0​

Geen foutmelding, wel een rij 0 die niet meer 0 is, en soms een totaalwaarde die te hoog is.

Oorzaak: rij 0 in de tabel is al ingevuld (basisgeval: allemaal 0). Je werkelijke "vul-rij"-werk start bij i = 1. Begin je bij i = 0, dan haal je items[-1] op, en Python's negatieve index geeft je het laatste item. Dat item komt zo in rij 0 terecht en kan daarna nog een keer meetellen: één item van waarde 10 en gewicht 1 in een rugzak van 2 geeft dan 20. Op het voorbeeld van de les komt er toevallig nog 40 uit, met een rij 0 vol 28'en.

# FOUT
for i in range(n + 1): # start bij 0
waarde, gewicht = items[i - 1] # items[-1] = laatste item
...

Oplossing:

# GOED
for i in range(1, n + 1): # start bij 1
waarde, gewicht = items[i - 1]
...

Die 1 in range(1, n + 1) is het hele punt.

Backtrack vergeet capaciteit te verminderen​

Geen foutmelding, wel een verkeerde lijst van items.

Oorzaak: bij elke "item meegenomen"-stap moet je niet alleen de index opslaan, maar ook de capaciteit verminderen met het gewicht van dat item. Vergeet je dat, dan blijf je naar dezelfde kolom kijken en lijken meer items "meegenomen" dan klopt.

# FOUT
for i in range(n, 0, -1):
if tabel[i][w] != tabel[i - 1][w]:
keuze.append(i - 1)
# w wordt NIET aangepast → fout

Oplossing:

# GOED
for i in range(n, 0, -1):
if tabel[i][w] != tabel[i - 1][w]:
keuze.append(i - 1)
w -= items[i - 1][1] # cruciaal!

Je schuift naar links omdat dit item zijn gewicht al heeft ingenomen: er is minder capaciteit over voor de rest.

Door naar cheatsheet →.