基礎揹包問題 - 多維有界揹包問題 - 深度優先搜索 (遞歸)
1. 基礎揹包問題
揹包問題 (Knapsack problem) 是一種組合優化的 NP 完全問題。給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價值最高。
如果限定每種物品只能選擇 0 個或 1 個,則問題稱爲 0-1 揹包問題 (0-1 knapsack problem) 。
如果限定物品 j
最多隻能選擇 maxj
個,則問題稱爲有界揹包問題 (bounded knapsack problem,BKP)。
如果不限定每種物品的數量,每種物品都就可以選擇任意多個,則問題稱爲無界揹包問題或完全揹包問題 (unbounded knapsack problem,UKP)。
2. 多維有界揹包問題 - 深度優先搜索 (遞歸)
現有 N
種 (N
<= 100) 物品,每種物品都有體積 ,重量 ,數量 ,價值 (、、 和 都爲整數)。限制體積最多 V
立方厘米 (V
<= 1000),重量最多 W
公斤 (W
<= 500)。如何選擇物品,使得揹包裝過的物品總價值最大。
物品 | 體積 | 重量 | 數量 | 價值 |
---|---|---|---|---|
編號 | 立方厘米 | 公斤 | 個 | 元 |
1 | 30 | 3 | 10 | 4 |
2 | 50 | 8 | 10 | 5 |
3 | 10 | 2 | 10 | 2 |
4 | 23 | 5 | 8 | 3 |
5 | 130 | 20 | 5 | 11 |
若 V
爲 500,W
爲 100,則選擇物品的最大價值爲 72 (72 = 10 * 4 + 10 * 2 + 4 * 3:由 10 件物品 1,10 件物品 3 和 4 件物品 4 組成)。這是一個多維且有界的揹包問題,屬於常規 0-1 揹包問題的擴展。
第一行測試用例個數。第二行,物品的種類 N
,揹包體積的限制 V
,揹包載重量的限制 W
。
接下來 N
行,每行爲該種物品i的體積 ,重量 ,數量 ,價值 (、、 和 都爲整數)。
72
選擇物品子集所能獲得的最大價值。
2
5 500 100
30 3 10 4
50 8 10 5
10 2 10 2
23 5 8 3
130 20 5 11
5 500 100
30 3 10 4
50 8 10 5
10 2 10 2
23 5 8 3
130 20 5 11
2.1 多維有界揹包問題 - 深度優先搜索 (遞歸)
/*
============================================================================
Name : yongqiang.cpp
Author : Yongqiang Cheng
Version : Version 1.0.0
Copyright : Copyright (c) 2020 Yongqiang Cheng
Description : Hello World in C++, Ansi-style
============================================================================
*/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <time.h>
using namespace std;
int computation = 0;
void dfs_v1(int map[100][4], int N, int V, int W, int sumvolume, int sumvalue, int sumweight, int *max_value, int goods_class)
{
if (sumvolume > V) {
computation++;
return;
}
if (sumweight > W) {
computation++;
return;
}
if ((sumvalue > *max_value))
{
*max_value = sumvalue;
}
if (goods_class >= N)
{
computation++;
return;
}
// volume - weight - number - value
// 選這類物品,然後選下一類
if (map[goods_class][2] > 0) {
map[goods_class][2] -= 1;
dfs_v1(map, N, V, W, sumvolume + map[goods_class][0], sumvalue + map[goods_class][3], sumweight + map[goods_class][1], max_value, goods_class + 1);
map[goods_class][2] += 1;
}
// 選這類物品,然後繼續選擇同類
if (map[goods_class][2] > 0) {
map[goods_class][2] -= 1;
dfs_v1(map, N, V, W, sumvolume + map[goods_class][0], sumvalue + map[goods_class][3], sumweight + map[goods_class][1], max_value, goods_class);
map[goods_class][2] += 1;
}
// 不選這類物品,然後選下一類
dfs_v1(map, N, V, W, sumvolume, sumvalue, sumweight, max_value, goods_class + 1);
return;
}
int inference(int map[100][4], int N, int V, int W)
{
int ret = 0;
int max_value = INT_MIN;
int goods_class = 0;
int sumvolume = 0;
int sumvalue = 0;
int sumweight = 0;
dfs_v1(map, N, V, W, sumvolume, sumvalue, sumweight, &max_value, goods_class);
ret = max_value;
return ret;
}
int main()
{
clock_t start = 0, end = 0;
double cpu_time_used = 0;
const char input_txt[] = "D:\\visual_studio_workspace\\yongqiangcheng\\yongqiangcheng\\input.txt";
const char output_txt[] = "D:\\visual_studio_workspace\\yongqiangcheng\\yongqiangcheng\\output.txt";
freopen(input_txt, "r", stdin);
// freopen(output_txt, "w", stdout);
start = clock();
printf("Start of the program, start = %ld\n", start);
printf("Start of the program, start = %ld\n\n", start);
int case_num;
cin >> case_num;
for (int i = 1; i <= case_num; i++)
{
int ret = 0;
int N = 0, V = 0, W = 0;
int map[100][4] = { 0 };
computation = 0;
cin >> N >> V >> W;
for (int h = 0; h < N; h++)
{
cin >> map[h][0] >> map[h][1] >> map[h][2] >> map[h][3]; // volume - weight - number - value
}
ret = inference(map, N, V, W);
cout << "computation " << i << " = " << computation << endl;
cout << "CASE #" << i << " = " << ret << endl;
}
end = clock();
printf("\nEnd of the program, end = %ld\n", end);
printf("End of the program, end = %ld\n", end);
cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Total time taken by CPU: %f\n", cpu_time_used);
printf("Exiting of the program...\n");
fclose(stdin);
// fclose(stdout);
return 0;
}
Start of the program, start = 0
Start of the program, start = 0
computation 1 = 245357
CASE #1 = 72
computation 2 = 245357
CASE #2 = 72
End of the program, end = 16
End of the program, end = 16
Total time taken by CPU: 0.016000
Exiting of the program...
請按任意鍵繼續. . .