【动态规划】黑熊过河

题目描述

晶晶的爸爸给晶晶出了一道难题:有一只黑熊想过河,但河很宽,黑熊不会游泳,只能借助河面上的石墩跳过去,它可以一次跳一墩,也可以一次跳两墩,但是每跳一次都会耗费一定的能量,黑熊最终可能因能量不够而掉入水中。所幸的是,有些石墩上放了一些食物,这些食物可以给黑熊增加一定的能量。问黑熊能否利用这些石墩安全地抵达对岸?请计算出抵达对岸后剩余能量的最大值。

输入

第1行包含两个整数P(黑熊的初始能量),Q(黑熊每次起跳时耗费的能量),0≤P,Q≤1000;
第2行只有一个整数n(1≤n≤106),即河中石墩的数目;
第3行有n个整数,即每个石墩上食物的能量值ai(0≤ai≤1000)。

输出

仅1行,若黑熊能抵达对岸,输出抵达对岸后剩余能量的最大值;若不能,则输出“NO”。

样例输入

12 5
5
0 5 2 0 7

样例输出

6



#include <bits/stdc++.h>

using namespace std;

int main()
{
    int p,q;
    int n;
    int a[100015];
    cin>>p>>q;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int dp[100015];
    bool vis[100015];
    memset(dp,0,sizeof(dp));
    memset(vis,false,sizeof(vis));
    if(p<q)
    {
        cout<<"NO";
        return 0;
    }
    vis[0] = true;
    dp[0] = p;
    dp[1] = dp[0]-q+a[1];
    if(dp[1]<q)
    {
        vis[1] = false;
    }
    else
    {
        vis[1] = true;
    }
    for(int i=2;i<=n;i++)
    {
        if(!vis[i-1]&&!vis[i-2])
        {
            cout<<"NO";
            return 0;
        }
        if(vis[i-1]==false&&vis[i-2]==true)
        {
            dp[i] = dp[i-2]-q+a[i];
        }
        else if(vis[i-1]==true&&vis[i-2]==false)
        {
            dp[i] = dp[i-1]-q+a[i];
        }
        else
        {
            dp[i] = max(dp[i-1]-q+a[i],dp[i-2]-q+a[i]);
        }
        if(dp[i]>=q)
            vis[i] = true;
    }

    if(vis[n]==true&&vis[n-1]==false)
    {
        cout<<dp[n]-q;
        return 0;
    }
    else if(vis[n]==false&&vis[n-1]==true)
    {
        cout<<dp[n-1]-q;
    }
    else if(vis[n]==true&&vis[n-1]==true)
    {
        cout<<max(dp[n]-q,dp[n-1]-q);
    }
    else
    {
        cout<<"NO";
    }
    return 0;
}

vis[]记录了该点能否到达           

一个点到达当前状态 无非就是从这个点前两个点中的一个来的      

而如果vis【i-1】和vis【i-2】都是false那么熊的能量已经耗尽 之后也无法到达   输出NO

其中有几个重要的特判和初始化操作

如开始dp【0】 = 初始值p

特判初始值p<q 等等

原文地址:https://www.cnblogs.com/hao-tian/p/9388159.html