题目:
在这里插入图片描述
题意: 给定m(初始的魔法值),s(在t时间内至少要走的距离),t(最多花费的时间),在每一秒,可以有三种状态选择:
1、花费10魔法值,走60米
2、站在原地不动,恢复4魔法值
3、魔法值不增减,直接走17米

思路: 很明显是动态规划,原本想到了用dp[i][j]表示在第i秒,魔法值为j时所能走的最远距离。代码如下:

#include <bits/stdc++.h>
using namespace std;
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define de(x) cout << x << " ";
const int N = 1e5 + 10, M = 1e3 + 10;
int dp[N][M];
int main() {
    int m, s, t;
    cin >> m >> s >> t;
    memset(dp, 0xc0, sizeof(dp));
    dp[0][m] = 0;

    int f = 0;
    int tim = -1;
    int dis = -INT_MAX;
    for (int i = 1; i <= t; i++) {
        for (int j = m; j >= 0; j--) {
            if (j >= 4) {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - 4]);
            }
            dp[i][j] =
                max(dp[i - 1][j] + 17, max(dp[i][j], dp[i - 1][j + 10] + 60));

            if (dp[i][j] > dis) {
                dis = dp[i][j];
            }

            if (dp[i][j] >= s && tim == -1) {
                // de(dis) de(i) de(j) de(888) Pu;
                f = 1;
                tim = i;
                break;
            }
        }
        if (f == 1)
            break;
    }
    if (f == 1) {
        puts("Yes");
        printf("%d\n", tim);
    } else {
        puts("No");
        printf("%d\n", dis);
    }
    return 0;
}

但是全部MLE了,经过分析,数组的第一维其实用处不大,因为每一次进行for循环中的max判断时,都是在前一秒的基础上,时间那一维完全可以去掉。
于是考虑用一维数组带体二维,就是用f[j]表示在魔法值为j时所能走的最远距离。但是需要用两个数组,因为必须要用一个数组保留上一秒的状态。

开O2优化才能AC,否则有两个点TLE(这个地方以后需要好好想想,等我看了别人的题解后再来更新吧)

AC代码如下(开O2优化):

#include <bits/stdc++.h>
using namespace std;
#define sf(x) scanf("%d", &x);
#define ll long long
#define Pu puts("");
#define de(x) cout << x << " ";
const int N = 3e5 + 10, M = 1e3 + 10;
int f1[M], f2[M];
int main() {
    int m, s, t;
    cin >> m >> s >> t;
    memset(f1, 0xc0, sizeof(f1));
    memset(f2, 0xc0, sizeof(f2));
    f1[m] = 0;  // 临界值

    int f = 0;
    int tim = -1;        // 如果成功时,记录最短时间
    int dis = -INT_MAX;  // 如果失败时,记录最长距离
    for (int i = 1; i <= t; i++) {
        for (int j = m; j >= 0; j--) {
            if (j >= 4) {
                f2[j] =
                    max(f2[j], f1[j - 4]);  // 情况一:如果站在原地,魔力值恢复4
            }
            // 情况二、三:直接花费一秒走17米,或者消耗10魔力值,走60米
            f2[j] = max(f2[j], max(f1[j] + 17, f1[j + 10] + 60));

            if (f2[j] > dis) {  // 记录当前能走到的最远距离
                dis = f2[j];
            }
            if (dis >= s && tim == -1) {  // 判断是否已经逃出去了
                f = 1;
                tim = i;
                break;
            }
        }
        if (f == 1)
            break;

        // 这是第一次MLE后进行的优化,把第一维时间去掉了
        // 原本f[i][j]表示在第i秒,魔力值为j时走的最远距离

        // 把f[j]表示魔力值为j时走的最远距离,但是需要用f1[j]和f2[j]两个数组,以保存上一秒的状态
        // 用空间换取时间
        for (int j = 1; j <= 1e3; j++) {
            f1[j] = f2[j];
            f2[j] = -INT_MAX;
        }
    }
    if (f == 1) {
        puts("Yes");
        printf("%d\n", tim);
    } else {
        puts("No");
        printf("%d\n", dis);
    }
    return 0;
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