【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;
    
}

 

posted @ 2018-02-12 08:59  evenbao  阅读(130)  评论(0编辑  收藏  举报