C语言实现--背包问题 算法(Knapsack Problem)

问题引入

        假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可得的相应总价物

品,假设物品是水果,水果的编号、单价与重量如下所示:

序号水果类型重量 /kg金额 /元
1

李子

44500
2

苹果

55700
3

橘子

22250
4

草莓

11100
5

甜瓜

66700

        请实现“如何最佳的选择物品”实现背包负重允许下装更多的物品?

问题分析

        背包问题是关于最佳化的问题,要解最佳化问题可以使用「动态规划」(Dynamic programming),从空集合开始,每增加一个元素就先求出该阶段的最佳解,直到所有的元素加 入至集合中,最后得到的就是最佳解。

        以背包问题为例,我们使用两个阵列value与item,value表示目前的最佳解所得之总价,item表 示最后一个放至背包的水果,假设有负重量 1~8的背包8个,并对每个背包求其最佳解。

逐步将水果放入背包中,并求该阶段的最佳解: 

放入李子

背包

1

2

3

4

5

6

7

8

负重

value

450

450

450

450

900

item

放入苹果

背包

1

2

3

4

5

6

7

8

负重

value

450

570

570

570

900

item

1

1

1

放入橘子

背包

1

2

3

4

5

6

7

8

负重

value

225

225

450

570

675

795

900

item

2

2

1

2

2

放入草莓

背包

1

2

3

4

5

6

7

8

负重

value

110

225

335

450

570

680

795

905

item

3

2

3

1

3

2

3

放入甜瓜

背包

1

2

3

4

5

6

7

8

负重

value

110

225

335

450

570

680

795

905

item

3

2

3

1

3

2

3

        由最后一个表格,可以得知在背包负重8公斤时,最多可以装入9050元的水果,而最后一个装入 的 水果是3号,也就是草莓,装入了草莓,背包只能再放入7公斤(8-1)的水果,所以必须看 背包负重7公斤时的最佳解,最后一个放入的是2号,也就 是橘子,现在背包剩下负重量5公斤(7-2),所 以看负重5公斤的最佳解,最后放入的是1号,也就是苹果,此时背包负重量剩下0公 斤(5-5), 无 法 再放入水果,所以求出最佳解为放入草莓、橘子与苹果,而总价为9050元。

代码实现

        说明:采用C语言,编译环境为DevC++。

#include <stdio.h>
#include <stdlib.h>
#define LIMIT 8//重量限制
#define N 5	//物品种类
#define MIN 1 //最小重量

struct body {
	char name[20]; int size;
	int price;
};
typedef struct body object;

int main() {
	int item[LIMIT+1] = {0}; 
	int value[LIMIT+1] = {0}; 
	int newvalue, i, s, p;
	object a[] = {{"李子", 4, 4500},
	{"苹果", 5, 5700},
	{"橘子", 2, 2250},
	{"草莓", 1, 1100},
	{"甜瓜", 6, 6700}};

	for(i = 0; i < N; i++){
		for(s = a[i].size; s <= LIMIT; s++){ 
			p = s - a[i].size;
			newvalue = value[p] + a[i].price;
			if(newvalue > value[s]){ // 找到阶段最佳解
				value[s] = newvalue; item[s] = i;
			}
		}
	}

	printf("物品\t价格\n");
	for(i = LIMIT; i >= MIN; i = i - a[item[i]].size){ 
		printf("%s\t%d\n",a[item[i]].name, a[item[i]].price);
	}

	printf("合计\t%d\n", value[LIMIT]);
	return 0;
}

运行结果

写在最后:

        读两遍下来,如果仍然有不清楚的地方,可在评论区留言。

        如果你有其他感到困惑的问题,欢迎留言。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

等日出看彩虹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值