编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
2011-04-21 11:15
656 查看
整体思路:
问题的解可以分为两种情况:
1)解没有跨过A[n-1]到A[0],即普通的求子数组和的最大值
2)解跨过A[n-1]到A[0]
对第二种情况,只要找到从A[0]开始和最大的一段(A[0],...,A[j])(0<=j<n)以及A[n-1]结尾的和最大的一段(A[i],...,A[n-1])(0<=i<n),那么第2种情况中,和的最大值M_2为:
M_2=A[i]+...A[n-1]+A[0]+...+A[j]
如果i<=j,则
M_2=A[0]+...+A[n-1] - 子数组和为负的最小值(数组元素全为正则返回0)
否则
M_2=A[0]+...+A[j]+A[i]+...+A[n-1]
代码如下,其中也分了A[0]+...+A[n-1]全为负的时候返回0(代码中define RETURN_ZERP)跟返回最大的负数(RETURN_MAXMINUS)这两种情况,lpos对应于整体思路中的i,rpos对应于整体思路中的j
问题的解可以分为两种情况:
1)解没有跨过A[n-1]到A[0],即普通的求子数组和的最大值
2)解跨过A[n-1]到A[0]
对第二种情况,只要找到从A[0]开始和最大的一段(A[0],...,A[j])(0<=j<n)以及A[n-1]结尾的和最大的一段(A[i],...,A[n-1])(0<=i<n),那么第2种情况中,和的最大值M_2为:
M_2=A[i]+...A[n-1]+A[0]+...+A[j]
如果i<=j,则
M_2=A[0]+...+A[n-1] - 子数组和为负的最小值(数组元素全为正则返回0)
否则
M_2=A[0]+...+A[j]+A[i]+...+A[n-1]
代码如下,其中也分了A[0]+...+A[n-1]全为负的时候返回0(代码中define RETURN_ZERP)跟返回最大的负数(RETURN_MAXMINUS)这两种情况,lpos对应于整体思路中的i,rpos对应于整体思路中的j
/*******************************问题描述**************************** 一个有N个整数元素的一维数组(A[0],A[1],...A(n-1)(首尾可以相邻),它包含 很多子数组,求子数组之和的最大值,当数组元素全部为负的时候,有两种处 理办法,第一种是返回0,第二种是返回数组中最大的负数 *******************************************************************/ /*******************************整体思路*************************** 问题的解可以分为两种情况: 1)解没有跨过A[n-1]到A[0],即普通的求子数组和的最大值 2)解跨过A[n-1]到A[0] 对第二种情况,只要找到从A[0]开始和最大的一段(A[0],...,A[j])(0<=j<n) 以及A[n-1]结尾的和最大的一段(A[i],...,A[n-1])(0<=i<n),那么第2种情况 中,和的最大值M_2为: M_2=A[i]+...A[n-1]+A[0]+...+A[j] 如果i<=j,则 M_2=A[0]+...+A[n-1]-子数组和为负的最小值 否则 M_2=A[0]+...+A[j]+A[i]+...+A[n-1] *******************************************************************/ #include<iostream> using namespace std; #define RETURN_MAXMINUS #ifdef RETURN_MAXMINUS /*********************************动态规划************************************** 假设A[0],A[1],...A(n-1)的最大子段为A[i],...,A[j],则有以下3种情况, 1)当0=i=j的时候,元素A[0]本身构成和最大的一段 2)当0=i<j的时候,和最大的一段以A[0]开头 3)当0<i时候,元素A[0]跟和最大的一段没有关系 则原始问题A[0],A[1],...A(n-1)的解All[0]=max{A[0],A[0]+Start[1],ALL[1]} 求得A[0],A[1],...A[n-1](首尾不连接)的情况后再考虑整体思路中的第二种情况 *********************************************************************************/ //从尾到首动态规划 int MaxSum(int *A,int length){ //先求出A[0],A[1],...A[n-1](首尾不连接)的情况下子数组和最大值nAll int nStart=A[length-1]; int nAll=A[length-1]; for(int i=length-2;i>=0;i--){ nStart=max(A[i],A[i]+nStart); nAll=max(nStart,nAll); } //下面处理整体思路的第二种情况,即跨过A[n-1],A[0] //先求A[n-1]结尾的和最大的一段(A[i],...,A[n-1])(0<=i<n) int sum=0; int ltempmax=-10000000; int lpos=length; for(int i=length-1;i>=0;i--){ sum+=A[i]; if(sum>ltempmax){ ltempmax=sum; lpos=i; } } //求A[0]开始和最大的一段(A[0],...,A[j])(0<=j<n) sum=0; int rtempmax=-10000000; int rpos=-1; for(int i=0;i<length;i++){ sum+=A[i]; if(sum>rtempmax){ rtempmax=sum; rpos=i; } } //如果lpos<=rpos,则循环数组中可能出现的子数组最大值要么是A[0]...A[n-1]子数组和的最大值nAll //要么是整个数组A[0]...A[n-1]的和再减去A[0]...A[n-1]中子数组和为负数的最小值 if(lpos<=rpos){ //求数组中和为负数且的最小值 int minStart=0; int minAll=0; for(int i=0;i<length;i++){ minStart=min(0,A[i]+minStart); minAll=min(minStart,minAll); } int tempmax=ltempmax+rtempmax; for(int i=lpos;i<=rpos;i++){ tempmax-=A[i]; } //比较A[0]...A[n-1]子数组和的最大值nAll跟A[0]...A[n-1]的和再减去A[0]...A[n-1]中子数组和为负数的最小值 return max(nAll,tempmax-minAll); }else{ //比较A[0]+...+A[j]+A[i]+...+A[n-1]即ltempmax+rtempmax的值跟A[0]...A[n-1]子数组和的最大值nAll return max(nAll,ltempmax+rtempmax); } } #endif //#define RETURN_ZERO #ifdef RETURN_ZERO /*********************************动态规划************************************** 假设A[0],A[1],...A(n-1)的最大子段为A[i],...,A[j],则有以下3种情况, 1)当0=i=j的时候,元素A[0]本身构成和最大的一段 2)当0=i<j的时候,和最大的一段以A[0]开头 3)当0<i时候,元素A[0]跟和最大的一段没有关系 则原始问题A[0],A[1],...A(n-1)的解All[0]=max{A[0],A[0]+Start[1],ALL[1]} 求得A[0],A[1],...A[n-1](首尾不连接)的情况后再考虑整体思路中的第二种情况 *********************************************************************************/ //从尾到首动态规划 int MaxSum(int *A,int length){ //先求出A[0],A[1],...A[n-1](首尾不连接)的情况下子数组和最大值nAll int nStart=0; int nAll=0; for(int i=length-1;i>=0;i--){ nStart=max(0,A[i]+nStart); nAll=max(nStart,nAll); } //下面处理整体思路的第二种情况,即跨过A[n-1],A[0] //先求A[n-1]结尾的和最大的一段(A[i],...,A[n-1])(0<=i<n) int sum=0; int ltempmax=-10000000; int lpos=length; for(int i=length-1;i>=0;i--){ sum+=A[i]; if(sum>ltempmax){ ltempmax=sum; lpos=i; } } //求A[0]开始和最大的一段(A[0],...,A[j])(0<=j<n) sum=0; int rtempmax=-10000000; int rpos=-1; for(int i=0;i<length;i++){ sum+=A[i]; if(sum>rtempmax){ rtempmax=sum; rpos=i; } } //如果lpos<=rpos,则循环数组中可能出现的子数组最大值要么是A[0]...A[n-1]子数组和的最大值nAll //要么是整个数组A[0]...A[n-1]的和再减去A[0]...A[n-1]中子数组和为负数的最小值 if(lpos<=rpos){ //求数组中和为负数且的最小值 int minStart=0; int minAll=0; for(int i=0;i<length;i++){ minStart=min(0,A[i]+minStart); minAll=min(minStart,minAll); } int tempmax=ltempmax+rtempmax; for(int i=lpos;i<=rpos;i++){ tempmax-=A[i]; } //比较A[0]...A[n-1]子数组和的最大值nAll跟A[0]...A[n-1]的和再减去A[0]...A[n-1]中子数组和为负数的最小值 return max(nAll,tempmax-minAll); }else{ //比较A[0]+...+A[j]+A[i]+...+A[n-1]即ltempmax+rtempmax的值跟A[0]...A[n-1]子数组和的最大值nAll return max(nAll,ltempmax+rtempmax); } } #endif #define MAIN int main(){ int a[6]={1,-2,3,5,-3,2}; int b[6]={1,-2,3,5,-1,2}; int c[6]={2,-1,3,5,-2,1}; int d[6]={-9,-2,-3,-5,-3}; int e[3]={3,-2,3}; #ifdef RETURN_MAXMINUS cout<<"a 的子数组和的最大值是(正确结果应该返回8) "<<MaxSum(a,6)<<endl; cout<<"b 的子数组和的最大值是(正确结果应该返回10) "<<MaxSum(b,6)<<endl; cout<<"c 的子数组和的最大值是(正确结果应该返回10) "<<MaxSum(c,6)<<endl; cout<<"c 的子数组和的最大值是(正确结果应该返回-2) "<<MaxSum(d,5)<<endl; cout<<"e 的子数组和的最大值(正确结果应该返回6) "<<MaxSum(e,3)<<endl; #endif #ifdef RETURN_ZERO cout<<"a 的子数组和的最大值是(正确结果应该返回8) "<<MaxSum(a,6)<<endl; cout<<"b 的子数组和的最大值是(正确结果应该返回10) "<<MaxSum(b,6)<<endl; cout<<"c 的子数组和的最大值是(正确结果应该返回10) "<<MaxSum(c,6)<<endl; cout<<"c 的子数组和的最大值是(正确结果应该返回0) "<<MaxSum(d,5)<<endl; cout<<"e 的子数组和的最大值(正确结果应该返回6) "<<MaxSum(e,3)<<endl; #endif system("PAUSE"); return 0; } #ifdef MAIN #endif
相关文章推荐
- 编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
- 编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
- 求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现
- 求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现
- 编程之美2.14扩展问题2 求数组的子数组之和的最大值并给出子数组的起始终止位置
- 编程之美2.14扩展问题2 求数组的子数组之和的最大值并给出子数组的起始终止位置
- 编程之美2.14 子数组之和的最大值 扩展问题(首尾相连)
- 《编程之美》读书笔记(十二):“求数组的子数组之和的最大值”扩展问题
- 编程之美寻找数组中的最大值和最小值以及扩展问题
- [编程之美2.14]求子数组之和的最大值
- 编程之美2.14 求子数组和的最大值(首尾相连)
- 编程之美2.10寻找数组中的最大值和最小值扩展问题Java版
- 编程之美2.14 求数组的子数组之和的最大值
- 编程之美2.14 求数组的子数组之和的最大值
- 2.14 求子数组之和的最大值
- 编程之美 2.14 数组的子数组之和的最大值 扩展题2
- 数组问题(一)求子数组和的最大值
- 编程之美之2.14 求数组的子数组之和的最大值
- 编程之美: 第二章 数字之魅 2.14求数组的子数组之和的最大值
- 求子数组最大和问题