zoukankan      html  css  js  c++  java
  • 【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;
        
    }
  • 相关阅读:
    javascript,函数声明和函数表达式
    javascript,小数值舍入操作方法:ceil()、floor()、round()
    javascript,子字符串操作方法:Slice()、Substr()、Substring()的区别
    javascript,第一个基于node.js的Http服务
    javascript,创建对象的3种方法
    MFC学习笔记2——MFC和Win32
    Qt下 QString转char*
    [转载] Qt程序在Windows下的mingw发布
    VC 获取当前时间
    MFC 对话框设计问题(控件的使用)
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196439.html
Copyright © 2011-2022 走看看