0 1背包问题 learn 1


##################################################################################################
背包问题(Knapsack problem)是一种组合优化的NP完全问题。
问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,
在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
问题的名称来源于如何选择最合适的物品放置于给定背包中。

我们有n种物品,物品j的重量为wj,价格为pj。我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。
如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题。可以用公式表示为:
最优化

受限于 


框中上面内容来自:维基百科->背包问题
#################################################################################################

####################################################################### ##############
框中内容来自《0-1背包问题递归实现与非递归实现--动态规划》
程序为:
/**************************************************************
*0 1 背包问题
* 参考URI:http://www.cnblogs.com/justinzhang/archive/2012/04/10/2441199.html
*
*给定一个背包,容量为c,有n个物品,
*重量为n维行向量w,
*价值为n维行向量v. 
*n维向量y=[0,1,0….yn]代表物品的选法,其中的没有元素yi,要么是0、要么是1,
* 为1代表选取第i个物品,为0表示不选取第i个物品。 
*目标函数是:Max(Sum(vi*yi)), 约束条件是sum(wi*yi) <=C, 其中 1=< i <=n. 
*
*
*背包问题具有最优子结构,
*令f(n,c)代表,有n个待选物品,背包容量为C时的最优解,
*此时物品选择向量为y=[y1,y2,…yn], 那么当y[n]=1时,y'=[y1, y2, …yn-1],必然为f(n-1, c-wn)的物品选择向量,
*当y[n]=0时,必然为f(n-1,c)的最优物品选择向量。
*所以背包问题可以由动态规划来求解。

*根据上面的分析,我们可以得到如下的递归式:
*当w[n]>C时,  f(n,c)=f(n-1,c);
*当w[n]<=C时,f(n,c) = max(f(n-1,c), vn+f(n-1, c-wn) );
*初始条件为:f(i, 0) = 0; f(0,i) = 0; f(0,0) = 0;
*
*
*
*
**************************************************************/
#include <stdio.h>

int w[] = {1, 3, 4, 5};  //物品重量数组,从下标0开始
int v[] = {2, 30, 44, 20}; //物品价值数组,从下标0开始
int c = 5; //背包容量	
int y[4] = {-1,-1,-1,-1}; //为0表示不选取物品,为1表示选取物品

/*******************************************************************
*description: 获取背包所装物品最大价值
*function: int f(int n, int c)
*input: n :物品个数
*input: c :背包容量
*
*return: 背包所装物品最大价值
*
********************************************************************/
int f(int n, int c)
{
    if(n==0 || c==0)
	{
		return 0;
	}
	int i = 0;
	//从当前所剩物品的左后一个物品开始向前,逐个判断是否要添加到背包中
	for(i=n-1; i>=0; i--)
	{
		//如果当前所剩物品的最后一个物品开始向前,逐个判断是否要添加到背包中
		//在这种情况的最优解为f(n-1, c)
		if(w[i] > c)
		{
			y[i] = 0;
			return f(n-1,c);
		}
		else
		{
		   //如果当前待判断的物品重量w[i]<=c,那么就选取f(n-1,C)和vi+f(n-1,C-wi)中的最大值
			int temp1 = f(n-1, c); //不选择物品i的情况下的最有将诶
			int temp2 = v[i] + f(n-1, c-w[i]); //选择物品i的情况下的最优解

			//返回选择物品i和不选择物品i中最优解大的一个
			if(temp1>temp2)
			{
				y[i] = 0;  //不取物品i
				return temp1;
			}
			else
			{
				y[i] = 1; //取物品i
				return temp2;
			}
		
		}
	
	
	}

}

int main(void)

{
    //物品个数为4,背包容量为5,求最优值
//	int w[] = {1, 3, 4, 5};  //物品重量数组,从下标0开始
//   int v[] = {2, 30, 44, 20}; //物品价值数组,从下标0开始
//   int c = 5; //背包容量
	int maxValue = f(4, 5);
    int i = 0;
	for(i=0; i<4; i++)
	{
		printf("%d  ",y[i]);
	}

	printf("\n%d\n", maxValue);


	return 0;

}

#####################################################################################

--------------------------------------------------------------------------------------------------
上述程序可以求出在满足sum(w[i]) 其中i=0……n-1,求出所装物品的最大值sun(v[i]*y[i])及所装物品对应的下标,装入为1,否则为0;  但是我想求出最大值为sun(v[i]*y[i]*w[i]) i=0……n-1,可以求出结果但是输出对应的物品的下标却不对。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值