0-1揹包問題


揹包問題是一種求最優解的問題,我們可以使用動態規劃(DP)和回溯法來解決這類問題


參考文獻:

[1] 最通俗易懂的01揹包問題講解


動態規劃

動態規劃Dynamic programmingDP)是一種在數學計算機科學經濟學中使用的,通過把原問題分解爲相對簡單的子問題的方式求解複雜問題的方法。 動態規劃常常適用於有重疊子問題最優子結構性質的問題。

動態規劃在查找有很多重疊子問題的情況的最優解時有效。它將問題重新組合成子問題。爲了避免多次解決這些子問題,它們的結果都逐漸被計算並被保存,從簡單的問題直到整個問題都被解決。因此,動態規劃保存遞歸時的結果,因而不會在解決同樣的問題時花費時間。

動態規劃只能應用於有最優子結構的問題。最優子結構的意思是局部最優解能決定全局最優解(對有些問題這個要求並不能完全滿足,故有時需要引入一定的近似)。簡單地說,問題能夠分解成子問題來解決。

問題描述:

有一個能裝12kg(capacity)的揹包,準備買6件(typeTotal)物品,各自的重量(kg)和價值分別爲:

0     0

1     2

3     5

2     3

6     10

2      4

對於一件物品,只存在裝(1)和 不裝(0)兩種狀態,不能裝一部分或者一件物品拿走多次,求問他能拿走的最高價值是多少?

問題分析:

f[i,j]表示在前i0\leq i\leq typeTotal)個物品中能夠裝入容量爲j0\leq j\leq capacity)的揹包的物品的最大價值,則可以得到如下的動態規劃函數:

f[i,j] = 0 \left ( i == 0 || j == 0\right )

f[i,j] = f[i-1,j],j < weight[i] ①

f[i,j] = max\left \{ f[i-1,j], f[i-1,j-weight[i]]+Val[i] \right \} , j>weight[i] ②  ②

式表明:如果第i個物品的重量大於揹包的容量,則裝人前i個物品得到的最大價值和裝入前i-1個物品得到的最大價是相同的,即物品i不能裝入揹包; 

式表明:如果第i個物品的重量小於揹包的容量,則會有一下兩種情況:  

  • 如果把第i個物品裝入揹包,則揹包物品的價值等於第i-1個物品裝入容量位j-wi的揹包中的價值加上第i個物品的價值vi;;
  • 如果第i個物品沒有裝入揹包,則揹包中物品價值就等於把前i-1個物品裝入容量爲j的揹包中所取得的價值。顯然,取二者中價值最大的作爲把前i個物品裝入容量爲j的揹包中的最優解。

C代碼實現:

#include "stdio.h"
#include "stdlib.h"

/* 0-1 揹包問題 */
#define len 100
int main()
{
    int capacity;
    int optimumSol[len+1][len+1];
    int weight[len];
    int val[len];
    int typeTotal;
    scanf("%d %d", &capacity, &typeTotal);
    for (int i = 1; i <= typeTotal; i++) {
        scanf("%d %d", &weight[i], &val[i]);
    }
    memset(optimumSol, 0, sizeof(optimumSol)/sizeof(int));
    int i, j;
    for (i = 1; i <= typeTotal; i++) {
        for (j = 0; j <= capacity; j++) {
            if (j < weight[i]) {
                //由i-1 >= 0 => i >= 1
                optimumSol[i][j] = optimumSol[i-1][j];
            } else {
                optimumSol[i][j] = optimumSol[i-1][j] > optimumSol[i-1][j-weight[i]] + val[i] ? 
                optimumSol[i-1][j] : optimumSol[i-1][j-weight[i]] + val[i];
            }
            printf("%d--%d--%d\n", i, j, optimumSol[i][j]);
        }
        
    }
    printf("optimumSol = %d\n", optimumSol[typeTotal][capacity]);

    return 0;
}

è¿éåå¾çæè¿°

ubuntu@VM-0-4-ubuntu:~/codeForTest$ ./ans 
12 6 
0 0
1 2
3 5
2 3
6 10
2 4
1--0--0
1--1--0
1--2--0
1--3--0
1--4--0
1--5--0
1--6--0
1--7--0
1--8--0
1--9--0
1--10--0
1--11--0
1--12--0
2--0--0
2--1--2
2--2--2
2--3--2
2--4--2
2--5--2
2--6--2
2--7--2
2--8--2
2--9--2
2--10--2
2--11--2
2--12--2
3--0--0
3--1--2
3--2--2
3--3--5
3--4--7
3--5--7
3--6--7
3--7--7
3--8--7
3--9--7
3--10--7
3--11--7
3--12--7
4--0--0
4--1--2
4--2--3
4--3--5
4--4--7
4--5--8
4--6--10
4--7--10
4--8--10
4--9--10
4--10--10
4--11--10
4--12--10
5--0--0
5--1--2
5--2--3
5--3--5
5--4--7
5--5--8
5--6--10
5--7--12
5--8--13
5--9--15
5--10--17
5--11--18
5--12--20
6--0--0
6--1--2
6--2--4
6--3--6
6--4--7
6--5--9
6--6--11
6--7--12
6--8--14
6--9--16
6--10--17
6--11--19
6--12--21

運行結果ok。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章