题目:返回一个二维整数数组中最大子数组之和。
要求:
1.输入一个二维整形数组,数组里有正有负。
2.二维数组中连续的一个子矩阵 组成一个数组,每个子数组都有一个和。
3.求所有子数组的和的最大值。
结对编程要求
- 两人结对完成编程任务。
- 一人负责程序分析,代码编程。
- 一人负责代码复审和代码测试计划
通过我两的分析,得到两种方案。
一中是通过整体压缩,先求出该二维整形数组的和,然后去掉一列或一行,有四种情况。
将这进行循环,比较去掉之后的数组和与没去掉的数组和的大小,我们取大的值,直到去掉的数组四种情况都比比没去掉的数组和小,结束循环。(切割法)
二是通过例举找出每个i*j矩阵的最大和,然后在这些最大和中找出最大值。(拓展法)
图示:(切割法)
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
四种情形:
1.
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
2.
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
3.
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
4.
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
四种情况与最初情形进行比较取最大值,进行循环直到这四种情况都比最初的小,结束循环。输出该值。
方案二:
a(0,0) |
... |
... |
a(0,j) |
... |
a(0,n) |
... |
... |
... |
... |
... |
... |
a(i,0) |
... |
... |
a(i,j) |
... |
a(i,n) |
... |
... |
... |
... |
... |
... |
a(m,0) |
... |
... |
a(m,j) |
... |
a(m,n) |
先定该集合的子机的左上角为啊a(i,j),取他的b*c和c*b矩阵(i+b<n且j+c<m),每一个a(i,j)的b*c和c*b矩阵都有一个和,然后比较出b*c和c*b矩阵和的最大值,然后比较每一个c*b和b*c的最大值,得到最终的最大值。从而输出该最大值。
b*c
a(i,j) |
... |
... |
a(i,j+c-1) |
... |
... |
... |
... |
a(i+b-1,j) |
... |
... |
a(i+b-1,j+c-1) |
c*b
a(i,j) |
... |
... |
a(i,j+b-1) |
... |
... |
... |
... |
a(i+c-1,j) |
... |
... |
a(i+c-1,j+b-1) |
一.拓展法(运算繁琐,运行易崩,只有5*5以下的矩阵可以用。局限性大)
1 #include<iostream> 2 #include<math.h> 3 using namespace std; 4 int A1[5][5]; 5 int max(int a, int b) 6 { 7 if (a > b) 8 return a; 9 else 10 return b; 11 } 12 int min(int a, int b) 13 { 14 if (a > b) 15 return b; 16 else 17 return a; 18 } 19 int findmax(int m[1000]) 20 { 21 int max = m[0]; 22 for (int i = 0; i<1000; i++) 23 if (m[i]>max) 24 max = m[i]; 25 return max; 26 } 27 int sum(int x, int y, int x1, int y1) 28 { 29 int sum = 0; 30 int i, j; 31 int maxx = max(x, x1); 32 int maxy = max(y, y1); 33 int minx = min(x, x1); 34 int miny = min(y, y1); 35 for (i = minx; i <= maxx; i++) 36 for (j = miny; j <= maxy; j++) 37 sum = sum + A1[i][j]; 38 return sum; 39 } 40 int findmaxarry(int A[5][5]) 41 { 42 int M[1000] = { 0 }; int i = 0; 43 int a, b, c, d; 44 for (a = 0; a<5; a++) 45 for (b = 0; b<5; b++) 46 for (c = 0; c<5; c++) 47 for (d = 0; d<5; d++) 48 { 49 if (a == c&&b == d) 50 { 51 M[i] = A[a][b]; i++; 52 } 53 else 54 { 55 M[i] = sum(a, b, c, d); i++; 56 } 57 } 58 return findmax(M); 59 } 60 int main() 61 { 62 63 64 for (int i = 0; i < 5; i++) 65 { 66 for (int j = 0; j < 5; j++) 67 { 68 cin >> A1[i][j]; 69 } 70 } 71 int AllMax; 72 AllMax = findmaxarry(A1); 73 cout << AllMax << endl; 74 system("pause"); 75 }
测试结果:
二.切割法(最终方案)
1 #include<iostream> 2 using namespace std; 3 int sum_Array_lift(int **p,int m,int n,int r,int le); 4 int sum_Array_right(int **p,int m,int n,int r,int le); 5 int max_shu(int a,int b); 6 int main() 7 { 8 int m,n,max_sum=0; 9 //实现整型数组的输入 10 cout<<"输入整型数组的行长度 "; 11 cin>>m; 12 cout<<"输入整型数组的列长度 "; 13 cin>>n; 14 //创建一个二维数组 15 int ** p; 16 p = new int *[m]; 17 for (int i = 0; i <m; i++) 18 { 19 p[i] = new int[n]; 20 } 21 cout<<"输入一个二维整型数组"<<endl; 22 for(int i=0;i<m;i++) 23 { 24 for(int j=0;j<n;j++) 25 { 26 cin>>p[i][j]; 27 } 28 } 29 int r=0,le=0,k1=0,k2=0; 30 max_sum=sum_Array_lift(p,m,n,r,le); 31 while(r!=m&&le!=n) 32 { 33 if(r!=m) 34 { 35 r++; 36 k1=max_shu(sum_Array_lift( p, m, n,r, le),sum_Array_right( p, m, n,r, le));//比较从第r行切和第n-1-r行切的值,取最大的给k1 37 r--; 38 } 39 if(le!=n) 40 { 41 le++; 42 k2=max_shu(sum_Array_lift( p, m, n,r, le),sum_Array_right( p, m, n,r, le));//比较从第le列切和第n-1-le列切的值,取最大的给k2 43 le--; 44 } 45 if(max_sum<max_shu(k1,k2))//让max_sum取k1和k2的最大值 46 { 47 max_sum=max_shu(k1,k2); 48 } 49 if(k1>k2) 50 { 51 r++; 52 if(sum_Array_lift( p, m, n,r, le)<sum_Array_right( p, m, n,r, le))//为了不让空间复杂度增加,我们通过改变矩阵的值 使得等同于切割后的矩阵 53 { 54 for(int j=0;j<n;j++) 55 { 56 for(int i=m-1;i>=r;i--) 57 { 58 p[i][j]=p[i-1][j]; 59 } 60 } 61 } 62 r--; 63 } 64 else 65 { 66 le++; 67 if(sum_Array_lift( p, m, n,r, le)<sum_Array_right( p, m, n,r, le))//为了不让空间复杂度增加,我们通过改变矩阵的值 使得等同于切割后的矩阵 68 { 69 for(int i=0;i<m;i++) 70 { 71 for(int j=n-1;j>=le;j--) 72 { 73 p[i][j]=p[i][j-1]; 74 } 75 } 76 } 77 le--; 78 } 79 if(r!=m) 80 { 81 r++; 82 } 83 if(le!=n) 84 { 85 le++; 86 } 87 if(k1>k2) 88 { 89 le--; 90 } 91 else r--; 92 } 93 cout<<"二维数组最大子数组之和为 "<<max_sum<<endl; 94 return 0; 95 } 96 int sum_Array_lift(int **p,int m,int n,int r,int le) 97 { 98 int sum=0; 99 for(int i=r;i<m;i++) 100 { 101 for(int j=le;j<n;j++) 102 { 103 sum=sum+p[i][j]; 104 } 105 } 106 return sum; 107 } 108 int max_shu(int a,int b) 109 { 110 if(a>b) 111 { 112 return a; 113 } 114 else return b; 115 } 116 int sum_Array_right(int **p,int m,int n,int r,int le) 117 { 118 int sum=0; 119 for(int i=m-1-r;i>=0;i--) 120 { 121 for(int j=n-1-le;j>=0;j--) 122 { 123 sum=sum+p[i][j]; 124 } 125 } 126 return sum; 127 }
测试结果:
总结
通过自己设计的算法,并实现。需要将难的不会的分解或转化为我们能实现的,逻辑思维很重要。估计5个小时,实际6个小时。结对开发让我们懂得了同伴的重要,合作的高效率。