其实这题的的逆天数据不用单调队列
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];
}
记得点赞

京公网安备 11010502036488号