其实这题的的逆天数据不用单调队列

a, c都是用于记录输入的变量

dp[枚举到的时间] = 最大金币数量

代码比较短

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 2e3 + 2; // 调试的时候开大了一点

int a[N][N];
int c[N];
int dp[N]; 

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr); // 加速用的, 但不写可能也能过

    int n, m, p;
    cin >> n >> m >> p;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }

    for (int i = 1; i <= n; i++) {
        cin >> c[i];
    }
    memset(dp, 128, sizeof dp); // 全都设为负值,结果可能为负数
    dp[0] = 0;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            int sum = dp[i - 1] - c[j]; // 上一个时间转移过来,减去买机器人的钱
            for (int k = 1; k <= min(m - i + 1, p); k++) { // 防止无用枚举节省时间
                int w = j + k - 1;
              	/*
                有人就问了:为啥要减去1呢?
                首先:对于k = 1, j = 1的情况, 如果不减一w = 1 + 1 = 2;
                第j个点对应的第j条边
                那么就会出现第j条边没有转移
                下面的t也是同理
            
                */
                if (w > n) w -= n; // 因为是环形嘛
                int t = i + k - 1;
                sum += a[w][t]; // 当前从j开始到当前点可以拿到多少金币呢?
              
                dp[t] = max(dp[t], sum); // t的时间中你可以拿到多少金币呢?
            }
        }
    }

    cout << dp[m];
}

记得点赞