hdu-3535背包好题-我对这道题的理解

不得不说,我这个菜鸡做这题真的是一脸懵,自己也没想明白,看别人的看明白了,但是有的部分我还是不明白,先说一下这道题为什么要开二维数组,我个人认为是这样的
为什么要开二维数组:
S == 0(类型0)时,如果你想从这些物品中只取一个,那么转移方程是这样的 :

 dp[i][s] = max(dp[i][s],dp[i-1][s-cost[k]]+val[k]);

因为我们开始时候把dp[i][j](j 由 0-T)设置为负无穷,所以如果有这个方程至少可以保证一定会取一个,我想上面的方程是让每个地方都不再是-INF,但是我们可能还会放多个,那么就用下面的方程

dp[i][s] = max(dp[i][s],dp[i][s-cost[k]]+val[k]);

把俩和在一起:

dp[i][s] = max(dp[i][s],dp[i][s-cost[k]]+val[k]);
dp[i][s] = max(dp[i][s],dp[i-1][s-cost[k]]+val[k]);

S == 1时你就差不多明白为啥开二维了,把每一个dp[i][j]都初始化为dp[i-1][j],都初始化为一个不拿,再让每一个dp[i][j]比较拿一个和不拿谁大谁小,因为就拿一个,所以用下面的方程(上面也提到过,必须是i-1)

dp[i][s] = max(dp[i][s],dp[i-1][s-cost[k]]+val[k]);

S == 2时,也是一个道理,这次是随便取,把每一个dp[i][j]都初始化为dp[i-1][j],都初始化为一个不拿,但这次转移方程是:

dp[i][s] = max(dp[i][s],dp[i][s-cost[k]]+val[k]);

最后ac代码是

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100+8;

int dp[maxn][maxn];
int M,S,C,G,N,T;
int cost[maxn],val[maxn];


int main()
{
	while(scanf("%d%d",&N,&T) == 2)//N组任务,T时间 
	{
		memset(dp,0,sizeof(dp));
		int index = 0;
		for(int i = 1; i <= N; i++)
		{
			scanf("%d%d",&M,&S); //M是任务量,S是类型
		    for(int k = 1; k <= M; k++)
			{
				scanf("%d%d",&cost[k],&val[k]);
			}
			
			if(S == 0)
			{
				for(int j = 0; j <= T; j++) dp[i][j] = -INF;
				for(int k = 1; k <= M; k++)
				{
					for(int s = T; s >= cost[k]; s--)
					{
						dp[i][s] = max(dp[i][s],dp[i][s-cost[k]]+val[k]);
						dp[i][s] = max(dp[i][s],dp[i-1][s-cost[k]]+val[k]);
						//我也不知道这里是为什么不能交换他俩的顺序,
						//下面有一个别人的解释,
						//如果有大佬看明白了请告诉我一声,好人一生平安
					}
				}
			}
			else if(S == 1)
			{
				for(int j = 0; j <= T; j++) dp[i][j] = dp[i-1][j];
				
				for(int k = 1; k <= M; k++)
				{
					for(int s = T; s >= cost[k]; s--)
					{
						dp[i][s] = max(dp[i][s],dp[i-1][s-cost[k]]+val[k]);
					}
				}
			}
			else if(S == 2)
			{
				for(int j = 0; j <= T; j++) dp[i][j] = dp[i-1][j];
				
				for(int k = 1; k <= M; k++)
				{
					for(int s = T; s >= cost[k]; s--)
					{
						dp[i][s] = max(dp[i][s],dp[i][s-cost[k]]+val[k]);
					}
				}
			} 
		}
		
		int ans = max(dp[N][T],-1);
		printf("%d\n",ans);
	}
	return 0;
}

别人的解释:
在这里插入图片描述
感谢大佬看完,奥利给

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值