Babeș-Bolyai Universität Cluj Napoca Fakultät für Mathematik und

Werbung
Babeș-Bolyai Universität
Cluj Napoca
Fakultät für Mathematik und Informatik
Grundlagen der Programmierung MLG5005
Seminar XI/XII
Greedy
Greedy Algorithmen sind anwendbar bei Konstruktionsaufgaben zum Finden einer optimalen Struktur. Sie finden eine
Lösung, die sie schrittweise aufbauen, ohne zurückzusetzen. Es werden dabei nicht mehr Teillösungen konstruiert als
unbedingt nötig.
Bestandteile
1. eine sich verbrauchende Kandidatenliste
2. eine sich aufbauende Resultatliste
3. Eine Auswahlfunktion, die aus der Kandidatenliste den jeweils besten Teil auswählt
4. Eine Lösungfunktion, die kontrolliert, ob die aktuelle Resultatliste eine Lösung des Problems darstellt
5. Eine Okayfunktion, die kontrolliert, ob die Erweiterung einer Resultatliste durch den nächsten Kandidaten zulässig
ist
6. Eine Zeilfunktion, die den Wert einer Lösung angibt
•
•
Greedy Algorithmus ist sehr einfach und schnell zu realisieren
unter Umständen ist die Lösung nicht optimal
1. Das Geldwechselproblem.
Ein Geldbetrag soll mit der kleinstmöglichen Zahl von Münzen gegeben werden.
def solve(coins, n):
result = []
coins.sort()
while n > 0:
p = len(coins) - 1
while p > 0 and coins[p] > n:
p -= 1
result.append(coins[p])
n -= coins[p]
return result
coins = [1, 5, 10, 50]
for i in range(1, 1000):
assert sum(solve(coins, i)) == I
2. Das Problem des Handlungsreisenden.
Gegeben ist ein gewichteter, ungerichteter Graph. Knoten repräsentieren Städte, Kanten die mit Kosten gewichteten
Verkehswege zwischen den Städten. Gesucht ist ein Tour durch den Graph, bei der jeden Knoten besucht wird und die
am Ausgangsknoten endet, derart, dass die Kosten minimal sind.
Greedy: die Strategie der kürzesten Verbindung → ABDBCE
3. Ein Scheduling Problem.
Gegeben wird n Jobs der Größen s1, …, sn und n Prozessoren. Gesucht ist eine Abbildung der Jobs auf die Prozessoren
mit minimaler Ausführungszeit.
Beispiel:
Jobs (min): 3, 5, 6, 10, 11, 14, 15, 18, 20
Prozessoren: 3
Greedy: Total 35 min
Optimal: Total 34 min
Divide et Impera
Die Strategie Divide et Impera zur Lösung eines Problems, dessen Eingabe die Größe n hat, besteht in folgender Idee:
a) Zerlege das Problem in mehrere Probleme der gleichen Art wie das ursprüngliche, so daß
1. die Eingabe jedes dieser Teilprobleme kleiner als n ist,
2. die Lösung des ursprünglichen Problems aus den Lösungen der Teilprobleme berechnet werden kann.
b) Löse jedes der Teilprobleme
1. entweder durch weitere Zerlegung wie in a)
2. oder direkt (das Problem ist trivial)
1. Finde die kleinste Zahl einer List.
def diMin(list):
if len(list) == 1:
return list[0]
m = len(list) / 2
return min(diMin(list[:m]), diMin(list[m:]))
print diMin(l)
2. Berechne den größten gemeinsamen Teiler.
def scmmdc(a,b):
while a!=b:
if a>b:
a-=b
else:
b-=a
return a
def cmmdc(x):
if len(x)==1:
return x[0]
a = cmmdc(x[0:len(x)/2])
b = cmmdc(x[len(x)/2:])
return scmmdc(a,b)
def testCmmdc():
d = {}
d[2] = [2,4,6,8,22]
d[12] = [12,48,60,1200]
d[10] = [10,2000]
for k in d.keys():
assert cmmdc(d[k]) == k
testCmmdc()
3. Das Maximum-Subarray Problem.
Gegeben ist eine Folge X von ganzen Zahlen im Array. Gesucht ist die Maximale Summe einer zusammenhängenden
Teilfolge von X.
Beispiel:
eingabe: [-2, -5, 6, -2, -3, 1, 5, -6]
ausgabe: Max sum: 7
T(n) ∈O(n*n*n)
def maxSubArraySumVerySlow(arr):
max = arr[0]
for i in range(0, len(arr)):
for j in range(i, len(arr)):
s=0
for k in range(i, j+1):
s+=arr[k]
if s>max:
max = s
return max
T(n) ∈O(n*n)
def maxSubArraySumSlow(arr):
max = arr[0]
for i in range(0, len(arr)):
s = 0
for j in range(i, len(arr)):
s+=arr[j]
if s>max:
max=s
return max
Divide et Impera: T(n) ∈ O(n*log(n))
def maxCrossingSum(arr, l, m, h):
sum = 0
i = m
left_sum = -1000
while i >= l:
sum = sum + arr[i]
i-=1
if sum > left_sum:
left_sum = sum;
sum = 0
i=m+1
right_sum = -1000
while i<=h:
sum = sum + arr[i]
i+=1
if sum > right_sum:
right_sum = sum;
return left_sum + right_sum;
def maxSubArraySum(arr, l, h):
if l == h:
return arr[l]
m = (l + h)/2
return max(maxSubArraySum(arr, l, m),
maxSubArraySum(arr, m+1, h),
maxCrossingSum(arr, l, m, h))
print "Max sum: " + str(maxSubArraySum(arr, 0, len(arr)-1))
import unittest
class SubArrayTest(unittest.TestCase):
def test(self):
self.assertEquals(maxSubArraySum([1], 0, 0), 1, "Array :"+str(arr))
self.assertEquals(maxSubArraySum([1, 1], 0, 1), 2, "Array :"+str(arr))
self.assertEquals(maxSubArraySum([1, -10, 1], 0, 2), 1,
"Array :"+str(arr))
self.assertEquals(maxSubArraySum([-2, -5, 6, -2, -3, 1, 5, -6], 0, 7),
7, "Array :"+str(arr))
Komplexität:
T(n) = 2T(n/2) + n
T(n) ∈ O(n*log(n))
Herunterladen