用c++求一个二维整数数组中最大子数组之和(结对作业)

题目:返回一个二维整数数组中最大子数组之和。

要求:

1.输入一个二维整形数组,数组里有正有负。

2.二维数组中连续的一个子矩阵 组成一个数组,每个子数组都有一个和。

3.求所有子数组的和的最大值。

结对编程要求

  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个小时。结对开发让我们懂得了同伴的重要,合作的高效率。

猜你喜欢

转载自www.cnblogs.com/yinianzs/p/9821223.html