最大联通子数组
#include<iostream> #define N 100 #include<ctime> using namespace std; typedef struct { int dian[N]; int xian[N][N]; int dianx,xianx; }A; void set(A &shu,int x,int y)//xy分别是行数和列数 { shu.dianx=x*y; srand((unsigned)time(NULL)); for(int i=1;i<=shu.dianx;i++) { shu.dian[i]=rand()%10; if(rand()%2==1) shu.dian[i]=shu.dian[i]*(-1); }//////////////////////////////////////////////////////随机生成数组的数 for(int i=1;i<=shu.dianx;i+=y) { for(int j=i;j<=i+y-2;j++) { shu.xian[j][j+1]=1; shu.xian[j+1][j]=1; } } for(int i=1+y;i<shu.dianx;i+=y) { for(int j=i;j<=i+x-1;j++) { shu.xian[j][j-y]=1; shu.xian[j-y][j]=1; } }////////////////////////////////////////////////////将随机生成的一维数组转换成二维的图的形式 } void output(A shu) { for(int i=1;i<=shu.dianx;i++) { cout<<"("<<shu.dian[i]<<")"; if(shu.xian[i][i+1]==1) cout<<"--"; else cout<<endl; } }////////////////////////////////////////////////////////图输出 /*void bianli(A &shu,int v,int visit[],int &b,int &max) { visit[v]=1; b+=shu.dian[v]; if(max<=b) max=b; for(int w=1;w<=shu.dianx;w++) { if((visit[w]==0)&&(shu.xian[v][w]==1)) { if(b+shu.dian[w]<0) { shu.xian[v][w]=0; } else bianli(shu,w,visit,b,max); } } } *////////////////////////////////////////////////////////遍历 /*int select(A shu,int fir,int sec,int visit[],int x) { int a,b; for(int w=1;w<=shu.dianx;w++) { if((visit[w]==0)&&(shu.xian[fir][w]==1)) { a=shu.dian[w];break; } } for(int w=1;w<=shu.dianx;w++) { if((visit[w]==0)&&(shu.xian[sec][w]==1)) { b=shu.dian[w];break; } } for(int w=1;w<=shu.dianx;w++) { if((visit[w]==0)&&(shu.xian[fir][w]==1)&&(shu.dian[w]>a)) { a=shu.dian[w]; } } for(int w=1;w<=shu.dianx;w++) { if((visit[w]==0)&&(shu.xian[sec][w]==1)&&(shu.dian[w]>b)) { b=shu.dian[w]; } } if(a>b) return fir; else return sec; }*/////////////////////////////////////////////////////当两个链接点的值相等时,判断谁周围的最大值大 void bianli(A &shu,int v,int visit[],int &b,int &max,int x) { visit[v]=1; max+=shu.dian[v]; if(max>=b) b=max; int a=0,bo=0; for(int w=1;w<=shu.dianx;w++) { for(int c=1;c<=shu.dianx;c++) { if((visit[w]==0)&&(shu.xian[c][w]==1)&&(visit[c]==1)) { a=w;bo=1;break; } } if(bo==1) break; } for(int w=1;w<=shu.dianx;w++) { for(int c=1;c<=shu.dianx;c++) { if((visit[w]==0)&&(shu.xian[c][w]==1)&&(visit[c]==1)) { if(shu.dian[a]<shu.dian[w]) a=w; /*else if((shu.dian[a]==shu.dian[w])&&(a!=w)) a=select(shu,a,w, visit, x);*/ } } } if(b+shu.dian[a]<0) { shu.xian[v][a]=0; } else bianli(shu,a,visit,b,max,x); } ////////////////////////////////////////////////////////遍历 int NoVisit(int visit[],A shu) { int k=0,i; for(i=1;i<=shu.dianx;i++) { if(visit[i]==0) { k=i; break; } } return k; }///////////////////////////////////判断图中没有visit的项 int main() { cout<<"请输入数组行列数:"<<endl; int x,y; cin>>x>>y; A shu; set(shu,x,y); output(shu); int v=1,b[N]={0},h=0; /* while(v) { bianli(shu,v,visit,b[h],max); v=NoVisit(visit,shu); h++; if(shu.dian[v]<0) { visit[v]=1; b[h]=shu.dian[v]; h++; } } */ for(int i=1;i<=shu.dianx;i++) { if(shu.dian[i]<0) { b[i]=shu.dian[i]; } else { int visit[N]={0}; int max=0; bianli(shu,i,visit,b[i],max,x); } } int max=b[1]; for(int i=2;i<=shu.dianx;i++) { if(b[i]>max) max=b[i]; } cout<<"最大联通子数组的和为:"<<max<<endl; }
思路:将二维矩阵转换成图的形式,即相邻两个数之间是联通的,记长度为1;根据图的遍历,将整个图从每个点都开始遍历一遍,便利时,当和小于0时断开两点间的路,当和大于最大和时最大和更新,这样,取以每个点为起点遍历的和的最大值即时最大联通子数组的和。遍历时,选取已遍历的联通子数组周围最大值遍历。还不能输出子数组。
感悟:老师上课举了一个思路,但是因为自己有自己的思路,所以没有按照老师的思路走,想试一试看能不能成功,事实是没有在规定的时间内完成任务。打算按照老师的方法再做一个,过几天再发吧。。。。