最大连通子数组的和

Posted 微微芋头

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大连通子数组的和相关的知识,希望对你有一定的参考价值。

一、题目要求:

1.返回一个二维数整数组中最大联通子数组的和

2.数组中有正数,也有负数

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

4.程序要使用的数组放在txt文件中

二、思路:

利用动态规划求出每一行的最大子数组

并标记最大子数组中的数flag为1

根据flag求出up[],down[],标记最大子数组起始结束位置,用来判断单个数

根据flag值判定是否联通,若联通则相加,不联通继续扫描

若有多行联通——————(bug)

若只有一行,扫描下一行与之相联通的数,若是整数则相加,负数不做动作

以此为基础形成迭代

缺陷:

由于使用动态规划做得,导致若有几行最大子数组相连时无法判断单个正数,所求最大连通子数组的和偏小

 

结对的小伙伴博客:http://www.cnblogs.com/fooreveryu/

三、代码

//求最大连通子数组和 张鹏宇 武于微
#include<iostream>
#include<cmath>
#include <fstream>
const int N = 500;
const int INF = -9999;
using namespace std;
/**************************************************************************************************************************

int Only(bool flag,int a,int b,int num1[],int *p)             //前后标志,起始位置,终止位置,动态规划部分,成功标志
{
    int p1,p2;   //开始位置结束位置
    int f1,f2;
    int max=MAXNUM(b-a,num1,&p1,&p2);
    f1=p1;
    f2=p2;
    if((flag==1&&f2<b)||(flag==0&&f1>b))//起始
        *p=0;
    else
        *p=1;
    return max;
}
*******************************************************************************************************************************/
int MAXNUM(int num,int a[],int *p,int *f)      //动态规划一维数组
{
    int dp[200][2],CMax,Q=1;
    for(int j=0;j<num;j++)
    {
        dp[j][0]=max(dp[j-1][0],dp[j-1][1]);
        dp[j][1]=max(dp[j-1][1]+a[j],a[j]);
        CMax=max(dp[j][0],dp[j][1]);
        if(dp[j][1]==a[j])
            {
                if(CMax==dp[j][1])
                {
                    *p=j;
                    *p=j;
                    Q=0;
                }
            }    
        else if(dp[j][1]==(dp[j-1][1]+a[j])&&CMax==dp[j][1])
        {
            if(Q==0)
                *f=j;
            else
                *p=j;
        }
    }
    return CMax;
}

