0-1背包(动态规划 & 贪心算法)

题目描述

        如果 背包重量为9,现在有3个物品,其重量、价值、和性价比分别为

        1:(3,4,4/3)   2:(4,5,5/4)  3:(5,6,6/5)

        求解背包能够装入的最大价值。

算法说明

        贪心算法不一定能够得出 0-1 背包的最优解

        动态规划可以得出 0-1 背包的最优解

代码实现

#include <iostream>
using namespace std;

int max(int a, int b) {
	return a > b ? a : b;
}

// 对商品按照性价比排序
void Quick_sort_value(int weight[], int value[], double w_v[], int left, int right) {
	if (left < right) {
		int i = left;
		int j = right;
		double x = w_v[i];
		int x_w = weight[i];
		int x_v = value[i];
		while (i < j) {
			while (i<j && w_v[j] < x)
			{
				j--;
			}
			if (i < j) {
				w_v[i] = w_v[j];
				weight[i] = weight[j];
				value[i++] = weight[j];
			}
			while (i < j && w_v[i] > x)
			{
				i++;
			}
			if (i < j) {
				w_v[j] = w_v[i];
				weight[j] = weight[i];
				value[j--] = weight[i];
			}
		}
		if (i == j) {
			w_v[i] = x;
			weight[i] = x_w;
			value[i] = x_v;
		}
		Quick_sort_value(weight, value, w_v, left, i - 1);
		Quick_sort_value(weight, value, w_v, i + 1, right);
	}
}

/*
* 贪心算法只适合求解小数背包问题,即可以将物品分割的背包问题。
*	例子:如背包重量为9,现在有3个物品,其重量、价值、和性价比分别为
*	1:(3,4,4/3)   2:(4,5,5/4)  3:(5,6,6/5)
*	可以将物品分割成部分。
*/
double greed_Value_decimal(int weight[], int value[],double w_v[], int left, int right,int bagweight) {
	// 根据性价比对物品排序。
	Quick_sort_value(weight, value, w_v, left, right);

	int sum_weight = 0;
	double sum_value = 0;
	for (int i = left; i <= right; i++) {
		sum_weight += weight[i];
		if (sum_weight <= bagweight) {
			sum_value += value[i];
		}
		else {
			double v = (w_v[i]) * (bagweight - sum_weight + weight[i]);
			sum_value = v + sum_value;
			break;
		}
	}
	return sum_value;
}


/*
*  贪心算法求解0-1背包问题时,不一定得出最优解。
* 
*  例子:如背包重量为9,现在有3个物品,其重量、价值、和性价比分别为
* 1:(3,4,4/3)   2:(4,5,5/4)  3:(5,6,6/5)
*/

int greed_Value(int weight[], int value[], double w_v[], int left, int right, int bagweight) {
	// 根据性价比对物品排序。
	//Quick_sort_value(weight, value, w_v, left, right);

	int sum_weight = 0;
	int sum_value = 0;
	for (int i = left; i <= right; i++) {
		sum_weight += weight[i];
		if (sum_weight <= bagweight) {
			sum_value += value[i];
		}
		else {
			break;
		}
	}
	return sum_value;
}

/*
*  动态规划算法求解0-1背包问题时,可以得出最优解。
*
*  例子:如背包重量为9,现在有3个物品,其重量、价值、和性价比分别为
* 1:(3,4,4/3)   2:(4,5,5/4)  3:(5,6,6/5)
*/

int dynamic_planning(int weight[], int value[], int n, int bagweight) {
	int* dp = new int[bagweight + 1];

	// 初始化dp数组
	for (int j = 0; j <= bagweight; j++) {
		if (weight[0] < j) {
			dp[j] = value[0];
		}
		else {
			dp[j] = 0;
		}
	}
	// 动态规划找最大价值
	for (int i = 1; i < n; i++) {
		for (int j = bagweight; j >= 0; j--) {
			dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
		}
	}
	return dp[bagweight];
}

int main()
{
	int weight[] = { 3,4,5 };
	int value[] = { 4, 5, 6 };
	double w_v[] = { (double)4 / 3, (double)5 / 4 ,(double) 6 / 5 };
	int bagweight = 9;

	// 贪心算法求解小数背包为题
	double maxvalue = greed_Value_decimal(weight, value, w_v, 0, 2, bagweight);
	cout.precision(6);
	cout << "贪心算法求解小数背包: " << maxvalue << endl << endl;

	// 贪心算法求解 0-1 背包为题
	maxvalue = greed_Value(weight, value, w_v, 0, 2, bagweight);
	cout << "贪心算法求解 0-1 背包: " << maxvalue << endl << endl;

	// 动态规划求解 0-1 背包为题
	maxvalue = dynamic_planning(weight, value, 3, bagweight);
	cout << "动态规划求解 0-1 背包: " << maxvalue << endl << endl;

	return 0;
}

程序运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值