01背包动态规划空间优化

问题描述:

给定 n 种物品和一个容量为 w 的背包,物品 i 的价值是 vai,其体积为 voi。

问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?

解题思路:

状态转移方程为:

dp[i][j] = dp[i-1][j]                                                      j < vo[i]   (即此时的背包容积小于第i个物品的体积)

dp[i][j] = max( dp[i-1][j] , dp[i-1][j-vo[i]] + va[i] )        j >= vo[i] (当背包容积大于第 i 个物品的体积时,有两种选择,选较大的一个)

两种选择:

1、不装这个物品 。则此时dp数组的值还是第i-1个物品是的值,即dp[i-1][j]

2、装下这个物品,此时是dp[i-1][j-vo[i]] + va[i],然后与不装比较看哪种情况装的物品的价值更大

代码:

#include<stdio.h>
#include<algorithm>
using namespace std;

int dp[105][105];
int va[105] , vo[105];//每件物品的价值va和体积vo

int main()
{
	int w , n ;//背包的总容量,物品的件数
	scanf("%d %d",&n,&w);
	for(int i = 1 ; i <= n ; i++)
	{
		scanf("%d %d",&va[i],&vo[i]);
	}
	
	for(int i = 1 ; i <= n ; i++)
	{
		for(int j = 0 ; j <= w ; j++)
		{
			if( vo[i] > j)
			{
				dp[i][j] = dp[i-1][j];
			}
			else
			{
				dp[i][j] = max(dp[i-1][j] , dp[i-1][j-vo[i]] + va[i]);
			}
		}
	} 
	printf("%d\n",dp[n][w]);
	
	
	return 0;
	
 } 
扫描二维码关注公众号,回复: 5678361 查看本文章

空间优化代码:

只开辟一维dp数组,每次更新是重最后向前循环,毕竟只需要最后一个结果,中间的过程可以不保存,但一定确保从后向前循环

#include<stdio.h>
#include<algorithm>
using namespace std;


int va[105] , vo[105];//每个物品的价值和体积 
int dp[105];

int main()
{
	int n , w;//物品数量和背包容积 
	scanf("%d %d",&n,&w);
	for(int i = 1 ; i <= n ; i++)
	{
		scanf("%d %d",&va[i] , &vo[i]);
	}
	for(int i = 1 ; i <= n ; i++)
	{
		for(int j = w ; j >= vo[i] ; j--)//要倒着进行,确保在没有被更新的状态下使用 
		{
			dp[j] = max(dp[j - vo[i]] + va[i] , dp[j]);
		}
	}
	printf("%d",dp[w]);
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41706331/article/details/87075843
今日推荐