最大子序列(P1085),子矩阵( P1086)存一下思路

来源:互联网 发布:网络课程视频加速器 编辑:程序博客网 时间:2024/06/16 19:32

彩笔自娱自乐 大神无视即可~~~

首先是子序列....

【问题描述】  
  给出一个长度为 N 的序列A[1]、A[2]、…、A[N],求最大连续和。换句话说,要找到1<=i<=j<=N,使得 A[i]+A[i+1]+…+A[j] 尽量大。    【输入格式】  
  第一行一个整数 N,接下来的 N 行,每行一个整数,第 i+1 行为 A[i](-10000 <= A[i] <= 10000)。暴力算法就不说了... 过50分ok

100分如下(from Mr.He)

void ready()  //用来计算从A[1]到A[i]的所有数的和 预处理,可以在输入数据时完成,此处单独写出{ sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+A[i];  //从A[1]...A[i-1]的和已经计算好,只需加上A[i]即可}

接下来是核心部分(from Mr.He)

先举例示意一下:
   a1  a2  a3  a4  a5  a6  a7  a8  a9  a10........假定现在i=8,则sum[8]可以括起来表示:

(                                               (                        i)      

( 1   2    3    4  -222)10....... 

假定a1--a5的和是前面最小的,则要舍弃:因为可能中间有负数会使相加反而变小,比如:a1--a6:1 2 3  4 -222 10;sum[5]=-212;   a6=10,a6反倒比sum[5]大。于是从a6重新取。

 -222前面的无法取到,就要从10重新取;舍去1 2 3  4 -222 的和;写出来:sum[8]-sum[5];  如果是 100 100 100 100 -1 100 则可以保留

但是这样就每次都要从头找一遍最小的sum;于是设置一个minv,比如minv现在=sum[5]=-212,但如果sum[7]=-10000,那么minv就等于sum[7];

于是变成 sum[8]-minv;minv=(sum[i],minv);


现在需要判断最大值,就比较简单了

best=(sum[i]-minv,best)   sum[i]减去之前最小的子序列就是到这个位置的最大子序列 


void solve100(){ ready();  //预处理,之前已给出int minv=0,best=A[1];  //假设最佳就是A[1] for(int i=1;i<=N;i++) { best=max(best,sum[i]-minv);    minv=min(minv,sum[i]); } printf("%d\n",best);}

接下来就是子矩阵

先示意:
子序列等于是以下情形

a1 a2 a3 a4 a5 a6

     (                 )       仅是圈几    个   a2~a5


推广到子矩阵:

a1 a2 a3 a4 a5 a6   高1    先把高为1时的a2~a5加起来,包括1*4个数,与max比较大小

a1 a2 a3 a4 a5 a6   高2    再把高为2时的a2~a5整条加起来,包括2*4个数  与max比较

a1 a2 a3 a4 a5 a6   高3    类似.....

a1 a2 a3 a4 a5 a6   高4

    (                  )        圈的是几   条    a2~a5,每条最大高4;只需从高为1开始到高为4,每次计算1~4条(此时可视作一个数)的最大子序列,每条的和存入A数组


于是可以把“条”的最大高度枚举一遍;比如矩阵高6 那么可以每条可以高1~6   

代码如下(from Mr.He)

int best=a[1][1],t;for(i=1;i<=M;i++) //a 的第 i 行起{ memset(A,0,sizeof(A));  //(A数组存的是每一条目前的和)for(j=i;j<=M;j++) //把第 i 行到第 j 行之间的每一列压缩成 A[1]..A[N](i,j枚举的是“条”的最大高度){ for(k=1;k<=N;k++) A[j]+=a[i][j] //递推压缩   (从高为1开始算起,每次多加一行) 计算 A[1]..A[N]的最大连续子序列和 t; best=max(best,t);}}

大神无视即可~~~



【提交】【记录】【状态】【讨论】【题解】【训练题】最大连续子序列[1]  
 时间限制:1秒   内存限制:64M       【问题描述】  
  给出一个长度为 N 的序列A[1]、A[2]、…、A[N],求最大连续和。换句话说,要找到1<=i<=j<=N,使得 A[i]+A[i+1]+…+A[j] 尽量大。    【输入格式】  
  第一行一个整数 N,接下来的 N 行,每行一个整数,第 i+1 行为 A[i](-10000 <= A[i] <= 10000)。
原创粉丝点击