动态规划——最长连续子序列和+最大子矩阵和
2014-01-26 21:19
162 查看
问题:给一列数n个,求最大连续子序列和(即连续的子序列中和最大的序列)若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素 本文作者 凌风 csdn (iaccepted)
拓展:给一个n*n的矩阵,求其中和最大的子矩阵(即所有子矩阵中和最大的阵)
首先也是从最简单的着手,拿到问题,很容易想到的就是直接爆搜(求所有可能的子序列和并找出最大的即可)时间复杂度为n^2
上面的这段代码思路非常的清晰也便于理解,但是数据量大的话时间消耗也会很大,当然ACM的要求肯定是达不到了,现在做时间复杂度为n的算法来解决该问题。
该算法基于的思想也很简单,最大连续子序列和的第一个元素不可能是负数,这点很好证明(反证),假设a[i…j]为最大的连续子序列且a[i]为负,那我a[i+1…j]的和将会大于a[i…j]的和,所以与原假设矛盾,这就能推出最大子序列和的第一个元素不可能是负数。得到这个结论我们就可以进一步进行推广,那就是如果一个子序列的和为负数,那么这个序列不可能是最大连续子序列中的开始的一段序列(类似于第一个元素的方法可得到证明即把这段和看做是一个元素)。根据这一思想就可以得到本体线性的算法。
作者博客:http://blog.csdn.net/iaccepted,欢迎交流
本文作者 凌风 csdn(iaccepted)
本文作者 凌风 csdn(iaccepted)
作者博客:http://blog.csdn.net/iaccepted,欢迎交流
下面记录下最大子矩阵和的求法。
其实最大子矩阵和的算法就是最大连续子序列的一个拓展问题,思路很简单,就是将矩阵先预处理下,按列累加,然后通过三个循环变量来遍历所有的子矩阵,对每个子矩阵以列和为元素转化为n个元素序列求最大连续子序列的问题就可以了。
拓展:给一个n*n的矩阵,求其中和最大的子矩阵(即所有子矩阵中和最大的阵)
首先也是从最简单的着手,拿到问题,很容易想到的就是直接爆搜(求所有可能的子序列和并找出最大的即可)时间复杂度为n^2
#include <stdio.h> #include <string.h> #include <limits.h> #define N 10002 /* problem:求最大连续子序列的问题dp time:n^2 */ int main(){ int a ,i,j,maxx,sum,n,ps,pe; scanf("%d",&n); for(i=0;i<n;++i){ scanf("%d",&a[i]); } maxx = INT_MIN;//初始为最小整数 for(i=0;i<n;++i){ sum = 0; for(j=i;j<n;++j){//i,j两个子循环来遍历所有的子序列并计算其和(a[i]加到a[j]) sum += a[j]; if(sum>maxx){//把和大的保留并记录下最大序列的始末位置ps、pe maxx = sum; ps = i; pe = j; } } } printf("%d %d %d\n",maxx,a[ps],a[pe]); }
上面的这段代码思路非常的清晰也便于理解,但是数据量大的话时间消耗也会很大,当然ACM的要求肯定是达不到了,现在做时间复杂度为n的算法来解决该问题。
该算法基于的思想也很简单,最大连续子序列和的第一个元素不可能是负数,这点很好证明(反证),假设a[i…j]为最大的连续子序列且a[i]为负,那我a[i+1…j]的和将会大于a[i…j]的和,所以与原假设矛盾,这就能推出最大子序列和的第一个元素不可能是负数。得到这个结论我们就可以进一步进行推广,那就是如果一个子序列的和为负数,那么这个序列不可能是最大连续子序列中的开始的一段序列(类似于第一个元素的方法可得到证明即把这段和看做是一个元素)。根据这一思想就可以得到本体线性的算法。
作者博客:http://blog.csdn.net/iaccepted,欢迎交流
本文作者 凌风 csdn(iaccepted)
#include <stdio.h> #include <string.h> #include <limits.h> #define N 10002 int main(){ int a ,maxx,i,n,sum,ps,pe,ts,te; scanf("%d",&n); for(i=0;i<n;++i){ scanf("%d",&a[i]); } sum = 0; maxx = INT_MIN; for(i=0;i<n;++i){ if(sum<=0){//如果前面的和为负,则前面的序列舍掉从本元素开始重新确定新序列 sum = a[i]; ts = i; te = i; }else{//如果前面的和为正,则可能出现在最大序列中,所以要继续累加 sum += a[i]; te = i; } if(sum>maxx){//记录下最大子序列和及起始和结束位置 maxx = sum; ps = ts; pe = te; } } printf("%d %d %d\n",maxx,a[ps],a[pe]); return 0; }至此,最大连续子序列问题得到解决。
本文作者 凌风 csdn(iaccepted)
作者博客:http://blog.csdn.net/iaccepted,欢迎交流
下面记录下最大子矩阵和的求法。
其实最大子矩阵和的算法就是最大连续子序列的一个拓展问题,思路很简单,就是将矩阵先预处理下,按列累加,然后通过三个循环变量来遍历所有的子矩阵,对每个子矩阵以列和为元素转化为n个元素序列求最大连续子序列的问题就可以了。
#include <stdio.h> #include <string.h> #define N 102 int main(){ int a ; int k,i,j,n,sum,maxx,i2,i1; while(scanf("%d",&n)!=EOF){ for(i=0;i<=n;++i)a[0][i]=a[i][0]=0; for(i=1;i<=n;++i){ for(j=1;j<=n;++j){ scanf("%d",&a[i][j]); a[i][j]+=a[i-1][j];//这里就是矩阵预处理即列进行累加和 } } maxx = -129; for(i1=0;i1<n;++i1){//子矩阵的行的上边界 for(i2=i1+1;i2<=n;++i2){//子矩阵的行的下边界 sum = 0; for(k=1;k<=n;++k){//转化为n个元素中找最大连续子序列的问题每个元素即为a[i2][k]-a[i1][k] if(sum<=0)sum = (a[i2][k]-a[i1][k]); else sum += (a[i2][k]-a[i1][k]); if(sum>maxx)maxx = sum; } } } printf("%d\n",maxx); } return 0; }
相关文章推荐
- 动态规划-最长连续子序列和与最大子矩阵
- [ACM_动态规划] POJ 1050 To the Max ( 动态规划 二维 最大连续和 最大子矩阵)
- 最大子序列、最长连续公共子串(连续)、最长公共子序列(动态规划)
- 【C】动态规划--最大连续子序列和/最长不下降子序列/最长公共子序列/最长回文子串/DAG最长路
- 递增子序列最大和(最长递增子序列) 动态规划
- 最长连续和与最大子矩阵
- 【两段连续不重合子序列和最大】 动态规划
- 最长连续和与最大子矩阵
- [动态规划]最大子序列+最大子矩阵
- 动态规划实现最大连续子序列和,最长不下降子序列和最长公共子序列
- HDU 2845(动态规划-最大非连续区间)
- 美团2017编程题—拼凑钱币&大富翁游戏&最大矩形面积&最长公共连续子串
- “最长上升子序列,最大连续子序列和,最长公共子串”的Java实现
- 动态规划 最长不重复连续子串
- 输入n个元素组成的序列S,你需要找出一个乘积最大的连续子序列。如果这个最大的乘积不是正数,应输出0(表示无解)。1<=18,-10<=Si<=10
- 动态规划练习--02(最大子矩阵)
- 动态规划求解数组连续最大和
- 动态规划(线性模型):POJ 2533 最长上升子序列
- 最长连续子序列和
- 【动态规划】求最大连续bit数