基礎揹包問題 - 多維有界揹包問題 - 深度優先搜索 (遞歸)

基礎揹包問題 - 多維有界揹包問題 - 深度優先搜索 (遞歸)

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) 物品,每種物品都有體積 viv_i,重量 wiw_i,數量 cic_i,價值 tit_i (viv_iwiw_icic_itit_i 都爲整數)。限制體積最多 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的體積 viv_i,重量 wiw_i,數量 cic_i,價值 tit_i (viv_iwiw_icic_itit_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...
請按任意鍵繼續. . .

在這裏插入圖片描述

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