最大连续和再续
remarkableboy 人气:2在求最大连续和的基础上,求得连续序列的始末位置
要求:The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
in:
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
out:
Case 1:
14 1 4
Case 2:
7 1 6
状态转移方程又两种选择,第一种二维dp(好不容易自己想了一个还让时间卡掉了): dp[k][j]=max(dp[k][j-1]+a[j],a[j]);我们已dp[k][j]表示从k出发到j时的最优解,理论上可行,但是时间只给了1s,这种O(t*n^2)的思路被卡掉也很正常
所以我们还是选择一维dp,dp[i]=max(dp[i-1]+a[i],a[i]);,我们知道dp[i]代表到i时的最优解,那么max(dp[i])时,i即为莫位置,然后在从i往前遍历找到其实即可.
#include <iostream> #include<cstring>//这道题时空卡的挺严的,不建议用memset #include<algorithm> using namespace std; int n,m; int a[100005]; int dp[100005]; long long maxa=-999999999; int s=1,e; long long total; int main() { std::ios::sync_with_stdio(false); cin>>n; for(int i=1; i<=n; i++) { cin>>m; for(int k=1; k<=m; k++) { cin>>a[k]; } for(int j=1; j<=m; j++) { dp[j]=max(dp[j-1]+a[j],a[j]); if(dp[j]>maxa) { maxa=dp[j]; e=j; } } for(int p=e;p>=1;p--) { total+=a[p]; if(total==maxa) { s=p; } } cout<<"Case"<<' '<<i<<':'<<endl; cout<<maxa<<' '<<s<<' '<<e<<endl; dp[0]=0;//10^6数据量用memset很耗时,但由于dp是线性的,可以不用 maxa=-999999999; s=1; e=0; total=0; if(i!=n) cout<<endl; } return 0; }
加载全部内容