最大连续子段和、M子段和

8 篇文章 0 订阅

最大子段和 (HDU1231)

题目就是给你一个序列,你找到其中和最大的子序列。


这是最基础的DP:

dp[i] 表示当最大子序列包括a[i]时最大子段和。如果dp[i-1] < 0 那么dp[i] = a[i] ,否则dp[i] = dp[i-1] + a[i]。


#include<cstdio>

using namespace std;

const int SIZE = 10005;
int N;
int A[SIZE];
int dp[SIZE];

int main()
{
    while(scanf("%d",&N)!=EOF && N)
    {
        for(int i=1;i<=N;i++) scanf("%d",&A[i]);
        int res = -1;
        int temp = -1;

        dp[0] = -1; // 防止第0个元素被选中

        int fr = 1, en = N;
        for(int i=1;i<=N;i++)
        {
            if(dp[i-1] < 0)
            {
                dp[i] = A[i];
                temp = i;
                if(dp[i] > res)
                {
                    res = dp[i];
                    fr = i;
                    en = i;
                }
            }
            else
            {
                dp[i] = dp[i-1] + A[i];
                if(dp[i] > res)
                {
                    res = dp[i];
                    fr = temp;
                    en = i;
                }
            }
        }
        if(res < 0) res = 0;
        printf("%d %d %d\n",res,A[fr],A[en]);
    }
    return 0;
}


最大M子段和:HDU1024


搞了很久发现是自己理解错题意

dp[j] 以j个元素结尾的最大i子段和

maxdp[j] 到j为止最大i-1子段和

j from i tp N

dp[j] = max(dp[j-1], maxdp[j-1]) + A[i]

maxdp[j-1] = max(dp[k]) (k from 1 to j-1)


#include<cstdio>
#include<cstring>
#include<algorithm>


using namespace std;


const int SIZE = 1000005;
typedef long long ll;
int N,M;
ll dp[SIZE];
ll maxdp[SIZE];
ll A[SIZE];


ll maxx(ll a,ll b)
{
    if(a < b) return b;
    return a;
}


int main()
{
    while(scanf("%d %d",&M,&N)!=EOF)
    {
        for(int i=1;i<=N;i++) scanf("%I64d",&A[i]);
        fill(maxdp,maxdp+1+N,0);
        fill(dp,dp+1+N,0);
        //printf("dp[0]=%I64d\n",dp[0][1]);
        long long temp;
        for(int i=1;i<=M;i++)
        {
            temp = -0x7fffffff;
            for(int j=i;j<=N;j++)
            {
                dp[j] = maxx(dp[j-1],maxdp[j-1]) + A[j];
                maxdp[j-1] = temp;
                temp = maxx(temp,dp[j]);
            }
        }


        printf("%I64d\n",temp);
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值