zoukankan      html  css  js  c++  java
  • 用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个小时。结对开发让我们懂得了同伴的重要,合作的高效率。

  • 相关阅读:
    poj 3304 直线与线段相交
    poj 2318 叉积+二分
    AC自动机
    MySQL报错:Packets larger than max_allowed_packet are not allowed 的解决方案
    SCOPE_IDENTITY的作用
    Truncate table、Delete与Drop table的区别
    .Net Attribute特性
    vs2010 调试快捷键
    TFS和VSS的简单对比
    做网站用UTF-8还是GB2312 & 各国语言对应字符集
  • 原文地址:https://www.cnblogs.com/yinianzs/p/9821223.html
Copyright © 2011-2022 走看看