• HihoCoder 1634 Puzzle Game(最大子矩阵和)题解


    题意:给一个n*m的矩阵,你只能选择一个格子把这个格子的数换成p(也可以一个都不换),问最大子矩阵和最小可能是多少?

    思路:

    思路就是上面这个思路,这里简单讲一下怎么n^3求最大子矩阵和:枚举两行(或者两列),然后把每一列之和看做一个数字,这样二维就变成了一维,我们可以直接求最大子串和的方法。初始一个ret为0,然后从左往右加,如果ret<0,那么把ret初始化0,负数作为初始值肯定比重新开始小,然后找出ret的最大值就是最大子矩阵和。

    代码:

    #include<cstdio>
    #include<cstring>
    typedef long long ll;
    using namespace std;
    const int maxn = 150 + 10;
    const int MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    int num[maxn][maxn], sum[maxn][maxn];
    int up[maxn], down[maxn], left[maxn], right[maxn];
    int n, m, p, xx1, yy1, xx2, yy2;
    int min(int x, int y){
        return x < y? x : y;
    }
    int max(int x, int y){
        return x > y? x : y;
    }
    int mat(int x1, int y1, int x2, int y2){
        return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
    }
    int main(){
        while(~scanf("%d%d%d", &n, &m, &p)){
            memset(sum, 0, sizeof(sum));
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    scanf("%d", &num[i][j]);
                    sum[i][j] = num[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
                }
            }
    
            //上下左右四个矩阵预处理
            memset(up, -INF ,sizeof(up));
            for(int i = 1; i <= n; i++){
                int tmp = -INF;
                for(int j = 1; j <= i; j++){
                    int ret = 0;
                    for(int k = 1; k <= m; k++){
                        ret += mat(j, k, i, k);
                        tmp = max(tmp, ret);
                        if(ret < 0) ret = 0;
                    }
                }
                up[i] = max(up[i - 1], tmp);
            }
            memset(down, -INF, sizeof(down));
            for(int i = n; i >= 1; i--){
                int tmp = -INF;
                for(int j = i; j <= n; j++){
                    int ret = 0;
                    for(int k = 1; k <= m; k++){
                        ret += mat(i, k, j, k);
                        tmp = max(tmp, ret);
                        if(ret < 0) ret = 0;
                    }
                }
                down[i] = max(down[i + 1], tmp);
            }
            memset(left, -INF, sizeof(left));
            for(int i = 1; i <= m; i++){
                int tmp = -INF;
                for(int j = 1; j <= i; j++){
                    int ret = 0;
                    for(int k = 1; k <= n; k++){
                        ret += mat(k, j, k, i);
                        tmp = max(ret, tmp);
                        if(ret < 0) ret = 0;
                    }
                }
                left[i] = max(left[i - 1], tmp);
            }
            memset(right, -INF, sizeof(right));
            for(int i = m; i >= 1; i--){
                int tmp = -INF;
                for(int j = i; j <= m; j++){
                    int ret = 0;
                    for(int k = 1; k <= n; k++){
                        ret += mat(k, i, k, j);
                        tmp = max(ret, tmp);
                        if(ret < 0) ret = 0;
                    }
                }
                right[i] = max(right[i + 1], tmp);
            }
    
            int Max = -INF;
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= i; j++){
                    int ret = 0, start = 1;;
                    for(int k = 1; k <= m; k++){
                        ret += mat(j, k, i, k);
                        if(ret > Max){
                            Max = ret;
                            xx1 = j, yy1 = start, xx2 = i, yy2 = k;
                        }
                        if(ret < 0) ret = 0, start = k + 1;
                    }
                }
            }
            int ans = Max;
            for(int i = xx1; i <= xx2; i++){
                for(int j = yy1; j <= yy2; j++){
                    if(p > num[i][j]) continue;
                    ans = min(ans , max(Max - num[i][j] + p, max(up[i - 1], max(down[i + 1], max(left[j - 1], right[j + 1])))));
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    【转载】 NumPy之:数据类型对象dtype
    在深度学习的视觉VISION领域数据预处理的魔法常数magic constant、黄金数值的复现: mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225]
    关于Numpy数据类型对象(dtype)使用详解
    【转载】 大端模式和小端模式的区别是什么?
    在使用pytorch官方给出的torchvision中的预训练模型参数时为保证收敛性要求使用原始的数据预处理方式
    【转载】 解决 sudo echo x > 时的 Permission denied错误
    Javascript高级程序设计第二版前三章基本数据等笔记
    冒号课堂§3.4:事件驱动
    理解 JavaScript 闭包
    Browser clientX scrollLeft clientLeft
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10301669.html
Copyright © 2020-2023  润新知