ACM ICPC
Praktikum
Kapitel 11: Dynamische
Programmierung
Übersicht
•
•
•
•
•
•
Definition
Fibonacci Zahlen
Binomialkoeffizienten
Edit Distanz
Transitive Hülle
Fahrstuhloptimierung
Dynamische Programmierung
• Entwickelt von R. Bellman in 50er Jahren
• Methode zur Lösung von Problemen mit
überlappenden Teilproblemen
dasselbe Teilproblem:
berechne nur einmal
Fibonacci Zahlen
• F(0)=F(1)=1
• F(n) = F(n-1)+F(n-2)
• Getrennte rekursive Aufrufe:
Aufwand n = 1,682…n
• Berechnung von 1 bis n durch Merken der
zwei letzten Fibonacci Zahlen:
Aufwand O(n)
Binomialkoeffizient
• C(n,0) = C(n,n) = 1
• C(n,k) = C(n-1,k-1) + C(n-1,k)
• Getrennte rekursive Aufrufe:
Aufwand O(2n)
• Berechnung über Tabelle von C(n‘,k‘)Werten, angefangen bei n‘=k‘=0:
Aufwand O(n ¢ k)
Edit Distanz
• Gegeben: zwei Zeichenketten s,t
• Gesucht: Edit Distanz zwischen s und t,
d.h. minimale Anzahl an Substitutionen,
Einfügungen und Löschungen von
Zeichen, um s in t zu überführen
• Durchlauf aller Möglichkeiten: zu teuer!
Edit Distanz
Brute force:
1.
#define MATCH 0
2.
3.
4.
5.
6.
int string_compare(char *s, char *t, int i, int j)
{
int k;
/* counter */
int opt[3];
/* cost of the three options */
int lowest_cost;
/* lowest cost */
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17. }
#define INSERT 1
#define DELETE 2
if (i == 0) return(j * indel(' '));
if (j == 0) return(i * indel(' '));
opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]);
opt[INSERT] = string_compare(s,t,i,j-1) + indel(t[j]);
opt[DELETE] = string_compare(s,t,i-1,j) + indel(s[i]);
lowest_cost = opt[MATCH];
for (k=INSERT; k<=DELETE; k++)
if (opt[k] < lowest_cost) lowest_cost = opt[k];
m[i][j].cost = lowest_cost;
/* REMOVE FROM PRINTED VERSION */
return( lowest_cost );
Edit Distanz
Subroutinen:
1. int match(char c, char d)
2. {
3.
if (c==d) return(0);
4.
else return(1);
5. }
6. int indel(char c)
7. {
8.
return(1);
9. }
Edit Distanz
Besser: statt getrennter rekursiver Aufrufe,
berechne Tabelle
• T[i,j] = min{T[i-1,j-1]+match(s[i],t[j]),
T[i,j-1]+indel(t[j]),
T[i-1,j]+indel(s[i])}
• Aufwand: O(|s| ¢ |t|)
Transitive Hülle
• Gegeben: Graph G=(V,E)
• Gesucht: Boolesche Matrix T=(tij), in der
tij=1 , es ex. Pfad von i nach j in G
• Brute force: Breitensuche für jedes (i,j)
Aufwand: O(n2 ¢ m), n=|V|, m=|E|
• Besser: rekursiver Ansatz
Transitive Hülle
Rechenregeln:
• t(0)i,j=1 , {i,j} 2 E
• t(k)i,j=t(k-1)i,j Ç (t(k-1)i,k Æ t(k-1)k,j)
• ti,j = t(n)i,j
Berechnung der Tabelle: Aufwand O(n3)
Fahrstuhl Optimierung
• Gegeben: Ein Fahrstuhl mit n Personen,
jede Person hat Zielstockwerk, Anzahl
Halte k
• Gesucht: Stockwerke für k Halte, so dass
Anzahl der Stockwerke, die Personen
laufen müssen, minimiert wird.
Gleiche Kosten: wähle kleinstmögliches
Stockwerk.
Fahrstuhl Optimierung
• m[i,j]: minimale Kosten für genau j Halte
mit höchstem Halt in Stockwerk i
• m[i,1] = mincost(0,i) + mincost(i,1)
• m[i,j] = mink<i { m[k,j-1] – mincost(k,1) +
mincost(k,i) + mincost(i,1)}
• mincost(a,b): minimale Kosten für
Personen mit Zielstockwerken zwischen a
und b, falls Halte bei a und b-1.
Rucksack Problem
• Gegeben: n Gegenstände mit Gewicht
w1,...,wn und Wert v1,...,vn, Kapazität W
• Gesucht: Menge M an Gegenständen mit
maximalem Wert, so dass i 2 M wi <= W
• Ansatz: V[i,j] = maximaler Wert für
Gegenstände 1 bis i bei Kapazität j
Rucksack Problem
Rechenregel:
• V[0,j] = 0
• V[i,j] = max{ V[i-1,j], vi + V[i-1,j-wi]}
falls j-wi >= 0
• V[i,j] = V[i-1,j] falls j-wi < 0
Laufzeit: O(n ¢ W)

Dynamische Programmierung