51nod-1085 背包问题【01背包】

传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1085

基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。
Input
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000)
第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
Output
输出可以容纳的最大价值。
Input示例
3 6
2 5
3 8
4 9
Output示例
14
相关问题
背包问题 V2 
40
 
背包问题 V3 
80

最基本的01背包问题,做的时候程序实在不知道哪错了,但是编译一直是13不是14,索性一交 ,竟然神奇的过了。无语

状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+p[i])  (j>=w[i])   这是二维的,空间上没有优化。


对于01背包

面对每个物品,我们只有选择拿取或者不拿两种选择,(这就是拿是1不拿是0)不能选择装入某物品的一部分,也不能装入同一物品多次。

声明一个 大小为  dp[n][w] 的二维数组,dp[ i ][ j ] 表示 在面对第 i 件物品,且背包容量为  j 时所能获得的最大价值 ,那么我们可以很容易分析得出 dp[i][j] 的计算方法,

(1). j < w[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿   dp[ i ][ j ] = dp[ i-1 ][ j ]

(2). j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值。

如果拿取,dp[ i ][ j ]=dp[ i-1 ][ j-w[ i ] ] + p[ i ]。 这里的dp[ i-1 ][ j-w[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。

如果不拿,dp[ i ][ j ] = dp[ i-1 ][ j ] ,   拿还是不拿,比较这两种情况那种价值最大


代码:(怎么都是13,以后再看)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[150][10050],c[10050],p[10050];
int main()
{
	int n,w,i,j;
	while(scanf("%d%d",&n,&w)!=EOF)
	{
		for(i=1;i<=n;i++)
			scanf("%d%d",&c[i],&p[i]);
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=w;j++)
			{
				if(c[i]<=j)
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+p[i]);
				else
				dp[i][j]=dp[i-1][j];
			}
		}
		printf("%d\n",dp[n][w]);
	}
	return 0;
} 

一维

dp数组是从上到下,从右往左计算的。在计算dp[i][j]之前,dp[j]里保存的是dp[i-1][j]的值,而dp[j-w]里保存的是 
dp[i-1][j-w],因为j是逆序枚举的。(假如顺序枚举的话dp[j-w]保存的会是dp[i][j-w]的值)这样,dp[j]=(max 
[j],dp[j-v]+w)实际上是把max{dp[i-1][j],dp[i-1][j-v]}保存在dp[j]中,覆盖掉dp[j]中原来的dp[i-1][j].
一维代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[10050],w[105],p[105];
int main()
{
	int n,W,i,j;
//	while(scanf("%d%d",&n,&W)!=EOF)
//	{
	scanf("%d%d",&n,&W);
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&w[i],&p[i]);
		}
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)
		{
			for(j=W;j>=w[i];j--)
				dp[j]=max(dp[j],dp[j-w[i]]+p[i]);
		}
		printf("%d\n",dp[W]);
//	}
	return 0;
}

令推荐个好玩的博客:http://www.cnblogs.com/sdjl/articles/1274312.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值