int findMaxSubMatrix() 
{
    int num,Num,Max,number[200][200],dp[200][2],CMax[200],flag[200][200]={0},up[200],down[200],Q=1;
    ifstream in("out.txt");
    in>>num;
    in>>Num;
    for (int i=0; i<num; i++)
    {
        for (int j=0; j<Num; j++)
            in>>number[i][j];
    }

    for(int i=0;i<num;i++)/***********第N行**********/
    {
        for(int j=0;j<Num;j++)/***********前N个**********/
        {
            dp[j][0]=max(dp[j-1][0],dp[j-1][1]);
            dp[j][1]=max(dp[j-1][1]+number[i][j],number[i][j]);
            CMax[i]=max(dp[j][0],dp[j][1]);
            if(dp[j][1]==number[i][j])
            {
                for(int k=0;k<Num;k++)                
                    flag[i][k]=0;
                if(CMax[i]==dp[j][1])
                {
                    flag[i][j]=1;
                    up[i]=j;
                    down[i]=j;
                    Q=0;
                }
            }    
            else if(dp[j][1]==(dp[j-1][1]+number[i][j])&&CMax[i]==dp[j][1])
            {
                flag[i][j]=1;
                if(Q==0)
                    down[i]=j;
                else
                    up[i]=j;
            }
            else
                flag[i][j]=0;            
        }
    }    
    
    int F=1;
    for(int i=0;i<num-1;i++)     //第i行
    {
        F=1;
        int j;
        for(j=0;j<Num&&F==1;j++)     //扫描下一行
        {
            if(flag[i][j]==1&&flag[i+1][j]==1)
            {
                CMax[i]=CMax[i+1]+CMax[i];
                CMax[i+1]=CMax[i];
                F=0;
            }
        }
/*************************************************************************************************************
        if(F==0)     //两行                                                  //两行周围动态规划,失败。。。。
        {
            int p,f;
            for(int j=0;j<Num;j++)
            {
                if(up[i]>up[i+1])     //第一行行前靠后
                {
                    int DP[200][2];
                    int maxa;
                    maxa=MAXNUM(up[i]-up[i+1],number[i],&p,&f);
                    if(p>=up[i+1]&&p<=up[i])
                    {
                        for(int m=up[i+1];m<p;m++)
                            flag[i][m]=0;
                        CMax[i]=CMax[i]+maxa;
                        CMax[i+1]=CMax[i];
                    }
                    else
                    {
                        for(int m=up[i+1];m<up[i];m++)
                        {
                            if(number[i][m]>0)
                            {
                                CMax[i]=CMax[i]+number[i][m];
                                flag[i][m]=1;
                                CMax[i+1]=CMax[i];
                            }
                        }
                    }
                    
                }
                else                  //第一行行前靠前
                {
                    int DP[200][2];
                    int maxa;
                    maxa=MAXNUM(up[i+1]-up[i],number[i+1],&p,&f);
                    if(p>=up[i]&&p<=up[i+1])
                    {
                        for(int m=up[i];m<p;m++)
                            flag[i][m]=0;
                        CMax[i]=CMax[i]+maxa;
                        CMax[i+1]=CMax[i];
                    }
                    else
                    {
                        for(int m=up[i];m<up[i+1];m++)
                        {
                            if(number[i+1][m]>0)
                            {
                                flag[i][m]=1;
                                CMax[i]=CMax[i]+number[i+1][m];
                                CMax[i+1]=CMax[i];
                            }
                        }
                    }
                }
                if(down[i]>down[i+1])     //第一行后前靠后
                {
                    int DP[200][2];
                    int maxa;
                    maxa=MAXNUM(down[i]-down[i+1],number[i],&p,&f);
                    if(p>=up[i+1]&&p<=up[i])
                    {
                        for(int m=p;m<down[i];m++)
                            flag[i][m]=0;
                        CMax[i]=CMax[i]+maxa;
                        CMax[i+1]=CMax[i];
                    }
                    else
                    {
                        for(int m=down[i+1];m<down[i];m++)
                        {
                            if(number[i+1][m]>0)
                            {
                                flag[i][m]=1;
                                CMax[i]=CMax[i]+number[i+1][m];
                                CMax[i+1]=CMax[i];
                            }
                        }
                    }
                }
                else                  //第一行行后靠前
                {
                    int DP[200][2];
                    int maxa;
                    maxa=MAXNUM(down[i+1]-down[i],number[i+1],&p,&f);
                    if(p>=up[i]&&p<=up[i+1])
                    {
                        for(int m=p;m<down[i+1];m++)
                            flag[i][m]=0;
                        CMax[i]=CMax[i]+maxa;
                        CMax[i+1]=CMax[i];
                    }
                    else
                    {
                        for(int m=down[i];m<down[i+1];m++)
                        {
                            if(number[i][m]>0)
                            {
                                CMax[i]=CMax[i]+number[i][m];
                                flag[i][m]=1;
                                CMax[i+1]=CMax[i];
                            }
                        }
                    }
                }
            }
        }

*************************************************************************************************************/
   
 /*********************************************************************************************************       
        if(F==0)    //两行                                            //两行未完成
        {          
            int p,nummax,arry[200],arry1[200];
            int an[4];
            for(int m=0;m<Num;m++)
            {
                arry[m]=number[i][m];
                arry1[m]=number[i+1][m];
            }
            if(up[i]>up[i+1])
            {
                nummax=Only(1,up[i+1],up[i],arry,&p);
                an[0]=p;
            }
            else 
            {
                nummax=Only(1,up[i],up[i+1],arry1,&p);
                an[1]=p;
            }
            if(down[i]>down[i+1])
            {
                nummax=Only(0,down[i+1],down[i],arry1,&p);
                an[2]=p;
            }
            else
            {
                nummax=Only(0,down[i],down[i+1],arry,&p);
                an[3]=p;
            }
            
        }
**************************************************************************************************************/
        if(F==1)    //一行
        {
            for(int k=0;k<Num;k++)
                flag[i+1][k]=0;
            for(int j=up[i];j<down[i]+1;j++)
            {
                if(number[i+1][j]>0)
                {
                    flag[i+1][j]=1;
                    CMax[i]=CMax[i]+number[i+1][j];
                    CMax[i+1]=CMax[i];
                }
            }
        }
    }

    Max=CMax[0];
    for(int i=1;i<num;i++)
        if(CMax[i]>Max)
            Max=CMax[i];
    return Max;
}

