Power收集

题目背景

据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了。

然而当时灵梦在Power达到MAX之前,不具有“上线收点”的能力,所以她想要知道她能收集多少P点,然而这个问题她答不上来,于是她找到了学OI的你。

题目描述

可以把游戏界面理解成一个N行M列的棋盘,有K个格子上有P点,其价值为val(i,j)

初始灵梦可以选择在第一行的任意一个格子出发,每秒她必须下移一格。

灵梦具有一个左右移动的速度T,可以使她每秒向左或右移动至多T格,也可以不移动,并且不能折返。移动可视为瞬间完成,不经过路途上的点,只能获得目标格子的P点。

求最终她能获得的POWER值最大是多少?

输入格式

第一行四个数字,N,M,K,T

接下来K行每行3个数字x,y,v,代表第x行第y列有一个val为v的P点,数据保证一个格子上最多只有1个P点。

输出格式

一个数字

输入输出样例

输入 #1
3 3 4 1
1 1 3
1 2 1
2 2 3
3 3 3
输出 #1
9

说明/提示

对于40%的测试点,1<=N,M,T,K<=200

对于100%的测试点,1<=N,M,T,K<=4000

v<=100,N,M,K,T均为整数

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 6e5 + 10;
int n, m, k, t;
int w[5006][5006];
int que[5006][6];
int dp[5006][5006];

int main() {
    scanf("%d%d%d%d", &n, &m, &k, &t);
    for (register int i = 1, x, y; i <= k; ++i) {
        scanf("%d%d", &x, &y);
        scanf("%d", &w[x][y]);
    }
    int head = 1, tail = 0;
    for (register int i = 1; i <= n; ++i) {
        head = 1, tail = 0;
        for (register int j = 1; j <= min(m, t); ++j) {
            while (head <= tail && que[tail][0] <= dp[i - 1][j]) {
                tail--;
            }
            que[++tail][0] = dp[i - 1][j];
            que[tail][1] = j;
        }
        //printf("debug que[tail][0] = %d
", que[tail][0]);
        for (register int j = 1; j <= m; ++j) {
            if (j + t <= m) {
                while (head <= tail && que[tail][0] <= dp[i - 1][j + t]) {
                    tail--;
                }
                que[++tail][0] = dp[i - 1][j + t];
                que[tail][1] = j + t;
            }
            while (que[head][1] < j - t) {
                head++;
            }
            dp[i][j] = que[head][0] + w[i][j];
        }
    }
    int res = 0;
    for (register int i = 1; i <= m; ++i) {
        res = max(res, dp[n][i]);
    }
    printf("%d
", res);
    return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/11392918.html