利用动态规划思想解题(1)

题目要求:

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 }

 

 

转载于:https://www.cnblogs.com/SCAU_que/articles/1886889.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值