题目描述
原题链接
解题思路
典型的01背包,定义一个数组 d p dp dp, d p [ i ] [ j ] dp[i][j] dp[i][j]表示当容量为 j j j时前 i i i个数可以获得的最大价值。将 i i i从 1 1 1到 n n n循环一次,每次 j j j再从当前第 i i i株草药的采摘时间枚举到 T T T,最后输出 d p [ n ] [ t ] dp[n][t] dp[n][t]的结果就可以了。
状态转移方程: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − b [ i ] ] + a [ i ] ) dp[i][j]=max(dp[i-1][j],dp[i-1][j-b[i]]+a[i]) dp[i][j]=max(dp[i−1][j],dp[i−1][j−b[i]]+a[i])
样例
输入
70 3
71 100
69 1
1 2
输出
3
代码
顺推代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int dp[1005][1005],a[105],b[105],t,n;
int main(){
cin>>t>>n;
for(int i=1;i<=n;i++)
cin>>b[i]>>a[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=t;j++){
if(j>=b[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-b[i]]+a[i]);
else dp[i][j]=dp[i-1][j];
}
}
cout<<dp[n][t];
return 0;
}
逆推代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int dp[1005],a[105],b[105],t,n;
int main(){
cin>>t>>n;
for(int i=1;i<=n;i++)
cin>>b[i]>>a[i];
for(int i=1;i<=n;i++){
for(int j=t;j>=1;j--){
if(j>=b[i])
dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
}
}
cout<<dp[t];
return 0;
}