hdu 1003 - Max Sum(分治of贪心)

今天比赛的一道题目,有位同学写的代码比我写的好多了,而且有点贪心的意思,所以就贴了上来,

用sum来存前面的正和,如果sum<0的话,那么sum就置成0,意为前面的和都不要了,而重新开始找最大连续和。

这是因为前面的和小于0的话,对后面的最大连续和,做不了贡献,反而会拖了后腿。

如果现在的sum比max要大的话,则更新答案,

代码如下:

#include <cstdio>
#define M 100005
#define INF 0x7fffffff
int main ()
{
    int t, n, x, start, end, sum, maxx, tt, k = 0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        start = 1; end = 1;
        sum = 0; tt = 1;
        maxx = -INF;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d",&x);
            sum+=x;
            if(sum>maxx)
            {
                maxx = sum;
                end = i;
                start = tt;
            }
            if(sum<0)
            {
                sum = 0;
                tt = i+1;
            }
        }
        if(k) printf("\n");
        printf("Case %d:\n%d %d %d\n", ++k, maxx, start, end);
    }
    return 0;
}

还有就是自己写的分治的代码,很长,而且不好写,,

具体思路就是入门经典上的分治法,每个区间的最大连续和或在【0......m】,或在【m+1....n】,或在【x,....m.....y】;

最后再选出最大的即可。。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 100005
#define INF 0x7fffffff
int n, a[M];
long long sum[M];
int solve(int l, int r, int &x, int &y)
{
    if(l==r)
    {
        x = l; y = l;
        return a[l];
    }

    int lx, ly, rx, ry;
    int m = (l+r)/2;
    solve(l,m,lx,ly);
    solve(m+1,r,rx,ry);

    int Lx = m, Rx = m+1;
    long long L = -INF, R = -INF;
    for(int i = m; i >= l; --i)
        if(sum[m]-sum[i-1]>=L) { L = sum[m]-sum[i-1]; Lx = i; }

    for(int i = m+1; i <= r; ++i)
        if(sum[i]-sum[m]>R) { R = sum[i]-sum[m]; Rx = i; }

    if(sum[ly]-sum[lx-1]>=sum[ry]-sum[rx-1])
        { x = lx; y = ly; }
    else
        { x = rx; y = ry; }
    if(L+R > sum[y]-sum[x-1])
        { x = Lx; y = Rx; }
    else if(L+R == sum[y]-sum[x-1]&&Lx < x)
        { x = Lx; y = Rx; }
    return sum[y]-sum[x-1];
}
int main ()
{
    int t, k = 0;
    scanf("%d",&t); getchar();
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d",&a[i]);
            sum[i] = sum[i-1]+a[i];
        }
        int ansx, ansy;
        long long  maxsum = solve(1,n,ansx,ansy);
        if(k) printf("\n");
        printf("Case %d:\n%I64d %d %d\n",++k,maxsum, ansx, ansy);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值