0-1背包问题--使用动态规划策略

题目(Description):

0-1背包问题是给定n个重量为 {w1, w2, … ,wn}、价值为 {v1, v2, … ,vn} 的物品和一个容量为 C 的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。

要求:用动态规划法求0/1背包问题的最优解。

输入(Input):

(1)物品的总个数;

(2)背包的总容量;

(3)每个物品的重量;

(4)每个物品的价值。

输出(Output):

(1)最优解;

(2)背包中物品的最大价值。

示例(Sample):

输入(Input):

4

10

7 3 4 5

42 12 40 25

输出(Output):

(0,0,1,1)

65

分析

这是约束优化问题,可以看成一个决策过程 ( x 1 , x 2 , ⋯   , x n ) \left(x_1,x_2,\cdots,x_n\right) (x1,x2,,xn),其中 x i ∈ { 0 , 1 } x_i\in\{0,1\} xi{0,1}。也就是说问题被分解成n步决策,每一步决策只依赖于上一步决策的结果。对 ∀ x i ∈ ( x 1 , x 2 , ⋯   , x n ) \forall x_i\in\left(x_1,x_2,\cdots,x_n\right) xi(x1,x2,,xn)的决策,都是在 ( x 1 , x 2 , ⋯   , x i − 1 ) \left(x_1,x_2,\cdots,x_{i-1}\right) (x1,x2,,xi1)已经完成决策的情况下进行的。在对 x i − 1 x_{i-1} xi1决策之后,在决策x_i时,问题处于下列两种状态之一:
1.背包容量不足以装入物品 i i i x i = 0 x_i=0 xi=0,背包价值不变;
2.背包容量允许装入物品 i i i x i = 1 x_i=1 xi=1,背包价值增加 v i v_i vi
这两种情况下背包价值的最大者应该是对 x i x_i xi决策后的价值。

举个例子:
在这里插入图片描述
构造动态规划表格
在这里插入图片描述

编程实现

#include <iostream>
using namespace std;

int KnapSack(int n, int C,int w[], int v[]) {
	int i,j;
	int V[20][200];
	for(i=0; i<=n; i++)
		V[i][0]=0;
	for(j=0; j<=C; j++)
		V[0][j]=0;
	for(i=1; i<=n; i++) {
		for(j=1;j<=C;j++)
			if(j<w[i])
				V[i][j] = V[i-1][j];
			else {
				//V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]);
				if (V[i-1][j]<V[i-1][j-w[i]]+v[i])
					V[i][j] = V[i-1][j-w[i]]+v[i];
				else
					V[i][j] = V[i-1][j];
			}	
		cout << endl;
	}
	
	//打印动态规划表
//	for(i=0; i<=n; i++) {
//		for(j=0; j<=C; j++){
//			cout << V[i][j] << "\t"; 
//		}
//		cout << endl;
//	} 
	
	
	// 回溯寻求解向量 
	j=C;
	int x[10];
	for(i=n; i>0; i--) {
		if(V[i][j]>V[i-1][j]) {
			x[i]=1;
			j=j-w[i];
		}
		else x[i]=0;
	}
	cout << "(";
	for(i=1; i<n; i++) {
		cout << x[i] << ","; 
	}
	cout << x[n] << ")\n" << V[n][C] << endl;
	
	return V[n][C];
}
int main()
{
	int n,C,i,v[20],w[20];
	//cout << "请输入物品个数:";
	cin >> n;
	//cout << "请输入背包容量:";
	cin >> C;
	//cout << "请依次输入每个物品的重量:";
	for(i=1; i<=n; i++) 
		cin >> w[i];
	//cout << "请依次输入每个物品的价值:";	
	for(i=1; i<=n; i++)
		cin >> v[i];
	KnapSack(n,C,w,v); 
	return 0;
}

运行结果

(0,0,1,1)
65
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值