基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)

基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)

1. 基础背包问题

N 件物品和一个承受最大重量为 W 的背包。第 i 件物品的重量是 w[i],价值是 v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

背包问题 (Knapsack problem) 是一种组合优化的 NP 完全问题。给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。

如果限定每种物品只能选择 0 个或 1 个,则问题称为 0-1 背包问题 (0-1 knapsack problem) 。
如果限定物品 j 最多只能选择 maxj 个,则问题称为有界背包问题 (bounded knapsack problem,BKP)。
如果不限定每种物品的数量,每种物品都就可以选择任意多个,则问题称为无界背包问题或完全背包问题 (unbounded knapsack problem,UKP)。

2. 0-1 背包问题

基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)_第1张图片

2.1 基本思路

最基础的背包问题,每种物品仅有一件,可以选择放或不放。利用递归针对每个物品是否放入背包进行两种情况下的搜索。0-1 背包问题在选第 i 个物品时,只有 2 种状态可选,放还是不放。

2    // 测试用例个数
4 5 // N = 4 物品的类别数,W = 5 背包承受的最大重量,最大价值 7
2 3 // w[0] = 2,v[0] = 3
1 2 // w[1] = 1,v[1] = 2
3 4 // w[2] = 3,v[2] = 4
2 2 // w[3] = 2,v[3] = 2
5 8 // N = 5 物品的类别数,W = 8 背包承受的最大重量,最大价值 10
3 4
5 5
1 2
2 1
2 3
2
4 5
2 3
1 2
3 4
2 2
5 8 
3 4
5 5
1 2
2 1
2 3

2.2 dfs_v1

算法遍历的组合数为 2 n 2^n 2n,计算复杂度大。

/*
============================================================================
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 
#include 

using namespace std;

int computation = 0;

void dfs_v1(int map[100][2], int N, int W, int sumweight, int sumvalue, int *max_value, int count, int book[100])
{
	if (count >= N)
	{
		computation++;

		if ((sumweight <= W) && (sumvalue > *max_value))
		{
			*max_value = sumvalue;
		}

		return;
	}

	if (0 == book[count])
	{
		int addvalue = 0, addweight = 0;

		// select
		addvalue = map[count][1];
		addweight = map[count][0];

		book[count] = 1;
		dfs_v1(map, N, W, sumweight + addweight, sumvalue + addvalue, max_value, count + 1, book);
		book[count] = 0;

		// unselect
		addvalue = 0;
		addweight = 0;

		book[count] = 1;
		dfs_v1(map, N, W, sumweight, sumvalue, max_value, count + 1, book);
		book[count] = 0;
	}

	return;
}

int inference(int map[100][2], int N, int W)
{
	int ret = 0;
	int max_value = INT_MIN;
	int count = 0;
	int sumweight = 0;
	int sumvalue = 0;
	int book[100] = { 0 };

	dfs_v1(map, N, W, sumweight, sumvalue, &max_value, count, book);

	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, W = 0;
		int map[100][2] = { 0 };

		computation = 0;

		cin >> N >> W;

		for (int h = 0; h < N; h++)
		{
			cin >> map[h][0] >> map[h][1]; // weight - value
		}

		ret = inference(map, N, 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 = 9
Start of the program, start = 9

computation 1 = 16
CASE #1 = 7
computation 2 = 32
CASE #2 = 10

End of the program, end = 15
End of the program, end = 15
Total time taken by CPU: 0.006000
Exiting of the program...
请按任意键继续. . .

基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)_第2张图片

2.3 dfs_v2

/*
============================================================================
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 
#include 

using namespace std;

int computation = 0;

void dfs_v2(int map[100][2], int N, int W, int sumweight, int sumvalue, int *max_value, int count, int book[100])
{
	if (sumweight > W)
	{
		return;
	}

	if (count >= N)
	{
		computation++;

		if (sumvalue > *max_value)
		{
			*max_value = sumvalue;
		}

		return;
	}

	if (0 == book[count])
	{
		int addvalue = 0, addweight = 0;

		// select
		addvalue = map[count][1];
		addweight = map[count][0];

		book[count] = 1;
		dfs_v2(map, N, W, sumweight + addweight, sumvalue + addvalue, max_value, count + 1, book);
		book[count] = 0;

		// unselect
		addvalue = 0;
		addweight = 0;

		book[count] = 1;
		dfs_v2(map, N, W, sumweight, sumvalue, max_value, count + 1, book);
		book[count] = 0;
	}

	return;
}

int inference(int map[100][2], int N, int W)
{
	int ret = 0;
	int max_value = INT_MIN;
	int count = 0;
	int sumweight = 0;
	int sumvalue = 0;
	int book[100] = { 0 };

	dfs_v2(map, N, W, sumweight, sumvalue, &max_value, count, book);

	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, W = 0;
		int map[100][2] = { 0 };

		computation = 0;

		cin >> N >> W;

		for (int h = 0; h < N; h++)
		{
			cin >> map[h][0] >> map[h][1]; // weight - value
		}

		ret = inference(map, N, 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 = 8
Start of the program, start = 8

computation 1 = 12
CASE #1 = 7
computation 2 = 23
CASE #2 = 10

End of the program, end = 12
End of the program, end = 12
Total time taken by CPU: 0.004000
Exiting of the program...
请按任意键继续. . .

基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)_第3张图片

2.4 dfs_v3

/*
============================================================================
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 
#include 

using namespace std;

int computation = 0;

void dfs_v3(int map[100][2], int N, int W, int sumweight, int sumvalue, int *max_value, int count, int book[100])
{
	if (sumweight > W)
	{
		return;
	}

	if (count >= N)
	{
		computation++;

		if (sumvalue > *max_value)
		{
			*max_value = sumvalue;
		}

		return;
	}

	if (0 == book[count])
	{
		int addvalue = 0, addweight = 0;

		// select
		addvalue = map[count][1];
		addweight = map[count][0];

		if ((sumweight + addweight) <= W)
		{
			book[count] = 1;
			dfs_v3(map, N, W, sumweight + addweight, sumvalue + addvalue, max_value, count + 1, book);
			book[count] = 0;
		}

		// unselect
		addvalue = 0;
		addweight = 0;

		book[count] = 1;
		dfs_v3(map, N, W, sumweight, sumvalue, max_value, count + 1, book);
		book[count] = 0;
	}

	return;
}

int inference(int map[100][2], int N, int W)
{
	int ret = 0;
	int max_value = INT_MIN;
	int count = 0;
	int sumweight = 0;
	int sumvalue = 0;
	int book[100] = { 0 };

	dfs_v3(map, N, W, sumweight, sumvalue, &max_value, count, book);

	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, W = 0;
		int map[100][2] = { 0 };

		computation = 0;

		cin >> N >> W;

		for (int h = 0; h < N; h++)
		{
			cin >> map[h][0] >> map[h][1]; // weight - value
		}

		ret = inference(map, N, 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 = 9
Start of the program, start = 9

computation 1 = 12
CASE #1 = 7
computation 2 = 23
CASE #2 = 10

End of the program, end = 12
End of the program, end = 12
Total time taken by CPU: 0.003000
Exiting of the program...
请按任意键继续. . .

基础背包问题 - 0-1 背包问题 - 深度优先搜索 (递归)_第4张图片

你可能感兴趣的:(C++)