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;
}

 

posted @ 2018-08-27 20:48  CaptainLi  阅读(284)  评论(0编辑  收藏  举报