int main()
{
    int M;
    ofstream outfile;
    outfile.open("out.txt",ios::out|ios::app);
    if(!outfile)
    {
        cout<<"open error!"<<endl;
    }
    M=findMaxSubMatrix();
    outfile<<endl;
    outfile<<"最大子数组的和为: "<<M<<endl;
    outfile.close();
}

四、运行结果截图

五、项目计划总结:

日期&&任务

听课

编写程序

阅读相关书籍

网上查找资料

  日总计

周一

2

2

1

1

6

周二

 

2

1

1

4

周三

 

1

2

2

5

周四

2

1

1

1

5

周五

 

4

1

1

6

周六

 

2

 

 

2

周日

 

4

2

 

6

周总计

4

16

8

6

34

 时间记录日志:

日期

开始时间

结束时间

中断时间

净时间

活动

备注

3/28

14:00

15:50

10

100

听课

软件工程上课

 

16:10

18:30

20

120

编写程序

合作编写求最大连通子数组和的程序

 

19:00

20:10

10

60

编程,网上查资料

编写求最大连通子数组和,上网查找相关资料

 

21:00

22:00

 

60

阅读书籍

《构建之法》

3/29

18:30

22:30

20

220

查资料,编写程序

编写求最大连通子数组和的程序,查阅相关资料,改善程序不足

3/30

16: 00

22:10

90

280

阅读书籍,编写程序

学习安卓知识,试编写安卓版四则运算3 

3/31

14:00

15:50

10

100

听课

软件工程上课

 

19:00

22:30

30

180

阅读书籍资料,编写程序

合作编写安卓版四则运算3,学习相关安卓知识

4/1

14:00

18:30

10

230

编写程序

合作编写安卓版四则运算3程序,请教同学相关知识

 

19:30

20:40

10

60

阅读书籍资料

学习安卓知识

 

22:20

23:30

 

70

阅读书籍

《构建之法》

4/2

19:00

21:50

30

140

编写程序

合作编写安卓版四则运算3程序

4/3

14: 30

18:30

 

240

编写程序

合作编写安卓版四则运算3程序

 

20:10

21:30

20

60

阅读书籍

《构建之法》

 

 

 

缺陷记录日志:

日期

编号

类型

引入阶段

排除阶段

修复时间

修复缺陷

3/28

1

 

讨论思路

阅读数据结构书

60min

 

 

描述:求一个二维数组中最大连通子数组的和时,没有达到目标要求

3/30

2

 

编码

编译

60min

 

 

描述:二维数组中最大连通子数组的和,由于使用动态规划做得,导致若有几行最大子数组相连时无法判断单个正数,所求最大连通子数组的和偏小,还有待解决

以上是关于最大连通子数组的和的主要内容,如果未能解决你的问题,请参考以下文章

二维数组求最大连通子数组的和

求数组中最大子数组的和03

返回二维数组子数组联通和最大

返回一个二维整数数组中最大子数组的和

课堂练习:返回一个二维数组中最大子数组的和

返回一个整数数组中最大子数组的和