本题是一个01背包问题。其中时间其实就相当于背包问题里面的重量。
那么可以建立一个二维数组dp[i][j]表示对于第i个药草,时间为j来说它的最大价值。那么它的最大价值有选与不选两种情况,如果不选那么就是上一个药草,时间为j所对应的最大价值、如果选就是上一个药草对于j-a[i].tm的时间的最大价值加上这个药草的价值。在这两种情况下取最大值即可。
#include <bits/stdc++.h>

using namespace std;
struct Node {
    int tm, value;
};
const int maxn = 100+10;
int dp[maxn][1000+10];
Node a[maxn];
int t, m;

int main() {
    cin>>t>>m;
    for (int i=1;i<=m;i++) {
        cin>>a[i].tm>>a[i].value;
    }
    for (int i=1;i<=m;i++) {
        for (int j=0;j<=t;j++) {
            if (j>=a[i].tm)
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-a[i].tm]+a[i].value);
            else
                dp[i][j] = dp[i-1][j];
        }
    }
    cout<<dp[m][t];
    return 0;
}
滚动数组对于空间的优化:
由于某一个药草的情况其实只取决于上一个药草的情况,那么就可以用滚动数组直接覆盖的做法。要注意得从大到小进行计算,不然前面小的计算出来会影响后面大的结果。
#include <bits/stdc++.h>

using namespace std;
struct Node {
    int tm, m;
};
int dp[1000+10];
Node a[100+10];
int t, m;

int main() {
    cin>>t>>m;
    for (int i=1;i<=m;i++) {
        cin>>a[i].tm>>a[i].m;
    }
    for (int i=1;i<=m;i++) {
        for (int j=t;j>=a[i].tm;j--){
            dp[j] = max(dp[j], dp[j-a[i].tm]+a[i].m);
        }
    }
    cout<<dp[t];
    return 0;
}