题目要求:
Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.
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 corner:
9 2
-4 1
-1 8
and has a sum of 15.
题目要求是对于给定的n*n的矩阵,要求其和最大的子矩阵.对于n*n的矩阵,任意的子矩阵只需要确定其左上角坐标(i1,j1)以及右下角坐标(i2,j2),也就是可以用4个参数(i1,j1,i2,j2)确定一个子矩阵,要把其所有子矩阵都单独去考虑,此时需要的时间复杂度为O(n^4),因为n最多可能为100,用O(n^4)的算法就会出现超时.要考虑一个比O(n^4)复杂度更低的算法. 矩阵问题为二维的情形,我们先把问题简单化,考虑一维的情况,如(9 2 -6 2),求其最大的子矩阵,也就相当于最大子段和问题.最大子段和问题我们可以在0(n)时间内完成,如何去做,请先自行思考.
一维的情况能在O(n)时间内去完成,二维的情况我们可以转换成一维的情况去实现.
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
如题目所给的sample数据分别可以看成以下一维的情况:
(0 -2 -7 0);
(9 2 -6 2);
(-4 1 -4 1);
(-1 8 0 -2);
(0+9,-2+2,-7+-6,0+2);.......
总共有O(n^2)种可能,每种可能花O(n)时间,总共可以在O(n^3)完成.
实现代码如下:
1 #include<stdio.h>
2 #define MAX 100
3
4 int Input[MAX][MAX];
5 int Max_line[MAX];
6
7 int Max_num(int n,int *a)
8 {
9 int max = *a;
10 int i;
11 for(i=0;i<n;i++)
12 {
13 if(*(a+i)>max)
14 max = *(a+i);
15 }
16
17 return max;
18 }
19
20 //得到一维数组的最大子段和
21 int MaxSum_1(int n,int *a)
22 {
23 int sum=0,b=0;
24 int i;
25 for(i=0;i<n;i++)
26 {
27 if(b>0) b+=*(a+i);
28 else b = *(a+i);
29 if(b>sum) sum = b;
30 }
31 return sum;
32 }
33
34 void InputFun(int length)
35 {
36 int i,j;
37 for(i = 0;i<length;i++)
38 for(j = 0;j<length;j++)
39 {
40 scanf("%d",&Input[i][j]);
41 }
42
43 }
44
45
46 main()
47 {
48
49
50
51 int i,j,length,z,s;
52 // printf("请输入二维数组大小:");
53 scanf("%d",&length);
54 if(length>100)
55 {
56 printf("超出范围!");
57 }
58 else
59 {
60
61 InputFun(length);
62
63 }
64 //单行
65 for(z=0;z<length;z++)
66 {
67 Max_line[z]=MaxSum_1(length,Input[z]);
68 }
69
70 int max = Max_num(length,Max_line); //一维时最大子段值
71
72 // printf("%d",max);
73 int y,k;
74
75 for(k=0;k<length-1;k++)
76 {
77 for(z=k+1;z<length;z++)
78 {
79
80 //循环执行次数
81
82 for(y=0;y<length;y++)
83 {
84 Max_line[y]=0;
85 //每一列累加
86 for(s=k;s<z+1;s++)
87 {
88 Max_line[y]+=Input[s][y];
89 }
90
91 }
92
93 int max1 = MaxSum_1(length,Max_line);
94 if(max1>max)
95 max=max1;
96
97 }
98
99 }
100
101
102 printf("%d\n",max);
103
104 }