返回整数数组的最大联通子数组
一、程序要求
1、输入一个二维整形数组,数组中有正数也有负数。
2、求所有子数组的和的最大值,要求时间复杂度为O(n)。
3、程序要使用的数组放在一个叫input.txt的文件中,文件格式是:
数组的行数,
数组的列数,
每一行的元素,(用逗号分开)
4、每一个数字都是有符号32位整数,当然,行数和列数都是正整数。
二、程序设计思想
将二维矩阵转换成图的形式,即相邻两个数之间是联通的,记长度为1;根据图的遍历,将整个图从每个点都开始遍历一遍,便利时,当和小于0时断开两点间的路,当和大于最大和时最大和更新,这样,取以每个点为起点遍历的和的最大值即时最大联通子数组的和。遍历时,选取已遍历的联通子数组周围最大值遍历。
三、源程序
//李俏、张莹荧,2016.4.2
//求整数数组的最大子数组的和
#include<iostream> #include<fstream> #include<ctime> using namespace std; #define N 100 typedef struct { int dian[N]; int xian[N][N]; int diannum;//数组中元素个数 }Tu;//图 void set(Tu &shuzu,int x,int y) { int i,j; fstream infile("input.txt",ios::in); //打开指定文件 if(!infile) { cout<<"open error!"<<endl; exit(1); } infile>>x>>y; //从文件中读取数组行数和列数 shuzu.diannum=x*y; for(i=1;i<=shuzu.diannum;i++)//从文件中读取数组元素 { infile>>shuzu.dian[i]; } infile.close(); for(i=1;i<=shuzu.diannum;i+=y) { for(j=i;j<=i+y-2;j++) { shuzu.xian[j][j+1]=1; shuzu.xian[j+1][j]=1; } } for(i=1+y;i<shuzu.diannum;i+=y) { for(j=i;j<=i+x-1;j++) { shuzu.xian[j][j-y]=1; shuzu.xian[j-y][j]=1; } }//将一维数组转换成二维图的形式 } void output(Tu shuzu)//以图的形式输出数组 { for(int i=1;i<=shuzu.diannum;i++) { cout<<shuzu.dian[i]; if(shuzu.xian[i][i+1]==1) cout<<" "; else cout<<endl; } } void bianli(Tu &shuzu,int v,int visit[],int &b,int &max,int x)//遍历图 { visit[v]=1; max+=shuzu.dian[v]; if(max>=b) b=max; int a=0,bo=0; for(int w=1;w<=shuzu.diannum;w++) { for(int c=1;c<=shuzu.diannum;c++) { if((visit[w]==0)&&(shuzu.xian[c][w]==1)&&(visit[c]==1)) { a=w; bo=1; break; } } if(bo==1) { break; } } for(int w=1;w<=shuzu.diannum;w++) { for(int c=1;c<=shuzu.diannum;c++) { if((visit[w]==0)&&(shuzu.xian[c][w]==1)&&(visit[c]==1)) { if(shuzu.dian[a]<shuzu.dian[w]) { a=w; } } } } if(b+shuzu.dian[a]<0) { shuzu.xian[v][a]=0; } else { bianli(shuzu,a,visit,b,max,x); } } int NoVisit(int visit[],Tu shuzu) { int k=0,i; for(i=1;i<=shuzu.diannum;i++) { if(visit[i]==0) { k=i; break; } } return k; }//判断图中没有visit的项 int main() { Tu shuzu; int x,y; int i; fstream infile("input.txt",ios::in); //打开指定文件 if(!infile) { cout<<"open error!"<<endl; exit(1); } infile>>x>>y; //从文件中读取数组行数和列数 for(i=1;i<=x*y;i++) { infile>>shuzu.dian[i]; } infile.close(); set(shuzu,x,y); cout<<"数组为:"<<endl; output(shuzu); int v=1,b[N]={0},h=0; for(i=1;i<=shuzu.diannum;i++) { if(shuzu.dian[i]<0) { b[i]=shuzu.dian[i]; } else { int visit[N]={0}; int max=0; bianli(shuzu,i,visit,b[i],max,x); } } int max=b[1]; for(int i=2;i<=shuzu.diannum;i++) { if(b[i]>max) max=b[i]; } cout<<"最大联通子数组的和为:"<<max<<endl; return 0; }
四、结果截图
五、心得体会
刚开始,没有思路。老师上课时给了一个思路,但是由于自己的能力不足,未能实现。说到联通就想到了图的知识,经过翻书和查资料要把数组转化为图,再求。实现起来很是吃力,通过同学的帮助,得到了上面程序。通过本次实验,我认识到自己的能力严重不足,要加强练习,努力提高。
六、时间记录表:
学生: 李 俏 日期 :2016年4月6日
教师: 王建民 课程 :软件工程
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间 | 活动 | 备注 |
3.31 | 16:30 | 17:00 | 无 | 30 | 编写程序 | 作业 |
4.1 | 14:10 | 15:50 | 30 | 60 | 编写程序 | 作业 |
4.4 | 15:30 | 18:20 | 20 | 180 | 编写程序 | 作业 |
4.5 | 14:20 | 15:30 | 10 | 60 | 编写程序 | 作业 |
4.6 | 12:30 | 13:30 | 无 | 60 | 编写程序 | 作业 |
七、缺陷记录日志:
学生 李俏,张莹荧
日期 2016年4月6日
教员 王建民
程序号 4
日期 | 编号 | 类型 | 引入阶段 | 排除阶段 | 修复时间 | 修复缺陷 |
4.4 | 1 | 数组 | 设计 | 编译 | 15min | |
描述:数组长度不合适,导致元素缺失 | ||||||
4.6 | 2 | 文件 | 设计 | 编译 | 30min | |
描述:没有考虑好,把问题想复杂了,不能有效地从文件中读出数据 |
八、工作照片
小伙伴:张莹荧(http://www.cnblogs.com/zhyying/)