zoukankan      html  css  js  c++  java
  • UVA108Maximum Sum子矩阵最大和(最大连续子序列的变形)+降维处理+dp

    A problem that is simple to solve in one dimension is often much more difficult to solve in more than one dimension. Consider satisfying a boolean expression in conjunctive normal form in which each conjunct consists of exactly 3 disjuncts. This problem (3-SAT) is NP-complete. The problem 2-SAT is solved quite efficiently, however. In contrast, some problems belong to the same complexity class regardless of the dimensionality of the problem. Given a 2-dimensional array of positive and negative integers, find the sub-rectangle with the largest sum. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the subrectangle with the largest sum is referred to as the maximal sub-rectangle. A sub-rectangle is any contiguous sub-array of size 1 × 1 or greater located within the whole array. As an example, the maximal sub-rectangle of the array:

                 0      −2     −7     0

                 9       2      −6     2

                −4     1      −4      1

                −1     8       0     −2

    is in the lower-left-hand corner:     9    2

                     −4    1

                    −1     8         and has the sum of 15.

    Input

    The input consists of an N × N array of integers. The input begins with a single positive integer N on a line by itself indicating the size of the square two dimensional array. This is followed by N2 integers separated by white-space (newlines and spaces). These N2 integers make up the array in row-major order (i.e., all numbers on the first row, left-to-right, then all numbers on the second row, left-to-right, etc.). N may be as large as 100. The numbers in the array will be in the range [−127, 127]. Output The output is the sum of the maximal sub-rectangle.

    Sample Input

    0      −2     −7     0

    9       2      −6     2

    −4     1      −4      1

    −1     8       0     −2

    Sample Output

    15

    题意:从所给的 N × N 的矩阵中选出任意矩阵,使其中的元素和最大

    思路:

      枚举i、j,然后对j进行降维压缩,再对降维后的一维数组求最大子序列(利用动态规划)即可。

      (还看到一种写法,但是不是特别理解:枚举行区间,求出每列的和,再用d[i]=max(d[i-1]+sum[i],sum[i])动态规划公式,即可求出最大子矩阵和。

    降维压缩代码:

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #define inf 0x3f3f3f3f
     5 using namespace std;
     6 
     7 int a[220][220];
     8 int c[220];
     9 int dp[220];
    10 int main()
    11 {
    12     std::ios::sync_with_stdio(false);
    13     int n;
    14     cin>>n;
    15     for(int i=0; i<n; i++)
    16     {
    17         for(int j=0; j<n; j++)
    18         {
    19             cin>>a[i][j];
    20         }
    21     }
    22     int ans=-inf;
    23     for (int i=0; i<n; i++) //n行
    24     {
    25         memset(c,0,sizeof(c));
    26         for (int j=i; j<n; j++) //n行
    27         {
    28             //对i到j行矩阵进行降维操作
    29             for (int k=0; k<n; k++) //n列
    30             {
    31                 c[k]+=a[j][k];
    32             }
    33             dp[0]=c[0];//对降维后的数组c[k]进行最大子序列和的动态规划
    34             if (ans<dp[0])
    35             {
    36                 ans = dp[0];
    37             }
    38             for(int k=1;k<n;k++)// n列
    39             {
    40                 dp[k]=max(dp[k-1]+c[k],c[k]);
    41                 if (ans<dp[k])
    42                 {
    43                     ans = dp[k];
    44                 }
    45             }
    46         }
    47     }
    48     cout<<ans<<endl;
    49     return 0;
    50 }
    View Code

    不是特别理解的代码:

    枚举行区间,求出每列的和,再用d[i]=max(d[i-1]+sum[i],sum[i])动态规划公式,即可求出最大子矩阵和。

     1 #include<iostream>
     2 #define inf 0x3f3f3f3f
     3 using namespace std;
     4 
     5 int a[220][220];
     6 int main()
     7 {
     8     std::ios::sync_with_stdio(false);
     9     int n;
    10     cin>>n;
    11     for(int i=1; i<=n; i++)
    12     {
    13         for(int j=1; j<=n; j++)
    14         {
    15             cin>>a[i][j];
    16             a[i][j]+=a[i-1][j];
    17         }
    18     }//每一行等于加上上面一行的和
    19     int maxx=a[1][1];
    20     for(int i=0; i<=n; i++)
    21     {
    22         for(int j=i+1; j<=n; j++)
    23         {
    24             int sum=0;
    25             for(int k=1;k<=n;k++)
    26             {
    27                 sum+=a[j][k]-a[i][k];
    28                 if(sum<0)
    29                     sum=0;
    30                 if(sum>maxx)
    31                     maxx=sum;
    32             }
    33         }
    34     }
    35     cout<<maxx<<endl;
    36 
    37 
    38     return 0;
    39 }
    View Code
  • 相关阅读:
    Proguard打包混淆报错:can't find superclass or interface
    proguard returned with error code 1.异常的解决方法
    android 混淆配置
    解决android混淆编译出现Proguard returned with error code 1和文件名、目录名或卷标语法不正确错误
    Eclipse提示No java virtual machine
    [mysql]数据库查询实例
    [算法]高效求素数
    [笔试]程序员面试宝典
    [linux]进程间通信IPC
    [linux]信号的捕获和处理
  • 原文地址:https://www.cnblogs.com/OFSHK/p/11221738.html
Copyright © 2011-2022 走看看