To jest bardziej rozwiązanie hybrydowe, z programowania dynamicznego i algorytm z nawrotami. Możemy użyć Back Tracking samodzielnie, aby rozwiązać ten problem, ale wtedy musimy wykonać wyczerpujące wyszukiwanie (2^N), aby znaleźć rozwiązanie. Część DP optymalizuje przestrzeń poszukiwań w Back Tracking.
import sys
from collections import OrderedDict
MinimumSum = 31
MaxArraySize = 4
InputData = sorted([1,4,5,10,17,34])
# Input part is over
Target = MinimumSum + 1
Previous, Current = OrderedDict({0:0}), OrderedDict({0:0})
for Number in InputData:
for CurrentNumber, Count in Previous.items():
if Number + CurrentNumber in Current:
Current[Number + CurrentNumber] = min(Current[Number + CurrentNumber], Count + 1)
else:
Current[Number + CurrentNumber] = Count + 1
Previous = Current.copy()
FoundSolution = False
for Number, Count in Previous.items():
if (Number >= Target and Count < MaxArraySize):
MaxArraySize = Count
Target = Number
FoundSolution = True
break
if not FoundSolution:
print "Not possible"
sys.exit(0)
else:
print Target, MaxArraySize
FoundSolution = False
Solution = []
def Backtrack(CurrentIndex, Sum, MaxArraySizeUsed):
global FoundSolution
if (MaxArraySizeUsed <= MaxArraySize and Sum == Target):
FoundSolution = True
return
if (CurrentIndex == len(InputData) or MaxArraySizeUsed > MaxArraySize or Sum > Target):
return
for i in range(CurrentIndex, len(InputData)):
Backtrack(i + 1, Sum, MaxArraySizeUsed)
if (FoundSolution): return
Backtrack(i + 1, Sum + InputData[i], MaxArraySizeUsed + 1)
if (FoundSolution):
Solution.append(InputData[i])
return
Backtrack(0, 0, 0)
print sorted(Solution)
Uwaga: Zgodnie z przykładów podanych przez Ciebie w pytaniu, minimalną kwotę i maksymalną wielkość tablicy są ściśle większe i mniejsze niż wartości określone odpowiednio.
Do tego wejścia
MinimumSum = 31
MaxArraySize = 4
InputData = sorted([1,4,5,10,17,34])
Wyjście jest
[5, 10, 17]
gdzie jak na tym wejściu
MinimumSum = 31
MaxArraySize = 3
InputData = sorted([1,4,5,10,17,34])
Wyjście jest
[34]
Objaśnienie
Target = MinimumSum + 1
Previous, Current = OrderedDict({0:0}), OrderedDict({0:0})
for Number in InputData:
for CurrentNumber, Count in Previous.items():
if Number + CurrentNumber in Current:
Current[Number + CurrentNumber] = min(Current[Number + CurrentNumber], Count + 1)
else:
Current[Number + CurrentNumber] = Count + 1
Previous = Current.copy()
Ta część programu wyszukuje minimalną liczbę numerów na podstawie danych wejściowych, wymagane, aby suma liczb od 1 do maksymalnej możliwej liczby (która jest sumą wszystkich dane wejściowe). Jest to rozwiązanie do programowania dynamicznego, w przypadku problemu z plecakiem. Możesz o tym przeczytać w Internecie.
FoundSolution = False
for Number, Count in Previous.items():
if (Number >= Target and Count < MaxArraySize):
MaxArraySize = Count
Target = Number
FoundSolution = True
break
if not FoundSolution:
print "Not possible"
sys.exit(0)
else:
print Target, MaxArraySize
Ta część programu wyszukuje wartość Target
który pasuje kryteria MaxArraySize
.
def Backtrack(CurrentIndex, Sum, MaxArraySizeUsed):
global FoundSolution
if (MaxArraySizeUsed <= MaxArraySize and Sum == Target):
FoundSolution = True
return
if (CurrentIndex == len(InputData) or MaxArraySizeUsed > MaxArraySize or Sum > Target):
return
for i in range(CurrentIndex, len(InputData)):
Backtrack(i + 1, Sum, MaxArraySizeUsed)
if (FoundSolution): return
Backtrack(i + 1, Sum + InputData[i], MaxArraySizeUsed + 1)
if (FoundSolution):
Solution.append(InputData[i])
return
Backtrack(0, 0, 0)
Teraz, gdy wiemy, że istnieje rozwiązanie, chcemy odtworzyć rozwiązanie. Używamy techniki backtrackingu tutaj. Możesz łatwo znaleźć wiele dobrych tutoriali na ten temat również w Internecie.
Jeśli chcesz ograniczyć rozmiar tablicy do 5 i sumę 37, co jeśli lista byłaby "[1,4,5,10,17,37]", czy chcesz ją zwrócić '[37]' lub [1,4,5,10,17] '? – lurker
To wygląda na odmianę na http://en.wikipedia.org/wiki/Knapsack_problem –
@mbratch: To by zwróciło 37. – crough