1007 Maximum Subsequence Sum
题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805514284679168
解题思路
1.一开始的思路好像是叫“在线处理法”;但这种方法能过大部分是因为题目规定了全为负值时取0的特殊情况;而且,无法过值为非正数的情况;
for(int i=1;i<=n;i++){
if(sum+Num[i]<0){
sum=0;
lnum=0;
}
else sum+=Num[i],lnum+=1;
if(ans<sum){
r=i;
l=r-lnum+1;
ans=sum;
}
}
2.另外一种思路就是dp,用dp[i]记录以i结尾的最大子序和,(动规NB);
用pre[i]记录子序的起始下标;一开始没想到这种方法是因为钻了牛角尖,没意识到只需要求出所有以i结尾的最大子序和,然后比较就可以了;
for(int i=2;i<=n;i++){
if(dp[i-1]+Num[i]>Num[i]){
dp[i]=dp[i-1]+Num[i];
pre[i]=pre[i-1];
}
else {
dp[i]=Num[i];
pre[i]=i;
}
if(ans<dp[i]){
ans=dp[i];
ansi=i;
}
}
总结
想dp解法没头绪的时候,就用暴力试一试;暴力出奇迹;
代码展示
#include<bits/stdc++.h>
using namespace std;
/*
10
-10 1 2 3 4 -5 -23 3 7 -21
6
-2 11 -4 13 -5 -2
*/
int Num[10005];
int dp[10005];//以第i项结尾的最大子序和
int pre[10005];
int main(){
int n;
cin>>n;
bool flag=false;
for(int i=1;i<=n;i++){
cin>>Num[i];
if(Num[i])flag=true;
}
dp[1]=Num[1];pre[1]=1;
int ans=-1,ansi;
for(int i=2;i<=n;i++){
if(dp[i-1]+Num[i]>Num[i]){
dp[i]=dp[i-1]+Num[i];
pre[i]=pre[i-1];
}
else {
dp[i]=Num[i];
pre[i]=i;
}
if(ans<dp[i]){
ans=dp[i];
ansi=i;
}
}
if(ans==-1)
cout<<0<<" "<<Num[1]<<" "<<Num[n];
else
cout<<ans<<" "<<Num[pre[ansi]]<<" "<<Num[ansi];
return 0;
}