Oryginalny problem wydawania reszty to problem w którym musimy wydać daną kwotę minimalną ilością monet/ banknotów zakładając, że mamy nieskończoną ilość egzemplarzy monet/ banknotów każdego nominału. Są dwie wersje problemu: jedna w której mamy obliczyć tylko ile minimalnie musimy użyć monet i banknotów (ta wersja mnie nie interesuje) i druga w której oprócz tego musimy znaleźć kombinację monet i banknotów o minimalnej ilości która realizuje wypłatę.
Zakładając, że kwota do wydania to kwota
, a nominały są zawarte w tablicy nominały
, udało mi się stworzyć algorytm, będący lekką modyfikacją algorytmu z Wiki, który liczy rozwiązanie w czasie O(kwota
* nominały
.length) i używa, jak mi się wydaje po paru krótkich próbach, O(nominały
.length) pamięci.
Algorytm jest tutaj: http://ideone.com/d6suB
Czy ktoś może potwierdzić, że ten algorytm rzeczywiście potrzebuje tylko O(nominały
.length) pamięci? A może gdzieś na necie już jest rozwiązanie o interesującej mnie złożoności.
Algorytm wykorzystuje niemutowalne listy jednokierunkowe. Dzięki temu mogę utworzyć nową listę z listy o dowolnej długości i nowego elementu w czasie stałym i używając stałą ilość dodatkowej pamięci. Usuwaniem węzłów, które przestają być osiągalne zajmuje się oczywiście odśmiecacz wbudowany w maszynę wirtualną.
Docelowo chciałbym mieć bardziej rozbudowany algorytm. Otóz w moim problemie każdy nominał ma ograniczoną liczbę egzemplarzy. Ponadto chciałbym nadać priorytety konkretnym monetom i banknotom (nie konkretnym nominałom, a konkretnym monetom czy banknotom!). Priorytety są po to, żeby zapobiegać jak tylko się da wypłacaniu danego nominału poniżej limitu ostrzegawczego - czyli docelowo po to, abym zminimalizował ryzyko, że nie bedę mógł komuś wypłacić pieniędzy. Wobec tego, moim pomysłem jest zrobienie tylu kroków ile jest konkretnie wszystkich monet i banknotów, a nie tylu kroków ile jest dostępnych nominałów.
Zakładając najprostszy wariant rozwiązania, czyli utworzenie całej macierzy takiej jak pokazana na Wiki zjadłoby sporą ilość pamięci. Jednostką w której liczę pieniądze jest grosz, a monet i banknotów może być w sumie kilkaset. Zakładając wypłatę 500 zł, czyli 50 000 groszy i 500 monet i banknotów razem oraz mając 8 bajtów na każdy element macierzy dostaję zajętość pamięci równą: 50 000 * 500 * 8 B = 200 MB Chociaż w sumie to może i nie tak znowu dużo.
Macie jakieś ciekawe pomysły jak to rozwiązać?