POJ 2385(线性DP)

题意

现在有两棵树,在1~t分钟内,其中一棵树会掉落一个苹果。一开始你在第一棵树下,每次你只能接住当前在的那棵树上掉落的苹果,或者花费1个体力点瞬移到另一棵树下,接住那个苹果。你总共有w个体力点。给定t,w,每分钟苹果的掉落情况,问你最多能获得多少个苹果。

分析

状态定义为 dp[i][j]:前t分钟在花费j个体力点的情况下能获得的最多苹果数。
状态转移方程 dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+(i分钟时当前树下是否掉落苹果). 当前状态有两个限制条件,一个是时间,另一个是移动的次数也就是花费的体力点。因此这一分钟的情况只能是上一分钟的情况转移过来。如果前一分钟没有移动那么也就还是这棵树,就是dp[i-1][j]+当前树是否掉落苹果;如果前一分钟是另一棵数,则表示要花费一个体力点,那么现在是j的话前一分钟就是j-1,所以就是dp[i-1][j-1]。最后一个问题是怎么判断当前是哪一棵树,因为每次只能从一棵树跳到另一棵,所找规律可以发现如果跳的奇数次就跳回来了,也就是最开始的第一棵树,然后偶数次就是另一棵。还要注意一点,边界判断,具体看代码

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[1005][35];
int a[1005];
int main()
{
    int t, w;
    while (cin >> t >> w)
    {
        int p;
        memset(a, 0, sizeof(a));
        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= t; i++)
            cin >> a[i];
        for (int i = 1; i <= t; i++)
        {
            for (int j = 0; j<=w; j++)
            {
                //注意判断边界
                if (j > 0)dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]);
                else dp[i][j] = dp[i - 1][j];
                if (j % 2 + 1 == a[i]) 
                    dp[i][j]++;
            }
        }
        int  ans = dp[t][0];
        for (int i = 1; i <= w; i++)
            ans = max(ans, dp[t][i]);
        cout << ans << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cugsl/article/details/81775743