背包问题【01 完全 多重】

目录

0-1背包

空间优化:二维变一维

完全背包

优化:

多重背包


要求恰好装满背包,那么在初始化时除了f[0]为0,其它f[1..V]均设为-∞

如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f[0..V]全部设为0。

初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。

0-1背包

问题描述:

N件物品和容积为M的背包。

第i件物品的体积为volume [ i ] ,价值为 worth [ i ]。

每种物品只有一件,可以选择放或者不放。

求解将哪些物品装入背包可使价值总和最大。

提示:

采用滚动数组防止超出内存要求

状态转移方程:

 f[ i ][v] = max{ f[i-1] [v] , f[i-1][ v-volume[i] ] + worth[i] }

前i件物品放入容量V的背包时的最大价值

= max { 前i -1 件物品放入容量V的背包时的最大价值 ,

【不放入第i件物品,总价值不变 】

前i -1 件物品放入容量V- volume[i] 的背包时的最大价值 + worth [ i ] 

【放入第i件物品;那么在放之前的物品是i-1容量是V-volume[i] 价值是f[i-1][ v-volume[i] ]    

}

空间优化:二维变一维

要保证j-v[i]没被算过的,就是需要J逆序,也就是从大的到小的,不然如果从正序开始的话,前面那些小的值已经都改变过了,而大的值会因为小的值被改变过,而经过二次改变。

f[v]  =  max{     f[v]  ,   f [ v-volume[i] ]   +   worth [i]     }

最大价值 = max{ 不加入物品i 的上一个最大价值(容量是v),加入物品 i (容量是v-volume[i ])  }

循环,逆推:

// 0 -1 背包 

#include<iostream>
#include<cmath>
#include<cstring>

using namespace std;

int main()

{
	int n;cin>>n;//N件物品 
	int m;cin>>m;//背包容积M

	int worth[n]; //价值
	int volume[n]; //体积 
	
	int dp[m];//注意初始化 
	memset(dp,0,sizeof(dp));//只求最大价值,初始值全部为0
	
	//输入下标i的价值和体积  从0开始
	for(int i=0;i<n;++i)
	{
		cin>>volume[i]>>worth[i];
	} 

	//滚动数组 取前i件物品
	for(int i=0;i<n;i++)
	{
		for(int v=m;v>=volume[i];--v)//
		{
			//容量V的最大价值 = max{ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值