0/1 Hátizsák probléma megoldása dinamikus programozási példa segítségével

Mi a hátizsák probléma?

Hátizsák probléma Az algoritmus nagyon hasznos probléma a kombinatorikában. A szupermarketben n csomag van (n ≤ 100), az i csomag súlya W[i] ≤ 100, értéke V[i] ≤ 100. A tolvaj behatol a szupermarketbe, a tolvaj nem tud M-nél nagyobb súlyt (M ≤ 100) szállítani. ). Itt a megoldandó probléma: mely csomagokat viszi el a tolvaj, hogy a legmagasabb értéket kapja?

Bemenet:

  • Maximális tömeg M és a csomagok száma n.
  • W[i] súlytömb és a megfelelő V[i] érték.

output:

  • Maximalizálja az értéket és a megfelelő súlyt a kapacitásban.
  • Melyik csomagokat viszi el a tolvaj.

A hátizsák algoritmus további két típusra osztható:

  • A 0/1 hátizsák probléma dinamikus programozással. Ebben a hátizsák-algoritmustípusban minden csomag felvehető vagy nem. Emellett a tolvaj nem vehet el egy elvitt csomag töredékét, és nem vehet el többször egy csomagot. Ezt a típust dinamikus programozási megközelítéssel lehet megoldani.
  • Tört hátizsák probléma algoritmus. Ezt a típust a Greedy Strategy megoldhatja.

Hátizsákprobléma megoldása dinamikus programozással példával

Az oszd meg és uralkodj stratégiában a megoldandó problémát részproblémákra osztod. A részproblémákat tovább osztjuk kisebb részproblémákra. Ez a feladat addig folytatódik, amíg könnyen megoldható részproblémákat nem kap. Az ilyen felosztás során azonban sokszor találkozhat ugyanazzal a problémával.

A hátizsákos dinamikus programozás alapötlete, hogy egy táblázat segítségével tároljuk a megoldott részproblémák megoldásait. Ha ismételten szembesül egy részproblémával, csak a táblázatban szereplő megoldást kell átvennie anélkül, hogy újra meg kellene oldania. Ezért a dinamikus programozás által megtervezett algoritmusok nagyon hatékonyak.

Oldja meg a hátizsák problémáját dinamikus programozással

Egy probléma dinamikus programozással történő megoldásához a következő feladatokat kell végrehajtania:

  • Keressen megoldást a legkisebb részproblémákra.
  • Találja meg a képletet (vagy szabályt), amellyel a legkisebb részproblémák megoldásán keresztül is fel lehet építeni egy részprobléma megoldását.
  • Hozzon létre egy táblázatot, amely tárolja a részfeladatok megoldásait. Ezután számítsa ki a részfeladat megoldását a talált képlet alapján, és mentse el a táblázatba.
  • A megoldott részproblémák közül megtalálja az eredeti probléma megoldását.

Elemezze a 0/1 hátizsák problémát

A 0/1 hátizsák-probléma dinamikus programozással történő elemzésekor észrevehető pontokat találhat. A hátizsák-algoritmus értéke két tényezőtől függ:

  1. Hány csomagot mérlegelnek
  2. A hátralévő súly, amelyet a hátizsák tárolhat.

Ezért két változó mennyisége van.

A dinamikus programozással hasznos információkkal rendelkezik:

  1. a célfüggvény két változó mennyiségtől fog függni
  2. az opciók táblázata egy 2 dimenziós táblázat lesz.

Ha a B[i][j] hívása a maximális lehetséges érték, az {1, 2, …, i} csomagok kiválasztásával j súlykorlátozással.

  • A maximális érték, ha n csomagban van kiválasztva M súlykorlátozással, B[n][M]. Más szóval: Ha választható i csomagok, akkor B[i][j] az optimális súly, ha a hátizsák maximális súlya j.
  • Az optimális súly mindig kisebb vagy egyenlő, mint a maximális tömeg: B[i][j] ≤ j.

