zoukankan      html  css  js  c++  java
  • noi openjudge 1768:最大子矩阵

    链接:http://noi.openjudge.cn/ch0406/1768/

    描述
    已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[-127, 127]。
    输出
    输出最大子矩阵的大小。
    样例输入
    4
    0 -2 -7 0 9 2 -6 2
    -4 1 -4 1 -1

    8 0 -2
    样例输出
    15

    芒果君:第一次看到这道题,还是在贪心里,就特别懵逼,后来dalao教我用矩阵前缀和来写,画个图的话就很容易理解啦~

    (a:元素,sum:从a(1,1)到a(i,j)所有值的和,就是前缀和。)

    边读入边求前缀和(sum),用这个公式来求:①+②+③-④ 得出sum(5,3)=a(5,3)+sum(4,3)+sum(5,2)-sum(4,2);

    好像有点递推思想呢?

    然后四重循环暴力枚举所有子矩阵,找到最大值!

    公式:①-②-③+④,枚举出(2,2)到(5,3)的矩阵大小t=sum(5,3)-sum(5,1)-sum(1,3)+sum(1,1),更新最大值。代码如下——

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int ju[110][110],sum[110][110],n,i,j,k,l,ans;
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     for(i=1;i<=n;++i)
     9         for(j=1;j<=n;++j){
    10             scanf("%d",&ju[i][j]);
    11             sum[i][j]=ju[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    12         }
    13     for(i=1;i<=n;++i)
    14         for(j=1;j<=n;++j)
    15             for(k=1;k<=i;++k)
    16                 for(l=1;l<=j;++l)
    17                     ans=max(ans,sum[i][j]+sum[k-1][l-1]-sum[i][l-1]-sum[k-1][j]);
    18     printf("%d",ans);
    19     return 0;
    20 }

    然后呢,这道题用DP做就是酱紫的(参考最大子序列和)~读入的时候求每一列的前缀和,再用三重循环把它处理成子矩阵(i,j限制行的范围,k是列)。抽象的看,是由线到面的转化。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int ju[110][110],f[110],n,i,j,k,ans;
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     for(i=1;i<=n;++i)
     9         for(j=1;j<=n;++j){
    10             scanf("%d",&ju[i][j]);
    11             ju[i][j]+=ju[i-1][j];
    12         }
    13     for(i=1;i<=n;++i)
    14         for(j=1;j<i;++j){
    15             for(k=1;k<=n;++k)
    16                 f[k]=ju[i][k]-ju[j][k];        
    17             for(k=1;k<=n;++k){
    18                 f[k]=max(f[k],f[k-1]+f[k]);
    19                 ans=max(ans,f[k]);
    20             }
    21         }
    22     printf("%d",ans);
    23     return 0;
    24 }

    各位dalao看懂了吗?没看懂也不关我的事~

    (最后不负责任的博主在一片骂声中点下了保存修改)

  • 相关阅读:
    【需求征集系统】打卡(五)
    【需求征集系统】打卡(五)
    《需求分析与系统设计》阅读笔记(一)
    每周总结【2020/10/24】————Redis与Mongodb初学
    【需求征集系统】打卡(四)
    【需求征集系统】打卡(三)
    初步自学Java小结
    关于“教室派”APP的使用报告和相关建议
    冲刺第一天
    结对开发之求环形数组的最大值
  • 原文地址:https://www.cnblogs.com/12mango/p/6803315.html
Copyright © 2011-2022 走看看