C语言:背包问题(动态规划)

// 背包问题:
// 现有四个物品,背包总量为8,背包最多能装入价值为多少的物品?
// i 物品编号:1  2  3  4 
// w 体积    :2  3  4  5 
// v 价值    :3  4  5  6
#include
#include

int volume[5] = { 0,2,3,4,5 };	// 物品体积
int value[5] = { 0,3,4,5,6 };	// 物品价值
int dp[5][9] = { 0 };			// 动态规划矩阵横坐标为背包容量,纵坐标为物品编号
int object[5] = { 0 };			// 若i物品有装入背包,则object[i]修改为1

// 返回两个值中的的最大值
int max(int a, int b)
{
	if (a > b)
		return a;
	return b;
}

// 动态规划找到背包所能装下的最大价值
void Dynamic()
{
	// 由物品1至4,背包容量由0至8依次考虑
	for (int i = 1; i < 5; i++)
	{
		for (int j = 1; j < 9; j++)
		{
			if (volume[i] > j)
			{
				// 若容量为j的背包本身就装不下第i个物品,则不考虑装入物品i的情况
				// 因此考虑i物品与不考虑i物品的最优值相同
				dp[i][j] = dp[i - 1][j];
			}
			else
			{
				// 若容量为j的背包可以装下第i个物品
				// 则比较i物品不装入背包dp[i - 1][j],与i物品装入背包dp[i - 1][j - volume[i]] + value[i]两种情况
				// 应注意的是,将i物品装入背包时,需预留出i物品的体积volume[i],再考虑体积为j - volume[i],
				// 考虑前i - 1个物品的情况下的最优值,最后再加上i的价值
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - volume[i]] + value[i]);
			}
		}
	}
}

// 回溯找回装了哪些物品
// 从dp[4][8]开始回溯
void Find(int i, int j)
{
	if (i == 0)
		return;
	if (dp[i][j] == dp[i - 1][j]) // 这说明物品i没有被装入背包
	{
		object[i] = 0;
		Find(i - 1, j);	// 递归寻找背包剩余容量为j时,物品i - 1是否被装入背包
	}
	else if (dp[i][j] == dp[i - 1][j - volume[i]] + value[i]) // 这说明物品i有被装入背包
	{
		object[i] = 1;
		Find(i - 1, j - volume[i]); // 递归寻找在背包剩余容量为j - volume[i]时,
									// 物品i - 1是否被装入背包
	}
}

int main()
{
	Dynamic();
    // 从dp[4][8]开始回溯
	Find(4, 8);

	// 打印dp矩阵,横坐标为背包容量,纵坐标为物品编号
	printf("dp矩阵如下:\n");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			printf("%d ", dp[i][j]);
		}
		printf("\n");
	}
	printf("\n");
	// 打印object矩阵
	printf("object矩阵如下:\n");
	for (int i = 1; i < 5; i++)
	{
		printf("%d ", object[i]);
	}
	return 0;
}

 输出结果如下:

C语言:背包问题(动态规划)_第1张图片

你可能感兴趣的:(c语言,算法)