Például: B[4][10] = 8. Ez azt jelenti, hogy optimális esetben a kiválasztott csomagok össztömege 8, amikor 4 első csomag közül lehet választani (1-4 csomag) és a maximális súly A hátizsákból 10. Nem szükséges, hogy mind a 4 elem ki legyen jelölve.

Képlet a B[i][j] kiszámításához

Bemenet, Ön határozza meg:

  • W[i], V[i] viszont az i csomag súlya és értéke, amelyben i Képlet a B[i][j] kiszámításához{1, …, n}.
  • M a maximális súly, amelyet a hátizsák elbír.

Abban az esetben, ha egyszerűen csak 1 csomag közül választhat. Minden j-re kiszámítja a B[1][j]-t: ami azt jelenti, hogy a hátizsák maximális súlya ≥ az 1. csomag súlya

B[1][j] = W[1]

A j súlykorlátozás mellett az {1, 2, …, i – 1, i} csomagok közötti optimális választásnak a legnagyobb értékhez két lehetősége van:

  • Ha az i csomag nincs kiválasztva, a B[i][j] a maximálisan lehetséges érték az {1, 2, …, i – 1} csomagok közül kiválasztva j súlykorlátozással. Neked van:
B[i][j] = B[i – 1][j]
  • Ha az i csomagot választjuk (természetesen csak akkor vegyük ezt az esetet, ha W[i] ≤ j), akkor B[i][j] egyenlő az i csomag V[i] értékével, plusz a maximális érték a következők közül választható ki. csomagok {1, 2, …, i – 1} súlykorlátozással (j – W[i]). Vagyis az Ön értékét tekintve:
B[i][j] = V[i] + B[i – 1][j – W[i]]

A maximális lehetséges érték B[i][j] létrehozása miatt B[i][j] lesz a fenti 2 érték maximuma.

A dinamikus programozás alapjai

Tehát mérlegelnie kell, hogy jobb-e az i csomagot választani vagy sem. Innentől kezdve megkapja a következő rekurzív képletet:

B[i][j]= max(B[i – 1][j], V[i]+B[i – 1][j – W[i]]

Könnyen belátható, hogy B[0][j] = a lehetséges maximális érték, ha 0 csomag = 0 közül választ.

Számítsa ki az opciók táblázatát

A fenti rekurzív képlet alapján összeállít egy opciótáblázatot. Annak ellenőrzésére, hogy az eredmények helyesek-e (ha nem pontosan, építse újra a B[i][j] célfüggvényt). A B[i][j] célfüggvény és az opciók táblázatának létrehozásával orientálja a nyomkövetést.

A B opciók táblázata n + 1 sort, M + 1 oszlopot tartalmaz,

  • Először is a dinamikus programozás alapjaival töltve: a 0. sor minden nullát tartalmaz.
  • Rekurzív képletekkel, használja a 0-s sort az 1. sor kiszámításához, használja az 1-es sort a 2. sor kiszámításához stb. … amíg az összes sort ki nem számítja.
Számítsa ki az opciók táblázatát
Lehetőségek táblázata

Nyom

Az opciók táblázatának kiszámításakor a B[n][M] érdekli, ami a maximális érték, amelyet az M súlykorlátozású n csomagban történő kiválasztásnál kapunk.

  • If B[n][M] = B[n – 1][M] akkor az n csomag nincs kiválasztva, nyomon követed a B[n – 1][M]-t.
  • If B[n][M] ≠ B[n – 1][M], észreveszi, hogy az optimális kiválasztás az n csomaggal és a B[n – 1][M – W[n]] nyomvonallal rendelkezik.

Folytassa a nyomkövetést, amíg el nem éri a lehetőségek táblázatának 0. sorát.

Algoritmus az opciók táblázatában a kiválasztott csomagok megkereséséhez

Megjegyzés: Ha B[i][j] = B[i – 1][j], az i csomag nincs kiválasztva. B[n][W] a hátizsákba helyezett csomag optimális összértéke.

A nyomkövetés lépései:

  • 1 lépés: i = n-ből kiindulva, j = M.
  • 2 lépés: Nézze meg a j oszlopban alulról felfelé, megtalálja az i sort úgy, hogy B[i][j] > B[i – 1][j]. Jelölje ki a kiválasztott csomagot i: Válassza az [i] = igaz;
  • 3 lépés: j = B[i][j] – W[i]. Ha j > 0, folytassa a 2. lépéssel, ellenkező esetben folytassa a 4. lépéssel
  • 4 lépés: A kiválasztott csomagok nyomtatására vonatkozó lehetőségek táblázata alapján.

Java Kód

public void knapsackDyProg(int W[], int V[], int M, int n) {
	int B[][] = new int[n + 1][M + 1];
	
	for (int i=0; i<=n; i++)
		for (int j=0; j<=M; j++) {
			B[i][j] = 0;
		}
	
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= M; j++) {
			B[i][j] = B[i - 1][j];
			
			if ((j >= W[i-1]) && (B[i][j] < B[i - 1][j - W[i - 1]] + V[i - 1])) {
				B[i][j] = B[i - 1][j - W[i - 1]] + V[i - 1]; 
			}
			
			System.out.print(B[i][j] + " ");
		}
		System.out.print("\n");
	}
	
	System.out.println("Max Value:\t" + B[n][M]);
	
	System.out.println("Selected Packs: ");
	
	while (n != 0) {
		if (B[n][M] != B[n - 1][M]) {
			System.out.println("\tPackage " + n + " with W = " + W[n - 1] + " and Value = " + V[n - 1]);
			
			M = M - W[n-1];
		}
		
		n--;
	}
}
A knapsackDyProg() függvény be Java

