动态规划——0-1背包问题

0-1背包问题

  1. 题目:
    有一个背包,它的容量为C(capacity)。现在有n种不同的物品,编号为0…n-1,其中每一件物品的重量为W(i),价值为v(i)。问可以向这个背包中盛放哪些物品,使得在不超过背包容量的基础上,物品的总价值最大。有一个背包,它的容量为C(capacity)。现在有n种不同的物品,编号为0…n-1,其中每一件物品的重量为W(i),价值为v(i)。问可以向这个背包中盛放哪些物品,使得在不超过背包容量的基础上,物品的总价值最大。
  2. 思路:
    暴力解法:每一件物品都可以放进背包,也可以不放进背包。时间复杂度为O((2^n)*n)
    贪心算法:优先放入平均价值最高的物品。现实中可以,实际中可能不是最优。贪心算法不能解决0-1背包问题。
    动态规划:
    F(n,C)考虑将n个物品放进容量为C的背包,使得价值最大。
    F(i,c)=max(F(i-1,c)不放,v(i)+F(i-1,c-w(i))放进)
    代码:
    递归求解
class Knapsack01{
public:
	int knapsack01(const vector<int>& w,const vector<int>& v,int C){
		int n=w.size();
		return bestValue(w,v,n-1,C);
	}
private:
	//用[0...index]的物品,填充容积为c的背包的最大价值
	int bestValue(const vector<int>& w,const vector<int>& v,int index,int c){
		if(index<0||c<=0)
			return 0;
			int res=bestValue(w,v,index-1,c); //不选index 
			if(c>=w[index])
				res=max(res,v[index]+bestValue(w,v,index,c-v[index]));
			return res; 
	} 
}; 

自顶向下记忆化搜索

class Knapsack01{
public:
	int knapsack01(const vector<int>& w,const vector<int>& v,int C){
		int n=w.size();
		memo=vector<vector<int>>(n,vector<int>(C+1,-1)); 
		return bestValue(w,v,n-1,C);
	}
private:
	vector<vector<int>> memo; 
	//用[0...index]的物品,填充容积为c的背包的最大价值
	int bestValue(const vector<int>& w,const vector<int>& v,int index,int c){
		if(index<0||c<=0)
			return 0;
		if(memo[index][c]!=-1)
			return memo[index][c];	
		int res=bestValue(w,v,index-1,c); //不选index 
		if(c>=w[index])
			res=max(res,v[index]+bestValue(w,v,index,c-v[index]));
		memo[index][c]=res; 
		return res; 
	} 
};  

动态规划,二维数组
在这里插入图片描述
时间复杂度:O(nC)
空间复杂度:O(nC)

class Knapsack01{
public:
	int knapsack01(const vector<int>& w,const vector<int>& v,int C){
		assert(w.size()==v.size()); 
		int n=w.size();
		if(n==0)
			return 0;
		vector<vector<int>> dp(n,vector<int>(C+1,-1));
		//初始化只加入第一个物品
		for(int j=0;i<=C;j++)
			dp[0][j]=(j>=w[0]?v[0]:0);
		for(int i=1;i<n;i++)
			for(int j=0;j<=C;j++){
				dp[i][j]=dp[i-1][j];
				if(j>=w[i])
					dp[i][j]=max(dp[i][j],v[i]+dp[i-1][j-v[i]]);
			} 
		return dp[n-1][C];	 
	}
}; 

动态规划方法的优化:
在这里插入图片描述
空间复杂度读为:O(2C)
在这里插入图片描述
代码:

class Knapsack01{
public:
	int knapsack01(const vector<int>& w,const vector<int>& v,int C){
		assert(w.size()==v.size()); 
		int n=w.size();
		if(n==0)
			return 0;
		vector<vector<int>> dp(2,vector<int>(C+1,-1));
		//初始化只加入第一个物品
		for(int j=0;i<=C;j++)
			dp[0][j]=(j>=w[0]?v[0]:0);
		for(int i=1;i<n;i++)
			for(int j=0;j<=C;j++){
				dp[i%2][j]=dp[(i-1)%2][j];
				if(j>=w[i])
					dp[i%2][j]=max(dp[i%2][j],v[i]+dp[(i-1)%2][j-v[i]]);
			} 
		return dp[n-1][C];	 
	}
}; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值