zoukankan      html  css  js  c++  java
  • Luogu 3625 [APIO2009]采油区域

    想了很久的dp,看了一眼题解之后感觉自己被安排了。

    发现从一个矩形中选择三个不相交的正方形一共只有六种取法。

    那么我们可以处理出四个值:

    $f_{i, j}$分别表示以$(i, j)$为右下角,左下角,右上角,左上角的矩阵中选一个$k*k$正方形的最大值。

    这样就可以算出前四种情况,后两种情况只要乱搞就可以了。

    时间复杂度$O(nm)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1505;
    
    int n, m, k, ans, a[N][N], sum[N][N], s[N][N];
    int f1[N][N], f2[N][N], f3[N][N], f4[N][N], r[N], c[N];
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void chkMax(int &x, int y) {
        if(y > x) x = y;
    }
    
    inline int max(int x, int y) {
        return x > y ? x : y;
    }
    
    inline int max(int x, int y, int z) {
        return max(max(x, y), z);
    }
    
    int main() {
        read(n), read(m), read(k);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++) {
                read(a[i][j]);
                sum[i][j] = sum[i][j - 1] + a[i][j];
            }
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                sum[i][j] += sum[i - 1][j];
        for(int i = k; i <= n; i++)
            for(int j = k; j <= m; j++)
                s[i][j] = sum[i][j] + sum[i - k][j - k] - sum[i][j - k] - sum[i - k][j];
                
    /*    for(int i = 1; i <= n; i++, printf("
    "))
            for(int j = 1; j <= m; j++)
                printf("%d ", s[i][j]);      */
    
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                chkMax(f1[i][j], max(s[i][j], f1[i - 1][j], f1[i][j - 1]));
        for(int i = 1; i <= n; i++)
            for(int j = m; j >= 1; j--)
                chkMax(f2[i][j], max(s[i][j + k - 1], f2[i - 1][j], f2[i][j + 1]));
        for(int i = n; i >= 1; i--)
            for(int j = m; j >= 1; j--)
                chkMax(f3[i][j], max(s[i + k - 1][j + k - 1], f3[i + 1][j], f3[i][j + 1]));
        for(int i = n; i >= 1; i--)
            for(int j = 1; j <= m; j++)
                chkMax(f4[i][j], max(s[i + k - 1][j], f4[i + 1][j], f4[i][j - 1])); 
        
        ans = 0;
        for(int i = k; i <= n - k; i++)
            for(int j = k; j <= m - k; j++) {
                chkMax(ans, f1[i][j] + f2[i][j + 1] + f3[i + 1][1]);
                chkMax(ans, f1[i][j] + f2[n][j + 1] + f4[i + 1][j]);
                chkMax(ans, f1[n][j] + f2[i][j + 1] + f3[i + 1][j + 1]);
                chkMax(ans, f1[i][m] + f4[i + 1][j] + f3[i + 1][j + 1]);
            }
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++) {
                chkMax(r[i], s[i][j]);
                chkMax(c[j], s[i][j]);
            }
        
        for(int i = k; i <= n - 2 * k; i++)
            for(int j = i + k, mid = r[j]; j <= n - k; j++, chkMax(mid, r[j]))
                chkMax(ans, f1[i][m] + mid + f3[j + 1][1]);
        for(int i = k; i <= m - 2 * k; i++)
            for(int j = i + k, mid = c[j]; j <= m - k; j++, chkMax(mid, c[j]))
                chkMax(ans, f1[n][i] + mid + f2[n][j + 1]);
        
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Tsinsen-A1489 抽奖 【数学期望】
    jmeter正则表达式
    robotframwork的WEB功能测试(一)—切换window窗口
    Appium基础篇(一)——启动emulator
    20161114记录一件工作的事
    robotframwork数据库测试(一)——pymysql与pyodbc
    robotframwork接口测试(四)—其他库的安装
    robotframwork接口测试(三)—HttpLibrary.HTTP安装
    robotframework接口测试(二)—post request
    robotframework接口测试(一)—Get request json
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9562563.html
Copyright © 2011-2022 走看看