用c++求一個二維整數陣列中最大子陣列之和(結對作業)
題目:返回一個二維整數陣列中最大子陣列之和。
要求:
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個小時。結對開發讓我們懂得了同伴的重要,合作的高效率。