0 1 背包问题 learn2

本文详细阐述了背包问题的概念及解决方法,包括01背包问题和带权重系数的背包问题,通过实例代码展示了如何利用动态规划算法求解背包问题中的最大价值。文章深入解析了动态规划表格的构建过程,并提供了求解过程的详细步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、求 Max(Sum(x[i]*w[i])), 约束条件是sum(w[i]*x[i]) <=C, 其中 1=< i <=n. 
/**************************************************************
*0 1 背包问题
* 参考URI:http://wenku.baidu.com/view/78bf286d25c52cc58bd6bec2.html, p21
*
*给定一个背包,容量为c,有n个物品,
*重量为n维行向量w,
*价值为n维行向量v. 
*n维向量x=[0,1,0….x[n]]代表物品的选法,其中的没有元素x[i],要么是0、要么是1,
* 为1代表选取第i个物品,为0表示不选取第i个物品。 
*目标函数是:Max(Sum(x[i]*w[i])), 约束条件是sum(w[i]*x[i]) <=C, 其中 1=< i <=n. 
*
*
*V[i][j]表示在前i(1<=i<=n)个物品中能够装入容量为j(1<=j<=c)所求的最大值
*
*
*
*
**************************************************************/
#include <stdio.h>

  #define  c 8  //背包容量,为约束条件
  #define  n 4   //物品个数
  int w[n+1] = {-1, 1, 3, 4, 5};  //物品重量数组,从下标1开始
  int v[n+1] = {-1, 2, 30, 44, 20}; //物品价值数组,从下标1开始
  int V[n+1][c+1] = {0,0};       

  int x[n+1] = {-1,-1,-1, -1, -1}; //为0表示不选取物品,为1表示选取物品,从下标1开始
/*******************************************************************
*description: 获取背包所装物品最大价值
*function: int fun(int m, int capacity, int w[], int v[])
*input: m :物品个数
*input: capacity :背包容量
*input: w[] :物品重量数组
*input: v[] :物品权重系数数组
*
*return: 背包所装物品sum(w[i]*x[i]) 且(i=1……n)满足约束条件的最大价值
*
********************************************************************/

int fun(int m, int capacity, int w[], int v[])
{
    int i = 0;
	int j = 0;
	for(i=0; i<=m; i++) //初始化第0列
	{
		V[i][0] = 0;
	}
	for(j=0; j<=capacity; j++)
	{
	    V[0][j] = 0;  //初始化第0行
	}
	for(i=1; i<=m; i++) //计算第i行,进行第i次迭代
	{
		for(j=1; j<=capacity; j++)
		{
			if(j<w[i])
			{
				V[i][j] = V[i-1][j];
			}
			else
			{
				V[i][j] = (V[i-1][j]>=(V[i-1][j-w[i]]+v[i]))?V[i-1][j]:(V[i-1][j-w[i]]+v[i]);

			}
		
		}
	}
	j = capacity; //求装入背包中的物品
    for(i=m; i>0; i--)
	{
		if(V[i][j]>V[i-1][j])
		{
			x[i] = 1;
			j = j-w[i];
		}
		else
		{
			x[i] = 0;
		}
	}
	return V[m][capacity]; //返回要求取得的最大值
}


int main(void)

{

	int maxValue = fun(4, 5, w, v);
    int i = 0;
	for(i=1; i<(n+1); i++)
	{
		printf("%d  ",x[i]);
	}

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


	return 0;

}

二、Max(Sum(v[i]*x[i]*w[i])), 约束条件是sum(w[i]*x[i]) <=C, 其中 1=< i <=n. 


/**************************************************************
*0 1 背包问题
* 参考URI:http://wenku.baidu.com/view/78bf286d25c52cc58bd6bec2.html, p21
*
*给定一个背包,容量为c,有n个物品,
*重量为n维行向量w,
*价值为n维行向量v. 
*n维向量x=[0,1,0….x[n]]代表物品的选法,其中的没有元素x[i],要么是0、要么是1,
* 为1代表选取第i个物品,为0表示不选取第i个物品。 
*目标函数是:Max(Sum(v[i]*x[i]*w[i])), 约束条件是sum(w[i]*x[i]) <=C, 其中 1=< i <=n. 
*
*
*V[i][j]表示在前i(1<=i<=n)个物品中能够装入容量为j(1<=j<=c)所求的最大值
*
*
*
*
**************************************************************/
#include <stdio.h>

  #define  c 8  //背包容量,为约束条件
  #define  n 4   //物品个数
  int w[n+1] = {-1, 1, 3, 4, 5};  //物品重量数组,从下标1开始
  int v[n+1] = {-1, 2, 30, 44, 20}; //物品价值数组,从下标1开始
  int V[n+1][c+1] = {0,0};       

  int x[n+1] = {-1,-1,-1, -1, -1}; //为0表示不选取物品,为1表示选取物品,从下标1开始
/*******************************************************************
*description: 获取背包所装物品最大价值
*function: int fun(int m, int capacity, int w[], int v[])
*input: m :物品个数
*input: capacity :背包容量
*input: w[] :物品重量数组
*input: v[] :物品权重系数数组
*
*return: 背包所装物品sum(w[i]*v[i]*x[i]) 且(i=1……n)满足约束条件的最大价值
*
********************************************************************/

int fun(int m, int capacity, int w[], int v[])
{
    int i = 0;
	int j = 0;
	for(i=0; i<=m; i++) //初始化第0列
	{
		V[i][0] = 0;
	}
	for(j=0; j<=capacity; j++)
	{
	    V[0][j] = 0;  //初始化第0行
	}
	for(i=1; i<=m; i++) //计算第i行,进行第i次迭代
	{
		for(j=1; j<=capacity; j++)
		{
			if(j<w[i])
			{
				V[i][j] = V[i-1][j];
			}
			else
			{
				V[i][j] = (V[i-1][j]>=(V[i-1][j-w[i]]+w[i]*v[i]))?V[i-1][j]:(V[i-1][j-w[i]]+w[i]*v[i]);

			}
		
		}
	}
	j = capacity; //求装入背包中的物品
    for(i=m; i>0; i--)
	{
		if(V[i][j]>V[i-1][j])
		{
			x[i] = 1;
			j = j-w[i];
		}
		else
		{
			x[i] = 0;
		}
	}
	return V[m][capacity]; //返回要求取得的最大值
}


int main(void)

{

	int maxValue = fun(4, 5, w, v);
    int i = 0;
	for(i=1; i<(n+1); i++)
	{
		printf("%d  ",x[i]);
	}

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


	return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值