說明
假設有一個揹包的負重最多可達8公斤,而希望在揹包中裝入負重範圍內可得之總價物品,假設是水果好了,水果的編號、單價與重量如下所示:
0 |
李子 |
4KG |
NT$4500
|
1 |
蘋果 |
5KG |
NT$5700
|
2 |
橘子 |
2KG |
NT$2250
|
3 |
草莓 |
1KG |
NT$1100
|
4 |
甜瓜 |
6KG |
NT$6700
|
解法
揹包問題是關於最佳化的問題,要解最佳化問題可以使用“動態規劃”(Dynamic programming),從空集合開始,每增加一個元素就先求出該階段的最佳解,直到所有的元素加入至集合中,最後得到的就是最佳解。
以揹包問題爲例,我們使用兩個陣列value與item,value表示目前的最佳解所得之總價,item表示最後一個放至揹包的水果,假設有負重量 1~8的揹包8個,並對每個揹包求其最佳解。
逐步將水果放入揹包中,並求該階段的最佳解:
揹包負重 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
value |
0 |
0 |
0 |
4500 |
4500 |
4500 |
4500 |
9000 |
item |
- |
- |
- |
0 |
0 |
0 |
0 |
0 |
揹包負重 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
value |
0 |
0 |
0 |
4500 |
5700 |
5700 |
5700 |
9000 |
item |
- |
- |
- |
0 |
1 |
1 |
1 |
0 |
揹包負重 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
value |
0 |
2250 |
2250 |
4500 |
5700 |
6750 |
7950 |
9000 |
item |
- |
2 |
2 |
0 |
1 |
2 |
2 |
0 |
揹包負重 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
value |
1100 |
2250 |
3350 |
4500 |
5700 |
6800 |
7950 |
9050 |
item |
3 |
2 |
3 |
0 |
1 |
3 |
2 |
3 |
揹包負重 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
value |
1100 |
2250 |
3350 |
4500 |
5700 |
6800 |
7950 |
9050 |
item |
3 |
2 |
3 |
0 |
1 |
3 |
2 |
3 |
由最後一個表格,可以得知在揹包負重8公斤時,最多可以裝入9050元的水果,而最後一個裝入的水果是3號,也就是草莓,裝入了草莓,揹包只能再放入7公斤(8-1)的水果,所以必須看揹包負重7公斤時的最佳解,最後一個放入的是2號,也就是橘子,現在揹包剩下負重量5公斤(7-2),所以看負重5公斤的最佳解,最後放入的是1號,也就是蘋果,此時揹包負重量剩下0公斤(5-5),無法再放入水果,所以求出最佳解爲放入草莓、橘子與蘋果,而總價爲9050元。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e3;
int v, n;
int value[N],w[N];
int dp[N][N];
int main()
{
cin >> n >> v;
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
cin >>w[i] >>value[i];
for (int i = 1; i <= n; i++)
for (int j = v; j >= w[i]; j--)
dp[i][j] =max(dp[i-1][j], dp[i - 1][j - w[i]] + value[i]);
cout << dp[n][v] << endl;
return 0;
}