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\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/10301669.html

时间: 2024-10-08 10:31:49

HihoCoder 1634 Puzzle Game(最大子矩阵和)题解的相关文章

Hihocoder 1634 Puzzle Game(2017 ACM-ICPC 北京区域赛 H题,枚举 + 最大子矩阵变形)

题目链接  2017 Beijing Problem H 题意  给定一个$n * m$的矩阵,现在可以把矩阵中的任意一个数换成$p$,求替换之后最大子矩阵的最小值. 首先想一想暴力的方法,枚举矩阵中的数,然后$O(n^{3})$求最大子矩阵更新答案,这样复杂度是$O(n^{5})$的. 思考得再仔细一些,就是包含这个数的最大子矩阵和,以及不包含这个数的最大子矩阵的和的较大值. 设原矩阵中最大子矩阵和为$mx$. 设$u_{i}$为只考虑矩阵前$i$行的最大子矩阵和,$d_{i}$为考虑矩阵第$

HihoCoder 1634 Puzzle Game

题目:https://cn.vjudge.net/problem/HihoCoder-1634 题意:给你一个矩阵,可以修改其中一个值为p,让你求最大子矩阵的最小值 我们可以暴力枚举每个点是否修改 当这个点不在最大矩阵内时,一定是它的上下左右的最大子矩阵大 当这个点在最大矩阵内时,可以直接判断 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<

hihocoder #1301 : 筑地市场 数位dp+二分

题目链接: http://hihocoder.com/problemset/problem/1301?sid=804672 题解: 二分答案,每次判断用数位dp做. #include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef long long LL; const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; //dp[x][0]表示高位还没有出

hihocoder #1224 : 赛车 dfs

#1224 : 赛车 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/1224 Description 幻想乡有一个赛车场.赛车场里有N个地点.同时地点之间还有单向的道路存在. 这些道路使得赛车场形成了一个外向树的结构.也就是说,道路将这N个地点连成了一个有根树.并且所有的边都是从父亲指向孩子的. 由于幽香喜欢刺激,每次她去赛车场都会从根节点出发,选择最长的一条路径来玩. 但是

NOI题库 1768最大子矩阵 题解

NOI题库 1768最大子矩阵  题解 总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 9 2 -4 1 -1 8 这个子矩阵的大小是15. 输入   输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依

题解+新技巧--一本通1282:最大子矩阵

http://ybt.ssoier.cn:8088/problem_show.php?pid=1282(题目传送) 虽然已知是DP,但第一眼看挺蒙的,想了想后设了个a[i][j][k][l]表示长(坐标)为i~j,宽(坐标)为k~l的矩阵,但根本找不到状态转移方程啊.后借鉴题解(https://www.cnblogs.com/GodA/p/5237061.html)后领悟到的另一种方法: 任何问题都有它的简化,看到二维,没办法时我们可以考虑一下一维:求一维数组的一个最大连续段,我们可以设b[i]

hihoCoder [Offer收割]编程练习赛3 D子矩阵求和

子矩阵求和 http://hihocoder.com/discuss/question/3005 声明一下: n是和x一起的,m是和y一起的 x是横着的,y是纵着的,x往右为正,y往下为正 (非常反常规的定义) 性质好题 看起来无从下手. 两个关键性质: 证明挺显然的.画画图 同余方程exgcd即可 子矩阵和? 先算出(0,0)的,每次平移,加减一行一列前n或m个, 细节: 1.纵向要循环到n,横向循环到m 2.注意开long long 3.反常规的设定真讨厌 #include<bits/std

【题解】Puzzle [Uva1399]

[题解]Puzzle [Uva1399] 传送门:\(\text{Puzzle [Uva1399]}\) [题目描述] 给定 \(m\) 和 \(n\),表示有 \(m\) 种不同的字符(大写字母\(A,B,C \cdots\)),\(n\) 个禁止串,请构造一个不包含任何禁止串的最长字符串 并将其输出.如果可以无限长或者无解则输出 \(No\),如果存在多解则输出字典序最大的一种. [输入] 第一行一个整数T表示数据组数. 接下来每组数据第一行为两个整数 \(m,n\),接下来 \(n\) 行

【简要题解】Hihocoder 重复旋律1-8简要题解

[简要题解]Hihocoder 重复旋律1-8简要题解 编号 名称标签 难度 1403 后缀数组一·重复旋律 Lv.4 1407 后缀数组二·重复旋律2 Lv.4 1415 后缀数组三·重复旋律3 Lv.4 1419 后缀数组四·重复旋律4 Lv.4 1445 后缀自动机二·重复旋律5 Lv.4 1449 后缀自动机三·重复旋律6 Lv.4 1457 后缀自动机四·重复旋律7 Lv.1 1465 后缀自动机五·重复旋律8 Lv.1 1466 后缀自动机六·重复旋律9 Lv.1 后缀数组 思路简单