NOIP2007普及 守望者的逃离
普及组的题目……很水。
原来写了一个模拟不过好像状态考虑的不全得了80,这次我们考虑一下dp做法。
守卫者有两种移动的方法,一种是闪现,一种是跑,我们可以把闪现和跑分开处理。
首先只处理闪现的情况,这个时候要用贪心,能闪就闪,否则原地回蓝即可。
之后在处理跑步的情况,这种情况就要用dp了,方程很好推,就是dp[i] = max(dp[i],dp[i-1]+17)
这样的做法为什么正确呢?因为其实我们跑步的时候只是会把原来只用闪现的情况中,有一些不够好的情况替换掉了,这样就能保证全部被考虑到。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define rep(i,a,n) for(ll i = a;i <= n;i++) #define per(i,n,a) for(ll i = n;i >= a;i--) #define enter putchar('\n') using namespace std; const int M = 300005; typedef long long ll; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int m,s,t,dp[M]; int main() { m = read(),s = read(),t = read(); rep(i,1,t) { if(m >= 10) m -= 10,dp[i] = dp[i-1] + 60; else dp[i] = dp[i-1],m += 4; } rep(i,1,t) { dp[i] = max(dp[i],dp[i-1]+17); if(dp[i] >= s) { printf("Yes\n%d\n",i); return 0; } } printf("No\n%d\n",dp[t]); return 0; }
当你意识到,每个上一秒都成为永恒。