浏览器标题切换
浏览器标题切换end

UVA-108-Maximum 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

 

posted @ 2019-07-21 16:52  抓水母的派大星  阅读(220)  评论(0编辑  收藏  举报