POJ1050 To the Max - 贪心[最大子矩阵和]

POJ1050 To the Max

传送门

题意:

给定一个\(n*n\)的带权矩阵,求一个矩阵,使矩阵内权值之和最大,输出这个矩阵的权值和。$n\leq100 $

思路:

可以利用前缀和优化,然后\(O(n^4)\)枚举矩阵的左上角和右下角,求出最大二维前缀和。

这样的枚举方案比较难以再次优化,我们考虑矩阵权值和的实质:等价于我们将矩阵每列的权值加起来,形成一个新数列,然后对这个数列求和,而最大的矩阵权值和,相当于在矩阵上下边界不变的情况下使新数列的和最大,即新数列的最大子段和。所以换种枚举方案:我们枚举矩阵的上下边界,将每列被夹在中间的权值加起来,形成一个长度为\(n\)的新数列,然后在这个数列上求最大子段和,最终答案是这\(O(n^2)\)个最大子段和的\(max\)。

AC Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500+100;
typedef long long ll;
int a[N][N];
ll sum[N][N];
ll num[N];
int main(){
    int n;
    while(~scanf("%d",&n)){
        memset(sum,0,sizeof(sum));
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
                sum[i][j]=sum[i-1][j]+a[i][j];
            }
        long long ans=-(1<<30);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                for(int k=1;k<=n;k++) num[k]=sum[i][k]-sum[j-1][k];
                long long res=-(1<<30),cnt=0;
                for(int k=1;k<=n;k++){
                    cnt+=num[k];
                    res=max(res,cnt);
                    if(cnt<0) cnt=0;
                }
                ans=max(ans,res);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
/*
4
0 -2 -7 0
9  2 -6 2
-4 1 -4 1
-1 8  0 -2

15
*/

原文地址:https://www.cnblogs.com/Loi-Brilliant/p/9611066.html

时间: 2024-10-24 14:53:58

POJ1050 To the Max - 贪心[最大子矩阵和]的相关文章

[POJ1050]To the Max(最大子矩阵,DP)

题目链接:http://poj.org/problem?id=1050 发现这个题没有写过题解,现在补上吧,思路挺经典的. 思路就是枚举所有的连续的连续的行,比如1 2 3 4 12 23 34 45 123 234 345...然后把这些行对应列相加缩成一行,之后就是求最大子序列和了. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃

[POJ1050]To the Max (矩阵,最大连续子序列和)

数据弱,暴力过 题意 N^N的矩阵,求最大子矩阵和 思路 悬线?不需要.暴力+前缀和过 代码 //poj1050 //n^4暴力 #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 105 #define INF 0x3fffffff using namespace std; int a[N][N]; int sum[N]; int ans; int

【HDU 1081】To The Max(求子矩阵元素和)

题目应该很容易看懂,是为了求一个矩阵之内最大的一个子矩阵的和. 子矩阵的和表示的是该矩阵内所有元素的和. 方法引入: 首先当然十分容易的可以想到一维求子段的和. 假设数组为a[110]; int sum = 0, MAX = 0,n; for (int i = 0; i < n; i++) { if (sum < 0) sum = 0; sum += a[i]; if (sum>MAX) MAX = sum; } 其中a[i]表示的是你所要积的范围大小,因为是一维,所以我们要积的是每一个

hdu-1081 To The Max (最大子矩阵和)

http://acm.hdu.edu.cn/showproblem.php?pid=1081 To The Max Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10874    Accepted Submission(s): 5204 Problem Description Given a two-dimensional array

POJ1050 To the MAX 想法题

题意 给一个N*N的方阵,找出一个子矩阵,使子矩阵的和最大.(n<=100) 思路 一维的情况是经典的"最大连续和问题".我们考虑把二维的问题降到一维来.我们枚举最高的层和最低的层,把他们中间的值都加到一个tmp数组里,然后用tmp数组来做"最大连续和问题",不断更新ans.那么最后得出的ans一定是最大子矩阵. 代码 #include <cstdio> #include <algorithm> #include <cstring

hdu 1081 To The Max 【最大子矩阵和】

To The Max Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8882 Accepted Submission(s): 4288 Problem Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is

HDU1081:To The Max(最大子矩阵,线性DP)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1081 自己真够垃圾的,明明做过一维的这种题,但遇到二维的这种题目,竟然不会了,我也是服了(ps:猪啊). 最终还是看了题解. 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define inf 0x3f3f3f3f using namesp

[POJ1050]To the Max(最大子段和)

题目链接 http://poj.org/problem?id=1050 题意 求最大子矩阵和. 题解 即求二维的最大子段和.二维数组sumRec[I][j]存储原始数组数据rec[0][j] to rec[I][j].那么sum[k][j]-sum[I][j]即表示从I+1到k行的第j列这一列的元素和.然后再遍历j,就变成了求一维子段和的问题.共三重循环,时间复杂度O(n^3) . 求一维最大子段和方法:每遍历一个元素,先判断之前元素的累加和若为负,则直接舍去前面的所有累加元素,因为对和更大没有

最优子矩阵问题

最优子矩阵是建立在数列连续最大和的基础上的.所谓最优子矩阵,就是指在一个n*m二维的矩阵中,确定一个小的矩阵,使这个小矩阵中所有元素的和最大. 思考一下最优子矩阵和连续最大和的异同: 1.  所求的和都具有连续性: 2.  连续最大和是一维问题,最优子矩阵是二维问题 另外,对于一个矩阵而言,如果我们将连续k行的元素纵向相加,并对相加后所得的数列求连续最大和,则此连续最大和就是一个行数为k的最优子矩阵!由此,我们可以将二维的矩阵压缩成一维矩阵,转换为线性问题,从而求解.其实就是将二维的问题,换成一