HDU 4374 One hundred layer(单调队列+DP)
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int maxn = 111;const int maxm = 10010;const int oo = 1 << 30;int n, m, x, t;int s[maxn][maxm];int sum[maxn][maxm]; int dp[maxn][maxm];int head, tail;int myque[maxm][2];int SUM(int i, int j, int k){ if (j > k) { return 0; } return sum[i][k] - sum[i][j-1];}int main(){ while (scanf("%d%d%d%d", &n, &m, &x, &t) != EOF) { for (int i = 1; i <= n; ++i) { sum[i][0] = 0; for (int j = 1; j <= m; ++j) { scanf("%d", &s[i][j]); sum[i][j] = sum[i][j-1] + s[i][j]; dp[i][j] = -oo; } } for (int i = x; i >= x - t && i >= 1; --i) { dp[1][i] = sum[1][x] - sum[1][i-1]; } for (int i = x; i <= x + t && i <= m; ++i) { dp[1][i] = sum[1][i] - sum[1][x-1]; } for (int i = 2; i <= n; ++i) { // 从上一层的左边到达本层 head = tail = 0; for (int j = 1; j <= m; ++j) { while (head != tail && myque[tail-1][1] <= dp[i-1][j] - SUM(i, 1, j - 1)) { tail--; } myque[tail][0] = j; myque[tail][1] = dp[i-1][j] - SUM(i, 1, j - 1); tail++; while (j - myque[head][0] > t) { head++; } dp[i][j] = max(dp[i][j], myque[head][1] + SUM(i, 1, j)); } // 从上一层的右边到达本层 head = tail = 0; for (int j = m; j >= 1; --j) { while (head != tail && myque[tail-1][1] <= dp[i-1][j] + SUM(i, 1, j)) { tail--; } myque[tail][0] = j; myque[tail][1] = dp[i-1][j] + SUM(i, 1, j); tail++; while (myque[head][0] - j > t) { head++; } dp[i][j] = max(dp[i][j], myque[head][1] - SUM(i, 1, j - 1)); } } int ans = -oo; for (int i = 1; i <= m; ++i) { ans = max(ans, dp[n][i]); } printf("%d\n", ans); } return 0;}