III. P R O G R A M O W A N I E I A L G O R Y T M Y
metoda zachłanna
16. Automat wydaje, czyli jak dynamicznie wydawać resztę
N A TEJ LE K C JI:
• dowiesz się, na czym polega metoda zachłanna;
• użyjesz w programie zmiennych tablicowych.
W rzucając pieniądze do automatu z napojami, nie m usisz o dliczać dokładnej kwoty. Urządzenie sam o sumuje nominały, w ydaje towar i resztę. Jak kom puter w autom acie o blicza resztę? Czy algorytm jest skom plikow any? Opracujm y go w spólnie. Nie będzie to bardzo trudne.
16.1. Zachłannie, czyli wydajemy resztę z użyciem najmniejszej liczby nominałów
Przypom nij sobie, jak sprzedaw ca w sklepie w ydaje resztę. O czyw iście może to zrobić, używ ając dowolnych nominałów. Robi to na tyle racjonalnie, by w kasie nie zabrakło żadnego z nich.-Automat musi kierow ać się innymi kryteriam i. Nie tylko kwota musi się zgadzać, lecz także w ydaw anie m usi być optym alne, czyli z użyciem jak najm niejszej liczby wydawanych monet. Załóżm y, że ma zostać w ydana kwota 13 zł i 60 groszy z użyciem najmniejszej liczby monet (rys. 16.1.).
. r .
m
1 szt.
V . .... ____^
0 szt.
IW..________ 4 '
? 1 szt.
.. .... ..J
1 szt. ; 1 szt.
'h— _____ 4
2 szt.
— ...
Rys. 16.1. Optymalne wydanie reszty w kwocie 13,60 zł
Zastanów się teraz nad kwotami, które m ożna w ydaw ać za pom ocą zestawu m onet z rysunku 16.1. Je śli jest ich dostatecznie dużo, m ożesz w ydać dow olną kwotę pod warunkiem , że nie będzie ona zaw ierała pojedynczych groszy. Z tego wniosek, że dzięki odpow iednio dobranym w system ie m onetarnym nom ina
łom, m ożna złożyć dow olną kwotę.
W ydaw anie reszty (jak na rysunku 16.1.), czyli zaczynając od największej, m oż
liwej liczby najw yższych nominałów, nazyw am y m etodą zachłanną. Je śli prze
analizujesz tę metodę, zapew ne dojdziesz do wniosku, że nie sprawdzi się ona dla nietypowego zestaw u nominałów. Gdybyśm y chcieli kwotę 6 złotych w ydać za pom ocą monet dwu- i pięciozłotow ych, algorytm zachłanny w ydałby najpierw
110
m onetę pięciozłotow ą, bo jej w artość m ieści się w 6. Kasjerka w sklepie w yda
łaby trzy m onety dwuzłotowe. Ale ona nie stosuje algorytm u zachłannego.
Przystępując do opracow ania algorytm u w ydaw ania reszty m etodą zachłanną, musim y założyć, że do dyspozycji są w szystkie dostępne nom inały w odp o
wiedniej ilości. Dla uproszczenia w przykładzie w ykorzystam y jedynie nom inały 1, 2 i 5 złotych oraz założymy, że w ydajem y resztę niezaw ierającą groszy (rys.
16.2.). W przykładow ym algorytm ie użyto następujących zmiennych:
r e s z t a - zm ienna zaw ierająca kwotę do wydania. W trakcie procesu w ydaw a
nia zm ienia w artość na równą kwocie, która pozostała do wydania.
I i c z b a 5 , l i c z b a 2 , l i c z b a l to zm ienne, w których ostatecznie zosta
nie zapisana liczba poszczególnych nom inałów do wydania.
START
Rys. 16.2. Przykład algorytmu wydającego resztę metodą zachłanną dla reszty wyrażo
nej liczbą całkowitą
Algorytm nie w ym aga om ówienia. Zastanów się jednak, czy blok zaznaczony czerw oną ram ką jest konieczny do otrzym ania praw idłowego wyniku. Od tego m iejsca w artość zm iennej r e s z t a nie zm ienia się do końca działania algo
rytmu. Może w ięc być w yśw ietlona jako liczba w ydawanych złotówek, czyli
indeks O
III. P R O G R A M O W A N I E I A L G O R Y T M Y
zm ienna l i c z b a l staje się niepotrzebna. W łaśnie dokonaliśm y weryfikacji optym aln ości kodu programu.
M odyfikacja w iąże się także ze zm ianą w bloku w yjściow ym - jako liczbę w yda
wanych złotów ek należy w pisać w artość zm iennej reszta. Może ona m ieć w artość 0 dla parzystych kwot do w ydania lub 1 dla nieparzystych. Na tym przykładzie widać, że każdy algorytm powinien być w eryfikow any nie tylko pod kątem funkcjonalności (daje praw idłowe wyniki czy nie), lecz także pod kątem jego budow y i w ykorzystania zasobów komputera. W tym przypadku dodatkow a zm ienna spowoduje zarezerw ow anie w iększego obszaru pam ięci.
Program realizujący algorytm z rysunku 16.2. w ykorzystuje fakt, że zm ienna zadeklarow ana jako int przechow ująca w ynik dzielenia będzie zaw ierała jedynie jego czę ść całkow itą. Nie ma w ięc potrzeby korzystania z odpowiedniej funkcji ( d iv ) podającej w artość całkow itą liczby (rys. 16.3.).
1 #include <iostream>
2 #include <stdlib.h>
3
4 using namespace std;
5
6 int liczba5=0j liczba2=0, liczbal=0, reszta;
7-int main () 8 {
9 cout << "Podaj kwotę do wydania: ";
10 cin >> reszta;
11
12 liczba5=reszta/5;
13 reszta=reszta-liczba5*5;
14 liczba2=reszta/2;
15 reszta=reszta-liczba2*2;
16
17 cout << "do wydania" << endl;
18 cout << liczba5 <<" szt. pięciozłotówek" << endl;
19 cout << -liczba2 <<" szt. dwuzłotówek" << endl;
20 cout << reszta <<" szt. złotówek" << endl;
21 return 0;
22 }
Rys. 16.3. Program wydający resztę według przykładowego algorytmu zachłannego
Podaj kwotę do wydania: 23 do wydania
4 szt. pięciozłotówek 1 szt. dwuzłotówek 1 szt. złotówek
Podaj kwotę do wydania: 1 0 do wydania
2 szt. pięciozłotówek 0 szt. dwuzłotówek 0 szt. złotówek
Rys. 16.4. Wyniki działania programu wydającego resztę metodą zachłanną dla kwoty 23 złote i 10 złotych
112
Program (rys. 16.3.) będzie zaw sze w yśw ietlał liczbę w szystkich nominałów, nawet gdy nie będą używane do w ydania reszty (rys. 16.4.). Zm odyfikujm y algorytm i program.
Dzięki zastosow aniu badania w arunków można opu ścić drukow anie i o b li
czenia dla nom inałów w iększych od pozostałej do w ydania kwoty (rys. 16.5.).
W program ie ułożonym w edług tego algorytm u zastosow ano badanie w arunków za pom ocą instrukcji i f (rys. 16.6.).
START I
Wprowadź kwotę do wydania r e s z t a
lic z b a 5 = 0 ; lic z b a 2 = 0 ; li c z b a l = 0 ;
Drukuj
“pięciozłotówki”
liczba5“szt.”
t
l i c z b a 5 = r e s z t a / 5 r e s z t a = r e s z t a - l i c z b a 5 * 5
i
NIE
r e s z t a /2 > = 0
Drukuj
“dwuzłotówki”
liczba2“szt.”
t I
TAK li c z b a 2 = r e s z t a / 2 r e s z t a = r e s z t a - l ic z b a 2 * 2
Rys. 16.5. Inne rozwiązanie algorytmu dla metody zachłannej wydawania reszty
113
III. P R O G R A M O W A N I E I A L G O R Y T M Y
1 #include <iostream>
2 #include <stdlib.h>
3
4 using namespace std;
5
6 int liezba5=0, liczba2=0, liczbal=0, reszta;
7 int main () 8 {
9 cout << "Wprowadź kwotę do wydania: ";
10 cin >> reszta;
11 cout << endl;
12 if (reszta/5>=l) 13 {
14 liczba5=reszta/5;
15 reszta=reszta-liczba5*5;
16 cout << "pięciozłotówki - " << liczba5 << " szt."<< endl;
17 >
18
19 if (reszta/2>=l) 20
{
21 liczba2-reszta/2;
22 reszta=reszta-liczba2*2;
23 cout << "dwuzłotówki - " << liczba2 << " szt.” << endl;
24 >
25
26 if (reszta==l)
27 cout << "złotówki - 1 szt.";
28
29 return 0;
30 >
Rys. 16.6. Przykładowy program realizujący algorytm z rysunku 16.5.
Wprowadź kwotę do wydania: 11 pięciozłotówki - 2 szt.
złotówki - 1 szt.
Rys. 16.7. Wynik działania programu z rysunku 16.6
16.2. Nominały w tablicach, czyli jedna zmienna, wiele wartości
W obiegu znajdują się zarówno monety, jak i banknoty. Program kom puterowy może podpow iedzieć sprzedawcy, ile i jakich nom inałów ma użyć do wydania reszty. W Polsce w obiegu są następujące nom inały banknotów: 50 0 zł, 200 zł, 10 0 zł, 50 zł, 20 zł, 10 zł oraz monet: 5 zł, 2 zł, 1 zł, 50 gr, 20 gr, 10 gr, 5 gr, 2 gr i 1 gr. Jedynie banknotem pięćsetzłotow ym nie da się wydawać reszty. Gdyby dla w szystkich pozostałych 14 nom inałów budować algorytm podobny do tego z rysunku 16.3., należałoby rozbudować go o kolejnych 11 dzieleń lub warunków.
W y d a n ie 11 złotych m eto d ą zachłanną nie przew iduje dw u zło tó w ek.
Można jednak posłużyć się tablicam i, w których zostaną zapisane w szystkie nom inały i użyć bloku warunkowego (rys. 16.8.). Spowoduje to, że algorytm po odpow iednich zm ianach w tablicy n o m i n a ł y będzie w ydawał także resztę dla nom inałów używanych na przykład w Stanach Zjednoczonych, w których używa się m onety 25 centów, a nie ma m onet o nom inałach 2 i 20 centów.
- Przypomnienie --- O dśw ież swoją w iedzę na tem at zm iennych tablicow ych. Tablica jest zm ienną, która może przechow yw ać w iele w artości. Każda pozycja tablicy jest indeksow ana (od 0 do n), to oznacza, że ma swój numer. W zw iązku z tym podczas deklaracji należy podać jej rozmiar. W C++, jeśli podczas deklaracji tablicy zostanie ona w ypełniona danymi, podawanie rozmiaru nie jest konieczne. Podobnie jak inne zm ienne tablice m uszą m ieć nazwę i określony typ danych, jakie będą przechowywały.
Przykład:
i n t t a b l ic a [ ] = { 2 0 0 0 0 , 1 0 0 0 0 ,5 0 0 0 ,2 0 0 0 ,1 0 0 0 , 5 0 0 ,2 0 0 ,1 0 0 ,5 0 ,2 0 ,1 0 ,5 ,2 ,1 } ;
lub inaczej
i n t t a b l i c a [ 1 3 ] ;
W pierw szym przypadku tablica została w ypełniona 14 danymi. W dru
gim - ta sam a tablica musi być w ypełniana danymi w czasie realizacji pro
gramu. O czyw iście w obu przypadkach program może w pisyw ać do nich nowe w artości. W przykładzie t a b l i c a [0] będzie m iała w artość 2 0 0 0 0 , t a b l i c a [ 4 ] 10 00, a t a b l i c a [ 8 ] to 50. Ja k widać, indeks w skazuje bezpośrednio pozycję w tablicy.
Można zadeklarow ać tablice o większej liczbie wymiarów.
Zm ienne tablicow e są nazyw ane także m acierzam i.
W róćm y do naszego zadania. Algorytm (rys. 16.8.) w zasadniczej części nadal realizuje m etodę zachłanną w ydaw ania reszty. Tym razem jednak używa do tego w szystkich m ożliw ych nominałów. W przykładow ym algorytm ie o b li
czona liczba poszczególnych nom inałów jest drukowana tuż po obliczeniu i nie jest przechow yw ana.
Prześledźm y działanie algorytm u na przykładzie. Załóżmy, że kwota do w yda
nia to 4 0 ,10 zł. Taką też w artość zapiszm y pod zm ienną r e s z t a .
III. P R O G R A M O W A N I E I A L G O R Y T M Y
START
Wprowadź kwotę do wydania reszta
Rys. 16.8. Przykładowy algorytm wydawania reszty metodą zachłanną używający 14 nominałów
Tab. 16.1. Analiza działania algorytmu wydawania reszty metodą zachłanną dla kwoty 40,10 zł
1 Krok Działanie W artości
1. Wprowadzenie kwoty do wydania reszta = 40.10
2. Wypełnienie tablicy nominałami nominaly[13]={200,100, 50, 20,10, 5, 2 ,1 , 0.5, 0.2, 0.1, 0.05, 0.02, 0.01}
3. Indeks tablicy - zmienna i - ustawiony na pierw szej danej tablicy
i = 0
4. Czy reszta jest już wydana reszta=40.1 * 0
kierunek - NIE 5. Czy kwota do wydania zawiera w sobie przynaj
mniej jedną wartość nominału 200
nominaly[0]=200 40.1<nominaly[0]
kierunek - NIE 6. Indeks tablicy ustawia się na następny nominał i= 0+ l= l
7. Czy reszta jest już wydana reszta=40.1 * 0
kierunek - NIE Kroki 4, 5, 6, 7 są wykonywane do momentu, gdy i = 3
8. Reszta do wydania jest większa od 20 reszta>=nominaly[3]=20 kierunek TAK
9. Obliczanie liczby dwudziestozłotówek liczbanominalow=40.1/20=2 Nie ma części ułamkowej, ponieważ zmienna jest typu int
10. Obliczanie pozostałej kwoty po wydaniu 20 zł reszta=40,l-(20*2)=0.1 zł
11. Wydruk liczby dwudziestozłotówek Wydaj 2 x 20
12. Indeks następnego nominału i=3+l=4
13. Reszta jeszcze nie wydana reszta=0.1 * 0
kierunek - NIE Dla nominałów od 4 do 9 wartość warunku reszta>=nominaly[i] - NIE
14. i=10 0.1>=nominaly[10]=0.1
kierunek TAK
15. Obliczanie liczby dziesięciogroszówek liczbanominalow=0.1/0.1=l
16. Obliczanie pozostałej kwoty po wydaniu 2x20 zł i 10 gr
reszta=0.1-0.1*1= 0
17. Wydruk liczby dziesięciogroszówek Wydaj 1 x 0.1
18. Cała reszta wydana Warunek reszta=0 spełniony
Koniec obliczeń
• ’ ;c ] ) ł } r e t u r n b.
, , b ) , b - b . rej ig»p_arr*y. ;• + + ) { j”s s e _ c la s s - u s e _ a rra y (l
III. P R O G R A M O W A N I E I A L G O R Y T M Y
Realizacja algorytm u (rys. 16.8.) w języku C++ napotyka na pewne trudno
ści. Otóż czę ść nom inałów jest m niejsza od 1. Z tej przyczyny tablicę powinno się zadeklarow ać jako zm ienną typu f l o a t . Pozostała kwota do wydania (zm ienna reszta) także musi być liczbą rzeczyw istą. Gdy do w ydania zostaje 0,01 złotego, w artość zmiennej reszta powinna w yn osić 0,01. Niestety kom puter oblicza w artość zmiennej reszta z pewnym przybliżeniem , co spow o
duje błędny wynik dla kwot do w ydania o nieparzystej liczbie groszy. W pro
gram ie zastosujem y w ięc zaokrąglenie do setnych części złotego. W program ie (rys. 16.9.) została użyta funkcja round powodująca zaokrąglenie wyniku do . części całkowitej w sposób, który znasz z m atematyki, na przykład dla liczby 0,6 da w ynik 1, a dla 0,4 da 0. Jej użycie jest m ożliw e po dołączeniu biblio
teki math.h. Zaokrąglenie wyniku obliczan ia reszty pozostałej do w ydania do dw óch m iejsc po przecinku realizuje linia 20.
res z ta=round(( reszta- (nominały [i] *liczbanominalow)) *100)/100;
Tablica nom inałów będzie m iała postać:
float nomin a ł y[] = { 2 0 0 , 1 0 0 , 5 0 , 2 0 , 1 0 , 5 , 2 , 1 , 0 . 5 , 0 . 2 , 0 . 1 , 0 . 0 5 , 0 . 0 2 , 0 . 0 1 } Nie ma potrzeby podawania rozmiaru tablicy w [ ], skoro podczas deklaracji w pisujem y do niej konkretne dane.
1 #include <iostream>
2 #include <stdlib.h>
3#include <math.h>
4using namespace std;
5
6int łiczbanominalow, i=0;
7float nominały[]»{200,100,50,20,10,5,2,l,0.5,0.2,0.1,0.05,0.02,0.01}, reszta;
8
9*int main()
I© {
11 cout << "Podaj kwotę do wypłacenia:
12 cin >> reszta;
13
14 cout << endl << "wydaj następujące nominały:" << endl << endl;
15 while (reszta!*©) 16 {
17 if (reszta >= nominały[i]) 18 {
19 liczbanominalow=reszta/nominaly[i];
20 reszta=round((reszta-(nominały[i]*liczbanominałow))+100)/100;
2122 cout << nominały[i] << ” zł - " << liczbanominalow << " szt." << endl;
23 >
24 i-M-;
25 )
26 return 0;
27 >
Rys. 16.9. Przykładowy program wydający resztę metodą zachłanną korzystający z wszystkich nominałów
Podaj kwotę do wypłacenia: 444.31 wydaj następujące nominały:
200 zł - 2 szt.
20 zł - 2 szt.
2 zł - 2 szt.
0.2 zł - 1 szt.
0.1 zł - 1 szt.
0.01 zł - 1 szt.
Rys. 16.10. Wynik działania programu wydającego resztę metodą zachłanną wykorzy
stującego wszystkie nominały
ZA D A N IA DO RO ZW IĄZAN IA
1. Jak ą wartość m oże przybierać liczba wydawanych najniższych nominałów, np. 1 zł 1 gr? Uzasadnij swoją odpowiedź i podaj kilka przykładów.
2. Zmodyfikuj program z rysunku 16.3. w taki sposób, by wydawanie reszty realizowała funkcja.
Zdefiniuj ją. Efekt działania program u (wyświetlanie komunikatów) powinien pozostać bez zmian.
3. Automaty, w których można dokonać zakupów, operują najczęs'ciej nominałam i od 5 zł do 10 g ro szy. Zmodyfikuj algorytm i program wydawania reszty w taki sposób, by mógł być zastosowany w takich urządzeniach.
4. Zmodyfikuj program z rysunku 16.9. w taki sposób, by m ożna było w prowadzać kwotę reszty do wydania w złotówkach, np. 34,51 zł. Sprawdź, jak dokładność wykonywania obliczeń wpływa na działanie program u dla różnych kwot w tym 34,51 zł.
5. Zmodyfikuj program wydawania reszty z wykorzystaniem wszystkich dostępnych nom inałów w USA.
PO DSUM OW ANIE LEKCJI
• M etod a z a c h ła n n a zakłada wydawanie reszty nominałam i największymi z możliwych. M ożna opra- s. 110 cować wiele algorytmów wykorzystujących metodę zachłanną, w tym także uwzględniających różne
zakresy dostępnych nominałów.
• Z m ie n n e ta b lic o w e są zmiennymi, w których można przechowywać wiele wartości. W szystkie są s. H5 tego sam ego typu, deklarowanego podczas deklaracji tablicy. Jeśli podczas deklaracji zmiennej tablico
wej jednowymiarowej wypełnimy ją danymi, nie ma potrzeby podawania jej rozmiaru.
• Dane zapisane w zmiennej tablicowej są indeksowane numerem miejsca w tablicy. Dla tablicy jedno- S- H2 wymiarowej pierw sza ma in d e k s 0.
119