1.
Legyen adott egy pixelből álló fekete-fehér kép. Szeretnénk a képen a bal felső saroktól a jobb alsó sarokig egy jobbra-lefele haladó határvonalat húzni úgy, hogy a vonaltól jobbra-felfele eső fekete, valamint a vonaltól balra-lefele eső fehér pixelek számának az összege a lehető legkisebb legyen. Oldjuk meg ezt a feladatot időben.
Megoldás:
Tároljuk egy mátrixban a részmegoldásokat, azaz legyen az pexeles képeknek a megoldása.
(Az pixeles képet a következőképp teároljuk: legyen image egy -es mátrix, melynek ott van -es értéke, ahol a képnek fekete pixele, és legyen image_flip egy -es mátrix, aminek ott van -es értéke, ahol a képnek fehér pixele. Mindenhol máshol van mindkét mátrixban.)
Az algoritmus induljon el az mátrix bal-felső sarkából és egy általános elemre hasonlítsa össze annak az értékét ha felülről jön a határvonal vagy ha balról jön a határvonal. Tehát és értékét kell valahogyan összehasonlítani.
Ekkor legyen
A szóban leírt summákat úgy tudjuk megvalósítani, hogy a képet egyesekkel és nullásokkal tároljuk, ahol jelöli a feketét és a fehér cellát. Ekkor az -edik sorban -től balra lévő fehér cellák száma:
mivel és .
A -edik oszlopban -től felfelé lévő fekete cellák száma:
Az algoritmus futásának végén tartalmazza az értékét az optimális határvonalnak, ha magát a határvonalat szeretnénk megadni, akkor minden cellában egy szám kettest fenntartunk, melynek az első eleme a határvonal értékét jelöli, a második eleme a hozzá tartozó határvonalnak őt megelőző elemét.
import numpy as np
def sol(image: np.ndarray) -> int:
for i in range(n):
for j in range(n):
A[i][j] = min(A[i-1][j] + np.sum(np.abs(image[i][:j]) - 1), A[i][j-1] + sum(image[:i][j-1]))
return A[-1][-1]
2.
Van egy érték bankónk, amit szeretnénk felváltani. A postán, ahol váltani szeretnénk, kifogyhatatlan mennyiségben vannak értékű pénzérmék. Adj idejű algoritmust, amely eldönti, hogy hányféleképpen tudják felváltani a bankónkat, ha a pénzérmék sorrendje nem számít! Például és lehetséges pénzérmék esetén -féle váltás van: .
Megoldás:
Tartsunk fenn egy tömböt, ahol azt jelöli, hogy értékű bankót hányféleképpen lehet felváltani.
A megoldást dinamikus programozással adjuk. Az tömbnek a nulladik elemét inicializáljuk -re, mert értékű bankót egy féleképpen tudunk felbontani.
Menjünk végig a pénzérméken iterátorral és minden pénzérmére menjünk végig tömbön iterátorral. Ha , akkor tudunk úgy váltani, hogy egy pénzérmét hozzáveszünk a értékű bankó váltásához. Tehát értékű bankót már féle képpen is tudjuk váltani.
A következő egy rövid python program, hogy érthetőbb legyen az algoritmus.
def exchange(n, coins):
A = [0] * (n + 1) # inicializalunk egy (n+1) hosszu csupa nulla tombot
A[0] = 1 # a nulladik elem inicializalva 1-re
for i in range(len(coins)):
for j in range(n+1):
if coins[i] <= j:
A[j] += A[j - coins[i]] # lenyeges lepes
return A[-1] # utolso elemet visszaadjuk
related: AlgTerv 1