51nod 0-1背包详解dp(加一维优化)

输入

第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000)
第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)

输出

输出可以容纳的最大价值。

输入示例

3 6
2 5
3 8
4 9

输出示例
14

这个题直接说一下递推式的确定,51nod 上面这样写到令f(i,j)表示选决定了前i件物品,重量恰好为j的时候能获得的最大价值。对f(i,j)如果我们不选取第i件物品,则显然。然后我当初是这样理解的,既然能去第i件物品为什么不取。其实这句话这样理解,就是f(i,j)表示,物品一共有i件,这个时候背包的容量是j,所以对于递推式的确定,就是说如果不取这个第i件物品,那么这个时候的背包的容量j不会变,这时就判断第(i-1)件物品取还是不取,所以这个时候f(i, j) = f(i – 1,j),如果取了第i件物品,这个时候背包容量就是j-wi的重量加上i的价值,判断哪个总收益最高,所以总的递推式是f(i,j) = max(f(i – 1, j) , f(i-1,j - wi) + vi)。然后这个剩下就是用dp[n][w] 了,题解用i从1循环到n,j从0到w,这个时候就加了一个判断,就是如果这个时候第i件物品的重量大于背包直接承受的重量 ,则f(i, j) = f(i – 1,j)。所以源代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[105][10010];
int wi[10010],pi[10010];

int main()
{
	int i,j;
	int n,w;
	scanf("%d%d",&n,&w);
	for(i=1;i<=n;i++)   
	{
	scanf("%d%d",&wi[i],&pi[i]);
	}
	for(i=1;i<=n;i++)
	{
		for(j=0;j<=w;j++)
		{
			if(j<wi[i]){

			dp[i][j]=dp[i-1][j];
			}
			else 
			{
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-wi[i]]+pi[i]);
			}
		}
	}
	printf("%d\n",dp[n][w]);
	return 0;
}




优化代码:

//    >File Name: 0-1背包问题.cpp
//    > Author: Webwei

#include<iostream>
#include<algorithm>
#include<cstring>
#define MAX 10010
using namespace std;
int dp[100010];

int main()
{

	int n,C,v,w;
	cin>>n>>C;
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++)
	{		
		cin>>v>>w;
		for(int j=C;j>=v;j--)
		{
			if(dp[j]<dp[j-v]+w)  dp[j]=dp[j-v]+w;
		}
	}
	cout<<dp[C]<<endl;
	return 0;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值