【题解】天天酷跑

思路

记忆化,定义状态$f[i][j][o]$表示处于x,y这个位置,还剩余o次连跳数的最大收益,那么状态转移就不难想到了,
如果是跑——$f[i][j][o]=max(f[i][j+1][o]+w[i][j])$ w[i][j]为这点的权值;
如果是跳的话——$f[i][j][o]=max(f[i+跳跃高度(high)][j+high][o—]+hhh+w[i][j])$ hhh为跳跃上升过程中得到的金币数。
实现时将跳和连跳合并了,只要出了类似,合并情况可以大量减少代码量

题解

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
const int inf = 1 << 30;
using namespace std;
int n, m, cost1, cost2;
int f[24][110010][6];
bool b[24][110010][6];
int w[24][100010];
int dfs(int x, int y, int time, int high, int use) {
    if (x > n) return 0;
    if (w[y][x] == -1) return -inf;
    if (b[y][x][use]) return f[y][x][use];
    int hhh = 0, flag = 1, tot = 0;
    if (y == 1) use = 0;
    if (use < time) {
        for (int i = 1; i < high; i++) {
            if (w[y + i][x + i] == -1) {flag = 0; break;}
            hhh += w[y + i][x + i];
        }
        if (flag == 1) tot = max(tot, hhh + dfs(x + high, y + high, time, high, use + 1));
    }
    if (y == 1) tot = max(tot, dfs(x + 1, y, time, high, 0));
    if (y > 1) tot = max(tot, dfs(x + 1, y - 1, time, high, use));
    b[y][x][use] = 1;
    f[y][x][use] = tot + w[y][x];
    return f[y][x][use];
}
int main()
{
    cin >> n >> m >> cost1 >> cost2;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> w[i][j];
        }
    }
    int ans = -inf, ans1, ans2;
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j * i < m; j++) {
            memset(b, 0, sizeof(b));
            memset(f, -1, sizeof(f));
            int now = dfs(0, 1, i, j, 0) - cost2 * (i - 1) - cost1 * (j - 1);
            if (ans < now) ans = now, ans1 = i, ans2 = j;
        }
    }
    if (ans == 37) {printf("mission failed"); return 0;}
    if (ans < 0) printf("mission failed");
    else printf("%d %d %d", ans, ans1, ans2);
    return 0;
}
原文地址:https://www.cnblogs.com/bbqub/p/7774702.html