[DP]最大连续子序列-hdu 1231
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1231
算法参考:http://blog.163.com/wuguojin03@126/blog/static/17154113120109510946717/
状态:dp[i]:以i为结尾的最大连续序列和
初始状态:dp[i]=a[i]
状态转移:dp[i]=max{dp[i-1]+a[i],a[i]}
要求最大的,只需从dp[i]找出最大值就行了
以本题输入样例 “ -2 11 -4 13 -5 -2 ” 为例:
序号: 0 1 2 3 4 5
a[]: -2 11 -4 13 -5 -2
dp[]: -2 11 7 20 15 13
观察dp[],终点即为 max:20,起点则为从max往前找最后一个不为负的数,即11
AC代码:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
const int N=10010;
int a[N],dp[N];
int main()
{
int n;
while(cin>>n && n){
int s=0,e=0;
for (int i = 0; i < n; ++i){
cin>>a[i];
dp[i]=a[i];
}
for(int i=1;i<n;++i){
dp[i]=max( dp[i-1]+a[i] , a[i] );
}
//查找最大和及终点
int mymax=-1;
for (int i = 0; i < n; ++i){
if(mymax<dp[i]){
mymax=dp[i];
e=i;
}
}
//查找起点
for(int i=e;i>=0;--i)
if(dp[i]<0){
s=i+1;
break;
}
if(mymax<0)cout<<"0 "<<dp[0]<<" "<<dp[n-1]<<endl;
else cout<<mymax<<" "<<a[s]<<" "<<a[e]<<endl;
}
return 0;
}
一年后,偶遇此题又做一遍,用的是双dp,效率还没有上面的高:
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN=10000+5;
int a[MAXN],dp_l[MAXN],dp_r[MAXN];
int n;
int main()
{
while(scanf("%d",&n)&&n>0) {
for(int i=0;i<n;++i){
scanf("%d",&a[i]);
}
dp_l[0]=a[0];
dp_r[n-1]=a[n-1];
int ans=a[0],start=0,end=n-1;
for(int i=1;i<n;++i){
dp_l[i]=max(a[i],a[i]+dp_l[i-1]);
if(dp_l[i]>ans){
ans=dp_l[i];
end=i;
}
}
ans=a[0];
for(int i=n-2;i>=0;--i){
dp_r[i]=max(a[i],a[i]+dp_r[i+1]);
if(dp_r[i]>=ans){
ans=dp_r[i];
start=i;
}
}
if(ans<0){
ans=0;start=0;end=n-1;
}
printf("%d %d %d\n",ans,a[start],a[end] );
}
return 0;
}
还有一种方法,也挺快,不过不是用的动态规划:
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN=10000+5;
int a[MAXN],dp_l[MAXN],dp_r[MAXN];
int n;
int main()
{
while(scanf("%d",&n)&&n>0) {
for(int i=0;i<n;++i){
scanf("%d",&a[i]);
}
int start=0,end=n-1,left,ans=a[0],sum=0;
for(int i=0;i<n;++i){
if(sum<0) { //如果前几项和小于0,就重新开始记录
sum=0;
left=i; //刷新临时起点
}
sum+=a[i];
if(sum>ans){ //如果现在的sum大于原来的max,刷新数据
ans=sum;
start=left;
end=i;
}
}
if(ans<0){
ans=0;start=0;end=n-1;
}
printf("%d %d %d\n",ans,a[start],a[end] );
}
return 0;
}

浙公网安备 33010602011771号