先看题目:https://ac.nowcoder.com/acm/problem/16650
题目描述:
给出能够用来采药的时间T和山洞里的草药的数目,问在规定的时间内,可以采到的草药的最大总价值。
解题思路:
01背包问题,定义状态dp[i][j]为前i个物品,花费时间在j以内,可获得的最大价值。
状态转移方程:dp[i][j] = max(dp[i-1][j] , dp[i-1][j-v[i]]) (放 or 不放 第i个物品)
优化空间复杂度可以用就地滚动。
就地滚动顾名思义就是用一个一维数组了!之前的状态和当前的状态都记在同一个数组里了。
使用就地滚动时别忘了改变内层循环的顺序

for(int i = 1; i <= n; i++)
    for(int j = v; j >= c[i]; j--)     //小技巧:这里只到c[i],可以剩下后面的if(j-v[i] > 0)语句
        dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

就地滚动相当于把前一阶段的状态和当前阶段的状态放在了同一行,为了确保区分它们,我们需要保证上一行的状态在j的左边,当前行的状态在j的右边

代码:

#include<bits/stdc++.h>
using namespace std;
int dp[1100];
int v[110],w[110];
int main()
{
    int t, m;
    scanf("%d%d",&t,&m);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d",&v[i],&w[i]);
    }
    for(int i = 1; i <= m; i++) {
        for(int j = t; j >= v[i]; j--) {
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
    }
    printf("%d\n",dp[t]);
}