A knapsackDyProg() függvény be Java

A hátizsák kód magyarázata:

  1. B[][] tábla létrehozása. Az egyes cellák alapértelmezett értéke 0.
  2. Építsd fel a B[][] táblázatot alulról felfelé haladva. Számítsa ki a lehetőségek táblázatát a visszakeresési képlettel!
  3. B[i][j] kiszámítása. Ha nem választja ki az i.
  4. Ezután értékelje: ha az i csomagot választja, az előnyösebb lesz, mint a B[i][j] visszaállítása.
  5. Kövesse nyomon a táblázatot az n sortól a 0 sorig.
  6. Ha az n. csomagot választja. Az n csomag kiválasztása után csak M – W[n – 1] súlyt adhat hozzá.


Ebben az oktatóanyagban két példa van. Íme a java kód a fenti program futtatásához, két példával:

public void run() {
	/*
	 * Pack and Weight - Value
	 */
	//int W[] = new int[]{3, 4, 5, 9, 4};
	int W[] = new int[]{12, 2, 1, 1, 4};
	
	//int V[] = new int[]{3, 4, 4, 10, 4};
	int V[] = new int[]{4, 2, 1, 2, 10};
	
	/*
	 * Max Weight
	 */
	//int M = 11;
	int M = 15;
	int n = V.length;
	
	/*
	 * Run the algorithm
	 */
	knapsackDyProg(W, V, M, n);
}

Megvan a kimenet:

  • Első példa:
0 0 0 3 3 3 3 3 3 3 3 3 
0 0 0 3 4 4 4 7 7 7 7 7 
0 0 0 3 4 4 4 7 7 8 8 8 
0 0 0 3 4 4 4 7 7 10 10 10 
0 0 0 3 4 4 4 7 8 10 10 11 
Max Value:	11
Selected Packs: 
	Package 5 with W = 4 and Value = 4
	Package 2 with W = 4 and Value = 4
	Package 1 with W = 3 and Value = 3
  • Második példa:
0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 4 
0 0 2 2 2 2 2 2 2 2 2 2 4 4 6 6 
0 1 2 3 3 3 3 3 3 3 3 3 4 5 6 7 
0 2 3 4 5 5 5 5 5 5 5 5 5 6 7 8 
0 2 3 4 10 12 13 14 15 15 15 15 15 15 15 15
Max Value:	15
Selected Packs: 
	Package 5 with W = 4 and Value = 10
	Package 4 with W = 1 and Value = 2
	Package 3 with W = 1 and Value = 1
	Package 2 with W = 2 and Value = 2