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