完全背包问题

完全背包描述:

总承受重量为m的背包和n种物品,每个物品都有各自的重量Weight和价值Value,每种物品都有无限件可用,将哪些物品装入背包物品重量总数不超过包的总承受重量m 时,能够得到的最大价值是多少?

思路:

对dp[i][j]这个集合进行划分,对i这件物品,可以令k取0,1,2,3,…一直取到超出该背包大小.
那么dp[i][j] = max(dp[ i-1 ] [ j ], dp[ i-1 ] [ j - Weight[ i ]] + Value[i],
dp[ i - 1] [j - 2 * Weight[ i ]] + 2 * Value[i] ,…)

那么k从0开始枚举 一直枚举到超出背包大小就得到dp[n][m];

递推

dp[i][j] =

MAX(dp[i-1][j - k * Weight[i]] + Value[i] * k)

朴素版完全背包

#include <iostream>
using namespace std;

const int N = 1010;

int dp[N][N];//dp[i][j]  代表在前i个物品中 选取总重量不超过j的最大值 
int Value[N], Weight[N];//记录 价值和  重量
int n;//n代表物品个数 
int BagSize;//m代表背包总大小 

//最重要的是对这个集合的划分
//可以将f(i,j) 划分成当前物品 选0 1 2 3 ....直到达到j这个重量
//那么就是 f[i-1][j- Weight[i]*k] + Value[i]*k 
int main(int argc, char** argv) 
{
	cin>>n>>BagSize;
	
	//读取每个物品的 重量 和  价值
	for(int i = 1; i <= n; i++)
	{
		cin>>Weight[i]>>Value[i];
	}
	
	// 
	for(int i = 1; i <= n; i++)
	{
		for(int j = 0; j <= BagSize; j++)
		{
			//当前这个物品从0个一直选 直到达到重量 j 
			for(int k = 0; k * Weight[i] <= j; k++)
			{
				dp[i][j] = 
				max(dp[i-1][j- k*Weight[i]] + Value[i]*k,dp[i][j]);
			}
		}
	}
	
	cout<<dp[n][BagSize]<<endl;
	return 0;
}

优化版完全背包问题

//以下的weight[i] 和 Value[i]都简化为 W 和 V
//dp[i][j] = max(dp[i-1][j], dp[i-1][j-W]+V, dp[i-1][j-2W]+2V, dp[i-1][j-3W]+3V)
//dp[i][j-W] = max( dp[i-1][j-w], dp[i-1][j-2w]+w, dp[i-1][j-3w]+2*v )
//==> dp[i][j] = max(dp[i-1][j], dp[i][j-Weight[i]]+Value[i])

dp[j] = max(dp[j],dp[j-Weight[i]] + Value[i])

#include <iostream>
using namespace std;

const int N = 1010;

int dp[N];
int Weight[N];//重量 
int Value[N];//价值 
int BagSize;//背包大小 
int n;//n个物品 

//以下的weight[i] 和 Value[i]都简化为 W 和 V 
//dp[i][j] = max(dp[i-1][j], dp[i-1][j-W]+V, dp[i-1][j-2*W]+2*V, dp[i-1][j-3*W]+3*V)
//dp[i][j-W] = max(          dp[i-1][j-w],   dp[i-1][j-2*w]+w,   dp[i-1][j-3*w]+2*v )
//==> dp[i][j]  = max(dp[i-1][j], dp[i][j-Weight[i]]+Value[i]) 


int main(int argc, char** argv) 
{
	cin>>n>>BagSize;
	
	for(int i = 1; i <= n; i++)
	{
		cin>>Weight[i]>>Value[i];
	}
	
	for(int i = 1; i <= n; i++)
	{
		//注意这里与01背包的区别 请独立思考为什么? 
		for(int j = Weight[i]; j <= BagSize; j++)
		{
			dp[j] = max(dp[j],dp[j-Weight[i]]+Value[i]);
		}
	}
	
	cout<<dp[BagSize]<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值