Implementacja rozwiązań różnych wariantów problemu plecakowego w języku Python
Ważne!
W kolejnych implementacjach wykorzystamy funkcję pomocniczą sortuj, której zadaniem jest posortowanie dostępnych przedmiotów nierosnąco ze względu na iloraz wartości oraz wag. Użyjemy zmodyfikowanego algorytmu sortowania bąbelkowegoPoYAEP8llsortowania bąbelkowego (nie będziemy go tu omawiać).
Linia 1. def sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły dwukropek.
Linia 2. for i in range otwórz nawias okrągły n minus 1 zamknij nawias okrągły dwukropek.
Linia 3. for j in range otwórz nawias okrągły n minus i minus 1 zamknij nawias okrągły dwukropek.
Linia 4. if wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy dwukropek.
Linia 5. wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy.
Linia 6. indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy.
def sortuj(wartoscDoWagi, indeksy, n):
for i in range(n - 1):
for j in range(n - i - 1):
if wartoscDoWagi[j] < wartoscDoWagi[j + 1]:
wartoscDoWagi[j], wartoscDoWagi[j + 1] = wartoscDoWagi[j + 1], wartoscDoWagi[j]
indeksy[j], indeksy[j + 1] = indeksy[j + 1], indeksy[j]
Ważne!
Podejście zachłannealgorytm zachłannyzachłanne może nie dać najlepszego możliwego wyniku w wypadku problemu plecakowego.
Ogólny problem plecakowy
Specyfikacja problemu:
Dane:
nazwy – tablica liczb łańcuchów znaków; nazwy poszczególnych przedmiotów
wartosci – tablica liczb naturalnych; wartości poszczególnych przedmiotów
wagi – tablica liczb naturalnych; wagi poszczególnych przedmiotów
n – liczba naturalna; liczba rodzajów przedmiotów
pojemnosc – liczba naturalna; maksymalna pojemność plecaka
Wynik:
liczby sztuk poszczególnych przedmiotów (również równe 0), których całkowita waga nie przekracza wartości przechowywanej w zmiennej pojemnosc, a których całkowita wartość jest największa wśród możliwych wypełnień plecaka rzeczami o takiej wadze, która nie przekracza wartości zmiennej pojemnosc
całkowita wartość spakowanego plecaka
Zaprezentowane rozwiązania będziemy testować dla następujących danych:
maksymalna pojemność plecaka wynosi 41;
do dyspozycji mamy nieograniczoną liczbę sztuk każdego rodzaju przedmiotów;
przedmioty mają następujące wartości oraz wagi:
Przedmiot –
0
1
2
3
4
5
6
Nazwa
anemon
bławatek
chaber
dziurawiec
eustoma
forsycja
gipsówka
Wartość
21
15
4
4
14
1
3
Waga
11
8
5
4
7
1
7
Już wiesz
Przypomnijmy, w jaki sposób działa algorytm, analizując zaprezentowane dane.
Dla każdego posortowanego przedmiotu sprawdzamy, czy można go spakować, a jeśli tak, ile sztuk.
Wybieramy pierwszy przedmiot. To eustoma, której waga to 7. Do plecaka wkładamy 5 sztuk tego przedmiotu. Pojemność plecaka po spakowaniu tych przedmiotów wynosi 6.
Waga kolejnego przedmiotu (anemonu) wynosi 11, zatem nie można go spakować do plecaka.
Następny przedmiot, bławatek, waży 8. On również nie może zostać spakowany do plecaka.
Kolejny przedmiot to dziurawiec. Jego waga wynosi 4, zatem do plecaka można spakować jego jedną sztukę. Po spakowaniu kolejnych przedmiotów pojemność plecaka wynosi 2.
Następnym przedmiotem jest forsycja. Jej waga to 1. Do plecaka pakujemy jej dwie sztuki.
W plecaku nie ma więcej miejsca, zatem kolejne przedmioty nie mogą zostać spakowane.
Obliczmy całkowitą wartość spakowanych przedmiotów:
eustoma: 14 × 5 sztuk
dziurawiec: 1 × 4 sztuki
forsycja: 2 × 1 sztuka
Całkowita wartość spakowanych przedmiotów wynosi 76. Wykorzystaliśmy całe miejsce.
W programie wykorzystamy dwie funkcje:
ogolnyPlecak – funkcja mająca na celu znalezienie największej łącznej wartości przedmiotów, które można zmieścić w plecaku o określonej pojemności z wykorzystaniem podejścia zachłannego;
sortuj – funkcja pomocnicza.
Jak wspomnieliśmy, nie będziemy omawiać funkcji sortuj. Przejdziemy zatem do zapisania funkcji właściwej.
Zapisujemy jej nagłówek. Funkcja przyjmie pięć argumentów:
nazwy – tablica łańcuchów znaków; nazwy poszczególnych przedmiotów,
wartosci – tablica liczb naturalnych; wartości poszczególnych przedmiotów,
wagi – tablica liczb naturalnych; wagi poszczególnych przedmiotów,
n – liczba naturalna; liczba rodzajów przedmiotów,
pojemnosc – liczba naturalna; maksymalna pojemność plecaka.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
W pierwszym kroku tworzone są dwie kolejne tablice:
wartoscDoWagi – tablica liczb rzeczywistych,
indeksy – tablica liczb naturalnych.
Obie tablice składają się z n elementów. Zapisujemy pętlę for, która będzie iterować po kolejnych elementach tablic, by je zapełnić.
Każdy i-ty element tablicy wartosci dzielimy przez i-ty element tablicy wagi. Pamiętajmy o wykonaniu rzutowania, by uzyskany wynik był liczbą zmiennoprzecinkową.
Wynik dodajemy do tablicy wartoscDoWagi. Następnie do tablicy indeksy dodajemy kolejne wartości licznika, czyli zmiennej i.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 2. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 3. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 4. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 5. wartoscDoWagi kropka append otwórz nawias okrągły float otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 6. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(float(wartosci[i]) / wagi[i])
indeksy.append(i)
Po wyjściu z pętli wywołujemy funkcję sortuj.
Funkcja sortuj przyjmuje trzy argumenty:
wartoscDoWagi – tablica liczb rzeczywistych,
indeksy – tablica liczb naturalnych,
n – liczba naturalna.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 2. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 3. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 4. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 5. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 6. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 8. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
Po wykonaniu sortowania tworzymy zmienną wynik i przypisujemy jej wartość 0. Zmienna ta będzie przechowywała sumę wartości wybranych przedmiotów.
Tworzymy również tablicę spakowane. Będzie przechowywała liczniki spakowanych przedmiotów.
W kolejnym kroku zapisujemy pętlę for, która będzie iterowała przez posortowane przedmioty. Wykorzystamy ją do wypełnienia tablicy spakowane zerami.
Zapisujemy kolejną pętlę for. Ponownie iterujemy przez posortowane przedmioty.
W pętli utworzymy zmienną indeks, której z każdą iteracją będziemy przypisywać wartość i-tego elementu tablicy indeksy – pobieramy w ten sposób indeks bieżącego przedmiotu.
Zapisujemy pętlę while. Będzie ona wykonywała się tak długo, jak długo waga pakowanego przedmiotu będzie albo mniejsza od pojemności, albo jej równa. Dzięki tej pętli kolejne przedmioty będą mogły być dodawane więcej niż jeden raz.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 2. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 3. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 4. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 5. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 6. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 8. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
Linia 10. wynik znak równości 0.
Linia 11. spakowane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 12. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 13. spakowane kropka append otwórz nawias okrągły 0 zamknij nawias okrągły.
Linia 15. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 16. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 17. while wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości paojemnosc dwukropek.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
wynik = 0
spakowane = []
for i in range(n):
spakowane.append(0)
for i in range(n):
indeks = indeksy[i]
while wagi[indeks] <= paojemnosc:
Jeśli przedmiot o danym indeksie zmieści się w plecaku, waga przedmiotu odejmowana jest od dostępnej pojemności plecaka (element tablicy wagi o indeksie indeks jest odejmowany od wartości zmiennej pojemnosc). Równocześnie dodajemy wartość tego przedmiotu do wyniku (element tablicy wartosci o indeksie indeks jest dodawany do wartości zmiennej wynik). Inkrementujemy wartość elementu tablicy spakowane o indeksie indeks.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 2. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 3. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 4. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 5. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 6. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 8. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
Linia 10. wynik znak równości 0.
Linia 11. spakowane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 12. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 13. spakowane kropka append otwórz nawias okrągły 0 zamknij nawias okrągły.
Linia 15. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 16. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 17. while wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości pojemnosc dwukropek.
Linia 18. pojemnosc minus znak równości wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 19. wynik plus znak równości wartosci otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 20. spakowane otwórz nawias kwadratowy indeks zamknij nawias kwadratowy plus plus.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
wynik = 0
spakowane = []
for i in range(n):
spakowane.append(0)
for i in range(n):
indeks = indeksy[i]
while wagi[indeks] <= pojemnosc:
pojemnosc -= wagi[indeks]
wynik += wartosci[indeks]
spakowane[indeks]++
Po wyjściu z pętli for zapisujemy kolejną pętlę for. Wykorzystamy ją do wypisywania informacji na temat tego, ile sztuk danego rodzaju przedmiotu zostało spakowanych.
Wypisujemy całkowitą wartość spakowanych przedmiotów.
Linia 1. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 2. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 3. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 4. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 5. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 6. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 8. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
Linia 10. wynik znak równości 0.
Linia 11. spakowane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 12. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 13. spakowane kropka append otwórz nawias okrągły 0 zamknij nawias okrągły.
Linia 15. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 16. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 17. while wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości pojemnosc dwukropek.
Linia 18. pojemnosc minus znak równości wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 19. wynik plus znak równości wartosci otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 20. spakowane otwórz nawias kwadratowy indeks zamknij nawias kwadratowy plus plus.
Linia 22. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 23. print otwórz nawias okrągły cudzysłów Liczba spakowanych sztuk przedmiotu cudzysłów plus nazwy otwórz nawias kwadratowy i zamknij nawias kwadratowy plus cudzysłów otwórz nawias okrągły indeks cudzysłów plus str otwórz nawias okrągły i zamknij nawias okrągły plus cudzysłów zamknij nawias okrągły dwukropek cudzysłów plus str otwórz nawias okrągły spakowane otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias okrągły.
Linia 25. print otwórz nawias okrągły cudzysłów lewy ukośnik nWartosc spakowanych przedmiotow dwukropek cudzysłów przecinek wynik.
def ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
wynik = 0
spakowane = []
for i in range(n):
spakowane.append(0)
for i in range(n):
indeks = indeksy[i]
while wagi[indeks] <= pojemnosc:
pojemnosc -= wagi[indeks]
wynik += wartosci[indeks]
spakowane[indeks]++
for i in range(n):
print("Liczba spakowanych sztuk przedmiotu " + nazwy[i] + " (indeks " + str(i) + "): " + str(spakowane[i]))
print("\nWartosc spakowanych przedmiotow: ", wynik
Ważne!
W linii 23 wykonujemy rzutowanie typu (zmiana typu całkowitoliczbowego na łańcuch znaków), by dokonać konkatenacji łańcuchów znaków, a w konsekwencji uniknąć znaków spacji umieszczanych między zmiennymi a łańcuchami znaków.
Dodajemy wywołanie funkcji.
Pamiętamy również o dodaniu funkcji sortuj.
Oto kompletny kod programu:
Linia 1. def sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły dwukropek.
Linia 2. for i in range otwórz nawias okrągły n minus 1 zamknij nawias okrągły dwukropek.
Linia 3. for j in range otwórz nawias okrągły n minus i minus 1 zamknij nawias okrągły dwukropek.
Linia 4. if wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy dwukropek.
Linia 5. wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy.
Linia 6. indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy.
Linia 8. def ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 9. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 10. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 11. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 12. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 13. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 15. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
Linia 17. wynik znak równości 0.
Linia 18. spakowane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 19. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 20. spakowane kropka append otwórz nawias okrągły 0 zamknij nawias okrągły.
Linia 22. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 23. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 24. while wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości pojemnosc dwukropek.
Linia 25. pojemnosc minus znak równości wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 26. wynik plus znak równości wartosci otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 27. spakowane otwórz nawias kwadratowy indeks zamknij nawias kwadratowy plus znak równości 1.
Linia 29. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 30. print otwórz nawias okrągły cudzysłów Liczba spakowanych sztuk przedmiotu cudzysłów plus nazwy otwórz nawias kwadratowy i zamknij nawias kwadratowy plus cudzysłów otwórz nawias okrągły indeks cudzysłów plus str otwórz nawias okrągły i zamknij nawias okrągły plus cudzysłów zamknij nawias okrągły dwukropek cudzysłów plus str otwórz nawias okrągły spakowane otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły zamknij nawias okrągły.
Linia 32. print otwórz nawias okrągły cudzysłów lewy ukośnik nWartosc spakowanych przedmiotow dwukropek cudzysłów przecinek wynik zamknij nawias okrągły.
Linia 34. nazwy znak równości otwórz nawias kwadratowy cudzysłów anemon cudzysłów przecinek cudzysłów bławatek cudzysłów przecinek cudzysłów chaber cudzysłów przecinek cudzysłów dziurawiec cudzysłów przecinek cudzysłów eustoma cudzysłów przecinek cudzysłów forsycja cudzysłów przecinek cudzysłów gipsówka cudzysłów zamknij nawias kwadratowy.
Linia 35. wartosci znak równości otwórz nawias kwadratowy 21 przecinek 15 przecinek 4 przecinek 4 przecinek 14 przecinek 1 przecinek 3 zamknij nawias kwadratowy.
Linia 36. wagi znak równości otwórz nawias kwadratowy 11 przecinek 8 przecinek 5 przecinek 4 przecinek 7 przecinek 1 przecinek 7 zamknij nawias kwadratowy.
Linia 37. n znak równości 7.
Linia 38. pojemnosc znak równości 41.
Linia 39. ogolnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły.
def sortuj(wartoscDoWagi, indeksy, n):
for i in range(n - 1):
for j in range(n - i - 1):
if wartoscDoWagi[j] < wartoscDoWagi[j + 1]:
wartoscDoWagi[j], wartoscDoWagi[j + 1] = wartoscDoWagi[j + 1], wartoscDoWagi[j]
indeksy[j], indeksy[j + 1] = indeksy[j + 1], indeksy[j]
def ogolnyPlecak(nazwy, wartosci, wagi, n , pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
wynik = 0
spakowane = []
for i in range(n):
spakowane.append(0)
for i in range(n):
indeks = indeksy[i]
while wagi[indeks] <= pojemnosc:
pojemnosc -= wagi[indeks]
wynik += wartosci[indeks]
spakowane[indeks] += 1
for i in range(n):
print("Liczba spakowanych sztuk przedmiotu " + nazwy[i] + " (indeks " + str(i) + "): " + str(spakowane[i]))
print("\nWartosc spakowanych przedmiotow:", wynik)
nazwy = ["anemon", "bławatek", "chaber", "dziurawiec", "eustoma", "forsycja", "gipsówka"]
wartosci = [21, 15, 4, 4, 14, 1, 3]
wagi = [11, 8, 5, 4, 7, 1, 7]
n = 7
pojemnosc = 41
ogolnyPlecak(nazwy, wartosci, wagi, n, pojemnosc)
Wynik działania programu:
Linia 1. Liczba spakowanych sztuk przedmiotu anemon otwórz nawias okrągły indeks 0 zamknij nawias okrągły dwukropek 0.
Linia 2. Liczba spakowanych sztuk przedmiotu bławatek otwórz nawias okrągły indeks 1 zamknij nawias okrągły dwukropek 0.
Linia 3. Liczba spakowanych sztuk przedmiotu chaber otwórz nawias okrągły indeks 2 zamknij nawias okrągły dwukropek 0.
Linia 4. Liczba spakowanych sztuk przedmiotu dziurawiec otwórz nawias okrągły indeks 3 zamknij nawias okrągły dwukropek 1.
Linia 5. Liczba spakowanych sztuk przedmiotu eustoma otwórz nawias okrągły indeks 4 zamknij nawias okrągły dwukropek 5.
Linia 6. Liczba spakowanych sztuk przedmiotu forsycja otwórz nawias okrągły indeks 5 zamknij nawias okrągły dwukropek 2.
Linia 7. Liczba spakowanych sztuk przedmiotu gipsówka otwórz nawias okrągły indeks 6 zamknij nawias okrągły dwukropek 0.
Linia 9. Wartosc spakowanych przedmiotow dwukropek 76.
Liczba spakowanych sztuk przedmiotu anemon (indeks 0): 0
Liczba spakowanych sztuk przedmiotu bławatek (indeks 1): 0
Liczba spakowanych sztuk przedmiotu chaber (indeks 2): 0
Liczba spakowanych sztuk przedmiotu dziurawiec (indeks 3): 1
Liczba spakowanych sztuk przedmiotu eustoma (indeks 4): 5
Liczba spakowanych sztuk przedmiotu forsycja (indeks 5): 2
Liczba spakowanych sztuk przedmiotu gipsówka (indeks 6): 0
Wartosc spakowanych przedmiotow: 76
Decyzyjny problem plecakowy
Specyfikacja problemu:
Dane:
nazwy – tablica liczb łańcuchów znaków; nazwy poszczególnych przedmiotów
wartosci – tablica liczb naturalnych; wartości poszczególnych przedmiotów
wagi – tablica liczb naturalnych; wagi poszczególnych przedmiotów
n – liczba naturalna; liczba rodzajów przedmiotów
pojemnosc – liczba naturalna; maksymalna pojemność plecaka
Wynik:
spakowane przedmioty, których całkowita waga nie przekracza wartości przechowywanej w zmiennej pojemnosc, a których całkowita wartość jest największa wśród możliwych wypełnień plecaka rzeczami o takiej wadze, która nie przekracza wartości zmiennej pojemnosc; pakujemy po jednej sztuce przedmiotu każdego rodzaju
całkowita wartość spakowanego plecaka
Zaprezentowane rozwiązania będziemy testować dla następujących danych:
maksymalna pojemność plecaka wynosi 21;
do dyspozycji mamy po jednej sztuce przedmiotu każdego rodzaju;
przedmioty mają następujące wartości oraz wagi:
Przedmiot –
0
1
2
3
4
5
6
Nazwa
aparat
baterie
czajnik
dmuchany materac
ekologiczny prysznic
filtr
garnuszek
Wartość
4
15
6
13
5
12
3
Waga
8
3
2
6
15
16
2
Pojemność plecaka to 21.
Już wiesz
Przypomnijmy, w jaki sposób działa algorytm, analizując podane dane.
Zaczniemy od obliczenia ilorazów wartości i wag: 4/8, 15/3, 6/2, 13/6, 5/15, 12/16, 3/2.
Dla każdego posortowanego przedmiotu sprawdzamy, czy można go spakować.
Wybieramy pierwszy przedmiot. To baterie, których waga to 3. Waga jest mniejsza od pojemności, zatem pakujemy je do plecaka. Pojemność plecaka po spakowaniu baterii wynosi 18.
Waga kolejnego przedmiotu (czajnika) wynosi 2, zatem można spakować ten przedmiot. Pojemność plecaka to 16.
Kolejnym przedmiotem jest dmuchany materac. Waga tego przedmiotu to 6. Jest mniejsza od pojemności plecaka, zatem przedmiot zostaje zapakowany. Pozostała pojemność plecaka wynosi 10.
Kolejny przedmiot, garnuszek, waży 2. Może zostać spakowany, a pojemność po jego spakowaniu wynosi 8.
Waga filtra, następnego przedmiotu, wynosi 16. Jest większa od tego, jaka jest pozostała pojemność plecaka, zatem nie można go spakować.
Aparat jest kolejnym przedmiotem, a jego waga wynosi 8. Może zostać spakowany do plecaka.
Wypełniliśmy tym samym całe miejsce w plecaku.
Obliczmy całkowitą wartość spakowanych przedmiotów:
baterie: 15
czajnik: 6
dmuchany materac: 13
garnuszek: 3
aparat: 4
Całkowita wartość spakowanych przedmiotów wynosi 41. Wykorzystaliśmy całe miejsce.
Decyzyjny problem plecakowy wymaga, by każdy przedmiot był dodawany do plecaka maksymalnie jeden raz. W programie wymaga to zmiany niewielkiej części programu.
Konieczne jest pominięcie pętli while w tym fragmencie i wykorzystanie instrukcji warunkowej if:
Linia 1. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 2. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 3. if wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości pojemnosc dwukropek.
Linia 4. pojemnosc minus znak równości wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 5. wynik plus znak równości wartosci otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 6. print otwórz nawias okrągły cudzysłów Spakowano przedmiot cudzysłów plus nazwy otwórz nawias kwadratowy indeks zamknij nawias kwadratowy plus cudzysłów otwórz nawias okrągły indeks cudzysłów plus str otwórz nawias okrągły indeks zamknij nawias okrągły plus cudzysłów zamknij nawias okrągły cudzysłów.
for i in range(n):
indeks = indeksy[i]
if wagi[indeks] <= pojemnosc:
pojemnosc -= wagi[indeks]
wynik += wartosci[indeks]
print("Spakowano przedmiot " + nazwy[indeks] + " (indeks " + str(indeks) + ")"
Zwróć uwagę, że w kodzie nie pojawia się również tablica spakowane, ponieważ w przypadku problemu decyzyjnego nie ma potrzeby liczenia, ile sztuk danego przedmiotu spakowano (do dyspozycji jest tylko jedna sztuka danego przedmiotu).
Oto kompletny kod programu:
Linia 1. def sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły dwukropek.
Linia 2. for i in range otwórz nawias okrągły n minus 1 zamknij nawias okrągły dwukropek.
Linia 3. for j in range otwórz nawias okrągły n minus i minus 1 zamknij nawias okrągły dwukropek.
Linia 4. if wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy dwukropek.
Linia 5. wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości wartoscDoWagi otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek wartoscDoWagi otwórz nawias kwadratowy j zamknij nawias kwadratowy.
Linia 6. indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy znak równości indeksy otwórz nawias kwadratowy j plus 1 zamknij nawias kwadratowy przecinek indeksy otwórz nawias kwadratowy j zamknij nawias kwadratowy.
Linia 8. def decyzyjnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły dwukropek.
Linia 9. wartoscDoWagi znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 10. indeksy znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 11. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 12. wartoscDoWagi kropka append otwórz nawias okrągły wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy prawy ukośnik wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły.
Linia 13. indeksy kropka append otwórz nawias okrągły i zamknij nawias okrągły.
Linia 15. sortuj otwórz nawias okrągły wartoscDoWagi przecinek indeksy przecinek n zamknij nawias okrągły.
Linia 17. wynik znak równości 0.
Linia 18. spakowane znak równości otwórz nawias kwadratowy zamknij nawias kwadratowy.
Linia 19. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 20. spakowane kropka append otwórz nawias okrągły 0 zamknij nawias okrągły.
Linia 22. for i in range otwórz nawias okrągły n zamknij nawias okrągły dwukropek.
Linia 23. indeks znak równości indeksy otwórz nawias kwadratowy i zamknij nawias kwadratowy.
Linia 24. if wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości pojemnosc dwukropek.
Linia 25. pojemnosc minus znak równości wagi otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 26. wynik plus znak równości wartosci otwórz nawias kwadratowy indeks zamknij nawias kwadratowy.
Linia 27. print otwórz nawias okrągły cudzysłów Spakowano przedmiot cudzysłów plus nazwy otwórz nawias kwadratowy indeks zamknij nawias kwadratowy plus cudzysłów otwórz nawias okrągły indeks cudzysłów plus str otwórz nawias okrągły indeks zamknij nawias okrągły plus cudzysłów zamknij nawias okrągły cudzysłów zamknij nawias okrągły.
Linia 29. print otwórz nawias okrągły cudzysłów lewy ukośnik nWartosc spakowanych przedmiotow dwukropek cudzysłów przecinek wynik zamknij nawias okrągły.
Linia 31. nazwy znak równości otwórz nawias kwadratowy cudzysłów aparat cudzysłów przecinek cudzysłów baterie cudzysłów przecinek cudzysłów czajnik cudzysłów przecinek cudzysłów dmuchany materac cudzysłów przecinek cudzysłów ekologiczny prysznic cudzysłów przecinek cudzysłów filtr cudzysłów przecinek cudzysłów garnuszek cudzysłów zamknij nawias kwadratowy.
Linia 32. wartosci znak równości otwórz nawias kwadratowy 4 przecinek 15 przecinek 6 przecinek 13 przecinek 5 przecinek 12 przecinek 3 zamknij nawias kwadratowy.
Linia 33. wagi znak równości otwórz nawias kwadratowy 8 przecinek 3 przecinek 2 przecinek 6 przecinek 15 przecinek 16 przecinek 2 zamknij nawias kwadratowy.
Linia 34. n znak równości 7.
Linia 35. pojemnosc znak równości 21.
Linia 36. decyzyjnyPlecak otwórz nawias okrągły nazwy przecinek wartosci przecinek wagi przecinek n przecinek pojemnosc zamknij nawias okrągły.
def sortuj(wartoscDoWagi, indeksy, n):
for i in range(n - 1):
for j in range(n - i - 1):
if wartoscDoWagi[j] < wartoscDoWagi[j + 1]:
wartoscDoWagi[j], wartoscDoWagi[j + 1] = wartoscDoWagi[j + 1], wartoscDoWagi[j]
indeksy[j], indeksy[j + 1] = indeksy[j + 1], indeksy[j]
def decyzyjnyPlecak(nazwy, wartosci, wagi, n, pojemnosc):
wartoscDoWagi = []
indeksy = []
for i in range(n):
wartoscDoWagi.append(wartosci[i] / wagi[i])
indeksy.append(i)
sortuj(wartoscDoWagi, indeksy, n)
wynik = 0
spakowane = []
for i in range(n):
spakowane.append(0)
for i in range(n):
indeks = indeksy[i]
if wagi[indeks] <= pojemnosc:
pojemnosc -= wagi[indeks]
wynik += wartosci[indeks]
print("Spakowano przedmiot " + nazwy[indeks] + " (indeks " + str(indeks) + ")")
print("\nWartosc spakowanych przedmiotow:", wynik)
nazwy = ["aparat", "baterie", "czajnik", "dmuchany materac", "ekologiczny prysznic", "filtr", "garnuszek"]
wartosci = [4, 15, 6,13, 5, 12, 3]
wagi = [8, 3, 2, 6, 15, 16, 2]
n = 7
pojemnosc = 21
decyzyjnyPlecak(nazwy, wartosci, wagi, n, pojemnosc)
algorytm wybierający na każdym kroku lokalnie najlepsze rozwiązanie, licząc, że doprowadzi to do globalnie optymalnegooptymalizacjaoptymalnego rozwiązania problemu
optymalizacja
optymalizacja
(od łac. optimus – najlepszy) poprawa wydajności algorytmu uzyskana dzięki zmniejszeniu liczby operacji niezbędnych do otrzymania wyniku