【hdu 4374】One Hundred Layer
【题目链接】
【算法】
不难看出,这题可以用动态规划来解决
f[i][j]表示第i行第j列能够取得的最大分数
则如果向右走,状态转移方程为f[i][j]=max{f[i-1][k]+a[i][k]+a[i][k+1]+...+a[i][j]}(i-T<=k<=j)
如果向左走,则状态转移方程为f[i][j]=max{f[i-1][k]+a[i][k]+a[i][k-1]+...+a[i][j]} (j<=k<=i+T)
用前缀和优化,s[i][j]表示第i行前j个数的和
则式子被简化为 :
向右走 : f[i][j] = max{f[i-1][k]+s[i][j]-s[i][k-1]} (i-T<=k<=j)
向左走 : f[i][j] = max{f[i-1][k]+s[i][k]-s[i][j-1]} (j<=k<=i+T)
但是这样做还是会TLE,所以我们继续优化 :
我们可以将第一个状态转移方程中s[i][j]提出,式子被写成f[i][j] = max{f[i-1][k]-s[i][k-1]}+s[i][j] (i-T<=k<=j)
将第二个状态转移方程中s[i][j-1]提出,式子被写成f[i][j] = max{f[i-1][k]+s[i][k]}+s[i][j-1] (j<=k<=i+T)
于是我们就可以用单调队列维护最值,时间复杂度 : O(数据组数*N*M)
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100 #define MAXM 10000 typedef long long LL; struct info { LL x,val; }; LL i,j,N,M,X,T,tmp,ans; LL a[MAXN+10][MAXM+10],s[MAXN+10][MAXM+10],f[MAXN+10][MAXM+10]; deque<info> q; template <typename T> inline void read(T &x) { LL f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } int main() { while (cin >> N >> M >> X >> T) { ans = -2e9; for (i = 1; i <= N; i++) { for (j = 1; j <= M; j++) { read(a[i][j]); } } for (i = 1; i <= N; i++) { for (j = 1; j <= M; j++) { s[i][j] = s[i][j-1] + a[i][j]; } } for (i = 1; i <= N; i++) { for (j = 1; j <= M; j++) { f[i][j] = -2e9; } } for (i = X; i >= X - T; i--) f[1][i] = s[1][X] - s[1][i-1]; for (i = X; i <= X + T; i++) f[1][i] = s[1][i] - s[1][X-1]; for (i = 2; i <= N; i++) { q.clear(); for (j = 1; j <= M; j++) { while ((!q.empty()) && (j - q.front().x > T)) q.pop_front(); tmp = f[i-1][j] - s[i][j-1]; while ((!q.empty()) && (tmp >= q.back().val)) q.pop_back(); q.push_back((info){j,tmp}); f[i][j] = q.front().val + s[i][j]; } q.clear(); for (j = M; j >= 1; j--) { while ((!q.empty()) && (q.front().x - j > T)) q.pop_front(); tmp = f[i-1][j] + s[i][j]; while ((!q.empty()) && (tmp >= q.back().val)) q.pop_back(); q.push_back((info){j,tmp}); f[i][j] = max(f[i][j],q.front().val-s[i][j-1]); } } for (i = 1; i <= M; i++) ans = max(ans,f[N][i]); writeln(ans); } return 0; }