dp经典问题-最大连续子序列和 hdu1003
题目描述:
这道题我先后做过三遍,结果每一遍都没有做出来。今天再仔仔细细的研究了一下,才发现用动态规划更好理解。
关于求最大连续子序列和的博文转载如下:https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes27.html
最大连续子序列和的特点就是这个和一定比它的子序列中任何一个数要大,所以就有了判断条件。
已知一序列:把数列第一个数存入dp[0],从第一个数开始遍历,用一个dp数组去存两数之间的最大子序列和,因此得出动态转移方程式dp[i]=max(dp[i-1]+a[i],a[i]);
代码实现:
#include <iostream> #include <cstdio> using namespace std; int a[100001],dp[100001]; int main() { int T,n,i=0; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } dp[0] = a[0]; int start = 0,end = 0,max = -1001; int first = 0,last = 0; for(int i=0;i<n;i++) { if(dp[i-1]+a[i]>=a[i]) //判断条件 { dp[i] = dp[i-1]+a[i]; end = i; } else//如果最长子序列和比a[i]还小,那么就从当前a[i]开始重新遍历 { dp[i] = a[i]; start = end = i; } if(max<dp[i]) { max = dp[i]; first = start; last = end; } } printf("Case %d:\n%d %d %d\n",++i,max,first+1,last+1); if(T!=0) { printf("\n"); } } return 0; }
另一个改进的版本:
#include<iostream> #include<cstdio> using namespace std; int main() { int t,n,a[100010],Case=1; int thissum,maxsum,begin,end,postion; cin>>t; while(t--){ cin>>n; for(int i=0; i<n; i++) cin>>a[i]; thissum=maxsum=a[0]; begin=end=postion=0; for(int i=1; i<n; i++){ if(thissum+a[i]<a[i]){//如对于6 -1 0 3 -4 3 2这组数据来说,就会更新postion thissum=a[i]; postion=i; } else thissum+=a[i]; if(thissum>maxsum){ maxsum=thissum; begin=postion; end=i; } } printf("Case %d:\n%d %d %d\n",Case++,maxsum,begin+1,end+1); } return 0; }