洛谷P1048 采药 题解

从题目中可以看出我们要帮辰辰采药,每株药都有它的时间(占用空间)以及这株药的价值,而且需要使采到的药价值最大。有了占用空间和价值和在输入中的背包容量,我们就可以看出这题应该使用01背包dp来做这一题。

二维数组

使用二维数组dp[i][j]dp[i][j]表明放了前ii株草药,可用时间不超过jj时的最大总价值

六要素

if(j<si[i])dp[i][j]=dp[i-1][j]/*不采药*/;//如果没有时间采药 那么就不采药
else dp[i][j]=max(dp[i-1][j]/*不采药*/,dp[i-1][j-ti[i]]+si[i]/*采药*/);//否则 就判断采药或不采药哪个价值更大

二维数组AcAc CodeCode

#include <bits/stdc++.h>
#define MAX 1001
using namespace std;
int t,m,ti[105],si[105],dp[105][1005];//t:背包容量,m:物品数量,a:重量,ti:占用背包空间,si:价值,dp[i][j]:只有前i株草药,背包容量为j时的最优解
int main()
{
	//memset(dp,0,sizeof(dp));
	scanf("%d%d",&t,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&ti[i],&si[i]);
	}
	for(int i=1;i<=m;++i)//循环前i个物品
	{
		for(int j=0;j<=t;j++)//循环背包容量
		{
			if(j<ti[i])dp[i][j]=dp[i-1][j]/*不采药*/;
			else dvp[i][j]=max(dp[i-1][j]/*不采药*/,dp[i-1][j-ti[i]]+si[i]/*采药*/);
		}
	}
	printf("%d",dp[m][t]);
	return 0;
}

但是由于第一维在使用后就没用了,所以我们可以把第一维删除掉,再更改状态转移方程,还可以倒着循环来解决重复采同一种药的问题

一维数组

使用一维数组f[i]f[i]表示可用时间不超过ii的最大总价值

六要素

f[j]=max(f[j]/*不采药*/,f[j-ti[i]]+si[i]/*采药*/);

一维数组AcAc CodeCode

#include <iostream>
#include <cstring>
#include <cmath>
#include <climits>
#define MAX 1001
using namespace std;
int t = 0, m = 0, ans = 0, si[MAX], ti[MAX],f[MAX];//t:背包容量,m:草药数量,a:重量,ti:占用背包空间,si:价值,dp[i]:只有i时间的最优解
int main()
{
	scanf("%d%d", &t,&m);
	for (int i = 1; i <= m; ++i)scanf("%d%d", &ti[i], &si[i]);
	for(int i=1;i<=m;++i)//循环前i个物品
	{
		for(int j=t;j>=0;--j)//循环背包容量
		{
			if(j>=ti[i])//确认可以采此药
			{
				f[j]=max(f[j]/*不采药*/,f[j-ti[i]]+si[i]/*采药*/);
			}
		}
	}
	printf("%d",f[t]);
	return 0;
}