动态规划 01背包问题详解 及 定义动态数组

动态规划是以空间换时间,通过使用大量空间存储已经计算的数据,从而使后面的数据运算更加简便,因此在使用大量空间的弊端下,定义动态数组可以使空间不被浪费,所以在动态规划经典题目——01背包问题中,作者动态定义结构体数组,二维数组。

题目

                                                                                                                                 图片来自网上

一、动态生成结构体数组

与动态生成整型类似,结构体数组只不过将整型所需空间换成结构体所需要的空间(sizeof的不同),例:

struct object {
	int volume;
	int value;
};
    object *obj;
//	ob_num为输入值
	obj = (object *)calloc(ob_num + 1, sizeof(object));

calloc 与 malloc的不同在于 calloc 在开辟内存空间时已经将元素赋值为零,同时calloc格式与malloc略有不同(calloc括号中需要将数量与类型空间大小以逗号隔开,而malloc以*号相连)。

该结构体包含两个整型,volume表示体积,value表示价值,这样物体信息的结构体就定义好了。

二、动态定义二维数组

        一维数组的动态生成需要一个指针,可以想到,只需定义一个指针数组,就可以动态定义二维数组了。首先得动态生成指针数组,就需要用到一个指向指针的指针类型int **table,通过这个第二层的指针,就可以生成一个指针数组,如下

table = (int **)calloc(ob_num + 1, sizeof(int *));

其中,ob_num+1表示开辟的数目,sizeof(int *)表示单个数目所需的空间大小。

接着与一维数组类似,加个for循环即可:

	for (int i = 0; i < ob_num + 1; i++)
		table[i] = (int *)calloc((bagV + 1), sizeof(int));

动态定义讲完了,接下就到了动态规划时间。

二、动态规划原理——01背包

动态规划就是通过记录原来的数据,为接下来进行的数据计算服务。我们一般以数组的下标作为存储的的地址,在01背包中我们定义了一个二维数组存放每个状态下的最优解;

二维数组的构成:

横轴下标代表背包容量 且从0开始,因为在计算容量为一时,需要调用容量为零的最优解--就是0;

纵轴下标代表物品编号 从零开始但第0行表示物品体积0价值0,方便后面第一行的动态规划。

关键:

以下面数据为例

4(物品个数) 8(背包容量)

物品体积         物品价值

2                         3

3                         4

4                         5

5                         6 

以【3,6】为例,在此时判断 容量6减去编号为3的物体的体积4,然后在上一行找到对应的数据;

找到[2,6-4]=[2,2],这时的最优解是【2,2】的数据3,2+4=6(等于当列的体积),求出此时的总价值,3+5=8;大于上一行的最优解,存储下来。

ps:只能往上一行进行比较,因为与当行比较就会导致重复,所以应当与上一行对应位置比较。

代码如下:i表示背包容量,j表示编号;

	for (int i = 0; i <= bagV; i++)
		for (int j = 1; j <= ob_num; j++) {
			if (obj[j].volume > i)
				table[j][i] = table[j - 1][i];
			else if (table[j - 1][i - obj[j].volume] + obj[j].value > table[j - 1][i])
				table[j][i] = table[j - 1][i - obj[j].volume] + obj[j].value;
			else
				table[j][i] = table[j - 1][i];
		}

通过求出每个背包容量的最优解,在最后一行最后一列就是能装的最大价值;

完整代码

#include <stdio.h>
#include <stdlib.h>

struct object {
	int volume;
	int value;
};

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

int main() {

	int ob_num, bagV, ** table, res = 0, swap;
	struct object *obj;

	scanf("%d%d", &ob_num, &bagV);

	obj = (object *)calloc(ob_num + 1, sizeof(object));

	table = (int **)calloc(ob_num + 1, sizeof(int *));
	for (int i = 0; i < ob_num + 1; i++)
		table[i] = (int *)calloc((bagV + 1), sizeof(int));

	for (int i = 1; i < ob_num + 1; i++)
		scanf("%d%d", &obj[i].volume, &obj[i].value);

	for (int i = 0; i < ob_num + 1 - 1; i++)
		for (int j = 0; j < ob_num + 1 - i - 1; j++)
			if (obj[j].volume > obj[j + 1].volume) {
				swap = obj[j].volume;
				obj[j].volume = obj[j + 1].volume;
				obj[j + 1].volume = swap;

				swap = obj[j].value;
				obj[j].value = obj[j + 1].value;
				obj[j + 1].value = swap;
			}

	for (int i = 0; i <= bagV; i++)
		for (int j = 1; j <= ob_num; j++) {
			if (obj[j].volume > i)
				table[j][i] = table[j - 1][i];
			else if (table[j - 1][i - obj[j].volume] + obj[j].value > table[j - 1][i])
				table[j][i] = table[j - 1][i - obj[j].volume] + obj[j].value;
			else
				table[j][i] = table[j - 1][i];
		}

	for (int i = 0; i < ob_num + 1; i++) {
		for (int j = 0; j < bagV + 1; j++)
			printf("%d ", table[i][j]);
		printf("\n");
	}

	for (int i = 0; i < ob_num; i++)
		free(table[i]);
	free(table);
	return 0;
}

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊巴拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值