首页 > 其他分享 >P1095 守望者的逃离

P1095 守望者的逃离

时间:2022-12-25 12:33:07浏览次数:53  
标签:施展 逃离 魔法值 int res 守望者 P1095 法术 del

P1095 守望者的逃离

题意:

一个岛上有一个人,跑步速度为 \(17m/s\) ,消耗 \(10\) 点魔法值可以在 \(1s\) 内移动 \(60m\) ,每秒原地休息的话可以恢复 \(4\) 点的魔法值。

已知这个人的魔法初始值为 \(M\) ,他所在的初始位置与岛的出口之间的举例 \(S\) ,岛沉没的时间为 \(T\) 。如果能逃出岛屿则输出逃出去需要的最短时间,否则输出能跑到的最远距离。

思路

在每一秒我们只有三种操作,跑步,原地恢复,和施展魔法,就自然的想到是否可以使用动态规划来解决这道问题。

我们进行一种操作,需要知道当前的时间,和当前的魔法值。所以很自然的想到定义 \(f[i][j]\) 为经过了 \(i\) 秒,魔法值为 \(j\) 时可以跑到的最远距离。

分析数据范围,显然这样会 MLE 和 TLE ,所以就思考是否有地方可以进行优化。发现,跑步和施展法术都需要消耗一秒,但是施展法术获得的距离远远大于跑步,所以可以得出结论,如果我们此时可以施展法术,则一定施展法术,然后因为每次恢复速度为 \(4\) 秒,施展法术每次消耗 \(10\) 点,所以第二维度开 \(15\) 就够了。

因为这里的第二维度为 \(15\) ,所以要先预处理初始的法术值,直到这个法术值不够施展,再去 \(dp\)

实现:

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5, M = 15, INF = 1e8;
int f[N][M];
int main()
{
    int m, s, t, tot, dist;
    scanf("%d%d%d", &m, &s, &t);
    tot = t;
    dist = s;
    int v = 17, del = 10, up = 60, rev = 4;
    int res = INF;
    // 可以施法的时候就立马施法
    while (m >= del && t)
    {
        m -= del;
        t--;
        s -= up;
        if (s <= 0)
        {
            res = tot - t;
            break;
        }
    }
    dist -= s; //预处理时已经运动的距离
    tot -= t;  //预处理时消耗的时间

    if (res != INF)
    {
        printf("Yes\n%d\n", res);
        return 0;
    }
    
    for (int i = 0; i < N; i++)
        for (int j = 0; j < M; j++)
            f[i][j] = -INF;

    f[0][m] = 0;
    for (int i = 1; i <= t; i++)
    {
        for (int j = 0; j < M; j++)
        {
            // 选择跑步
            f[i][j] = max(f[i][j], f[i - 1][j] + v);
            if (j - rev >= 0)
                // 休息
                f[i][j] = max(f[i][j], f[i - 1][j - rev]);
            if (j + del < M)
                // run!
                f[i][j] = max(f[i][j], f[i - 1][j + del] + up);
        }
    }

    int best = 0;
    for (int i = 1; i <= t; i++)
    {
        for (int j = 0; j < M; j++)
        {
            if (f[i][j] >= s)
            {
                res = min(res, i);
            }
            best = max(best, f[i][j]);
        }
    }
    
    if (res != INF)
        printf("Yes\n%d\n", res + tot);//剩下段需要的最短时间 + 预处理耗费的时间
    else
        printf("No\n%d\n", best + dist);//剩下段能跑到的最远距离 + 预处理时跑到的距离

    return 0;
}

标签:施展,逃离,魔法值,int,res,守望者,P1095,法术,del
From: https://www.cnblogs.com/zxr000/p/17003874.html

相关文章

  • 年轻人为什么逃离车间?
    “最早的时候有一些偏远地方的年轻女孩来我们这里当‘厂妹’,但是前几年就已经看不到年轻人了。现在光剩下我们这些‘厂妈’了。”夏阿姨说,因为工作简单、收入稳定,一开始还是......
  • 做题记录整理dp7 P1373 小a和uim之大逃离(2022/9/20)
    P1373小a和uim之大逃离好吧,这道题是看题解的。。。(dp学得是真的拉)不过看的是kksc03这种无代码的,应该也还行。。。#include<bits/stdc++.h>#definefor1(i,a,b)for(......