//求最大联通子数组和 张鹏宇 武于微 /**************************************************************** 题目要求:
文件读入二维数组,计算最大联通子数组的和
1.返回一个二维数整数组中最大联通子数组的和
2.数组中有正数,也有负数
3.求所有子数组的最大值
4.程序要使用的数组放在txt文件中
*****************************************************************/ #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("Zhangpy.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; } //cout<<CMax[i]; } 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("Zhangpy.txt",ios::out|ios::app); if(!outfile) { cout<<"open error!"<<endl; } M=findMaxSubMatrix(); cout<<endl; outfile<<"最大子数组的和为: "<<M<<endl; outfile.close(); }
思路:
利用动态规划求出每一行的最大子数组
并标记最大子数组中的数flag为1
根据flag求出up[],down[],标记最大子数组起始结束位置,用来判断单个数
根据flag值判定是否联通,若联通则相加,不联通继续扫描
若有多行联通——————(bug)
若只有一行,扫描下一行与之相联通的数,若是整数则相加,负数不做动作
以此为基础形成迭代
缺陷:
由于使用动态规划做得,导致若有几行最大子数组相连时无法判断单个正数,所求最大连通子数组的和偏小
项目计划总结:
日期&&任务 |
听课 |
编写程序 |
阅读相关书籍 |
网上查找资料 |
日总计 |
周一 |
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 |
|
|
描述:二维数组中最大连通子数组的和,由于使用动态规划做得,导致若有几行最大子数组相连时无法判断单个正数,所求最大连通子数组的和偏小,还有待解决 |
小伙伴在这里:http://home.cnblogs.com/u/wuyw/