项目组成员:刘静(20092532),解凤娇(20112878),王洪叶(20112886)

          项目  名称:二维数组求子数组和的最大值

          项目  分析:对于一位数组求子数组的和的最大值,我们使用了穷举法,比较容易的得出了正确的结果,可是对于二维数组来说,难度确实是增加了,而且如果使用穷举法,就会使程序的复杂度大大增加。时间复杂度为O(n^5)。

 

 1 int getMaxSum(int **array, int m, int n)
 2 {
 3   int maxSum =0;//最大初始值
 4   int tempSum = 0;//临时存储子数组的和
 5 
 6   int i,j;//循环用
 7 
 8   for(i=0;i<m;i++)
 9   {
10       for(j=0;j<n;j++)
11      {
12            maxSum += array[i][j];
13      }
14   }
15   for(xb=0;xb<m;xb++)
16   {
17     for(yb=0;yb<n;yb++)
18     {    
19       for(xa=0;xa<=xb;xa++)
20       {
21         for(ya=0;ya<=yb;ya++)
22         {
23            tempSum = 0;
24            for(i=xa;i<xb;i++)
25            {
26               for(j=ya;j<yb;j++)
27               {
28                 tempSum += array[i][j];
29               }
30            }
31            if(tempSum > maxSum)
32            {
33              maxSum = tempSum;
34            }                
35         }
36       }
37     }
38   }
39   return (maxSum)
40 }
View Code

                 进一步改进程序确实有点困难,是想到了使用二维变一维的方法,但是具体实施的时候,困难重重,所以参考了网上的部分代码,稍微有些初步的认识,首先是获取部分数组的和的数组。

                             

1 int sum1(int **PS,int imin,int imax,int j)  
2 {  
3     return PS[imax][j]-PS[imax][j-1]-PS[imin-1][j]+PS[imin-1][j-1];  
4 }  
View Code
//部分代码
for (i=0;i<=n;i++)  
    {  
        PS[i][0]=0;  
    }  
    for (j=0;j<=m;j++)  
    {  
        PS[0][j]=0;  
    }  
    for (i=1;i<=n;i++) //求部分数组的和 
    {  
        for (j=1;j<=m;j++)  
        {  
            PS[i][j]=array[i][j]+PS[i][j-1]+PS[i-1][j]-PS[i-1][j-1]; //表示以(0,0)为起点,以(i,j)为终点的连续子数组的和 
        }  
    }      
View Code

     最后通过循环遍历部分数组和的数组获取子数组的最大值。

#include<iostream>  
#include<windows.h>
using namespace std; 
int sum1(int **PS,int imin,int imax,int j);
int Maxsum(int **PS,int **array,int m,int n)
{
    int Start,All;    
    int a,c; 
    int i,j;
    int MaxSum=-1; 

    for (i=0;i<=n;i++)  
    {  
        PS[i][0]=0;  
    }  
    for (j=0;j<=m;j++)  
    {  
        PS[0][j]=0;  
    }  
    for (i=1;i<=n;i++) //求部分数组的和 
    {  
        for (j=1;j<=m;j++)  
        {  
            PS[i][j]=array[i][j]+PS[i][j-1]+PS[i-1][j]-PS[i-1][j-1]; //表示以(0,0)为起点,以(i,j)为终点的连续子数组的和 
        }  
    }      
    for (a=1;a<=n;a++) //枚举求子数组(转换为一维数组)最大值  
    {  
        for (c=a;c<=n;c++)  
        {  
            Start=sum1(PS,a,c,m);  
            All=sum1(PS,a,c,m);  
            for (i=m-1;i>=1;i--)  
            {  
                if(Start>0)
                    Start+=sum1(PS,a,c,i);
                else
                    Start=sum1(PS,a,c,i);
                if(Start>All)
                    All=Start;
            }  
            if(All>MaxSum)
            {
                MaxSum=All;
            }
            
        }  
    }  
       cout<<"该二维数组的子数组的最大值为:"<<MaxSum<<endl;
    return 0;
}
int sum1(int **PS,int imin,int imax,int j)  
{  
    return PS[imax][j]-PS[imax][j-1]-PS[imin-1][j]+PS[imin-1][j-1];  
}  
int main()  
{
    int m,n;
    int i,j,k=1;
    int **PS;
    int **array;
    do{
        cout<<"请输入n行m列,以空格隔开:";  
        cin>>n>>m;
        cout<<endl;
        PS=(int **)malloc(sizeof(int*)*(n+1));  
        array=(int **)malloc(sizeof(int*)*(n+1));  
        for (i=0;i<=n;i++)  
        {  
            PS[i]=(int *)malloc(sizeof(int)*(m+1));  
            array[i]=(int *)malloc(sizeof(int)*(m+1));  
        }  
        cout<<"请输入"<<n<<""<<m<<"列数字:"<<endl;  
        for (i=1;i<=n;i++)  
        {  
            for (j=1;j<=m;j++)  
            {  
                cin>>array[i][j];  
            }  
        }   
        Maxsum(& *PS,& *array,m,n);    
        system("pause");
        cout<<endl;
        cout<<"        1、继续"<<endl;
        cout<<"        0、退出"<<endl;
        cin>>k;
    }while(k!=0);
    return 0;  
    
} 
View Code

     实验结果截图:

                                               

       实验心得:通过这几节小课的小实验,慢慢发现要想写好一个程序,真的很难,得考虑程序的规范、程序的时间复杂度、程序所能承受多大的考验(程序测试),脚踏实地最靠谱,加油!
      

posted on 2014-03-18 19:54  夜雨闻香  阅读(586)  评论(1编辑  收藏  举报