动态规划 | 1007 最大连续子序列和

本题是对“ 最大连续子序列和”这个问题的变形,只要读懂题,处理好细节,没有什么设坑的地方。

这道题可以用贪心和DP来做,我开始用贪心做的,wa了一个测试点。经过了一波冷静的分析,查出了原因,AC了。

贪心

贪心的思路很简单,遍历一遍数组,用mA记录最优解的第一个数,用mB记录最优解的第二个数,mSum记录最优解,a、b、sum都是临时变量。

一下加粗的代码是漏打的bug:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100000
#define MAX (1<<30)-1
#define V vector<int>

using namespace std;

int num[LEN];

int main(){
//    freopen("1007.txt","r",stdin);
    int i,n,t,a,b,mSum=-1,sum=0,mA,mB;
    I("%d",&n);
    FF(i,n) I("%d",&num[i]);
    a=num[0];
    FF(i,n){
        t=num[i];
        if(sum+t<0){
            sum=0;
            a=num[i+1];
        }else{
            sum+=t;
            b=t;
            if(sum>mSum){
                mSum=sum;
                mA=a;
                mB=b;
            }
        }
    }
    if(mSum<0){
        O("%d %d %d",0,num[0],num[n-1]);
    }else{
        O("%d %d %d",mSum,mA,mB);
    }
    return 0;
}

 

DP

DP的思路在注释中,这里不再赘述

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100000
#define MAX (1<<30)-1
#define V vector<int>

using namespace std;

int a[LEN];
int s[LEN];    //s[i]表示dp[i]的连续序列从a的哪个元素开始的 
int dp[LEN];//dp[i]存放以a[i]结尾的连续序列的最大和 

int main(){
//    freopen("1007.txt","r",stdin);
    int i,n;
    bool flag=0;    //数组中的元素是否全部小鱼0 
    I("%d",&n);
    FF(i,n){
        I("%d",&a[i]);
        if(a[i]>=0) flag=1;
    }
    if(!flag){
        O("%d %d %d",0,a[0],a[n-1]);
        return 0;
    }
    //边界
    dp[0]=a[0] ;
    //注意隐式赋值: s[0]=0 
    F(i,1,n){
        //状态转移方程
        if(dp[i-1]+a[i]>a[i]){    //
            dp[i]=dp[i-1]+a[i];
            s[i]=s[i-1];
        }else{                    //不放 
            dp[i] =a[i];
            s[i]=i;
        }
    }
    //遍历一遍,找到以哪个元素结尾,连续和最大
    int k=0;
    F(i,1,n) {
        if(dp[i]>dp[k]){
            k=i;
        }
    }    
    O("%d %d %d",dp[k],a[s[k]],a[k]);
    return 0;
}

 

posted @ 2018-03-14 20:24  TQCAI  阅读(169)  评论(0编辑  收藏  举报