UVA 507 - Jill Rides Again

                      通过这个题学习了一下最大连续和这一块,这个题有好几种方法的,

                    一种是http://blog.csdn.net/shuangde800/article/details/7828614用的:

                “最大连续和问题,有好几种算法,其中最快的一种是O(n)的,只需要扫描一遍即可。 

假设用数组arr存好感度 ,  那么设sum[i]=arr[0]+arr[1]+..+arr[i]. 即sum[i]是从车站1到车站i的好感度之和。 这样的话,如果要求某一段车站的好感度之和, 假设车站3到车站5,只需要O(1)时间: sum[5]-sum[2]就是答案。 要使得sum[i]-sum[j]更大,就要使得sum[j]更小。因而不断更新sum[min],然后一次判断sum[i]-sum[min]和max做题时需要注意的是,答案要求好感度最大的连续和区间长度越长越好, 起点越早越好。”代码如下:

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
    //freopen("in.txt","r",stdin);
    int cas,r,num[20002],left,right;
    scanf("%d",&cas);
    for(int cass=1; cass<=cas; cass++)
    {
        scanf("%d",&r);
        num[0]=0;
        for(int i=1; i<=r-1; i++)
        {
            scanf("%d",&num[i]);
            num[i]+=num[i-1];
        }
        int min=0,max=-2147483647;
        for(int i=1; i<=r-1; i++)
        {
            int t=num[i]-num[min];
            if(t>max)
            {
                 max=t;
                 left=min;
                 right=i;
            }
            else if(t==max)
            {
                if(min==left)
                    right=i;
                else if(i-min>right-left)
                {
                    right=i;
                    left=min;
                }
            }
            if(num[i]<num[min])
            min=i;
        }
        if(max>0)
            cout<<"The nicest part of route "<<cass<<" is between stops "<<left+1<<" and "<<right+1<<"\n";
        else cout<<"Route "<<cass<<" has no nice parts\n";
    }
    return 0;
}
              第二种就是 http://blog.csdn.net/frankiller/article/details/8074741,不需要像上述代码一样num[i]+=num[i-1],

从左到右逐步累加,记录每次累加之后的最大值,假如累加值<0,则将累加值清0,重新累加。当这个过程结束之后所记录的最大值就是最大的连续序列的累加值。因为只需要从左到右扫描一次,因此算法的复杂度为O(n),代码如下:

#include<stdio.h>
#include<string.h>
int main()
{
    int a[20001],n,i,j,max,begin,start,end,f,s,sum;
    scanf("%d",&sum);
    for (j=1; j<=sum; j++)
    {
        scanf("%d",&n);
        f=1;
        for (i=1; i<n; i++)
        {
            scanf("%d",&a[i]);
            if (a[i]>0) f=0;
        }
        if (f) printf("Route %d has no nice parts\n",j);
        else
        {
            s=0;
            max=0;
            start=1;
            begin=1;
            end=1;
            for (i=1; i<n; i++)
            {
                s=s+a[i];
                if (s<0)
                {
                    s=0;
                    start=i+1;
                }
                if (s>max ||((s==max)&&(i-start>end-begin)))
                {
                    max=s;
                    begin=start;
                    end=i;
                }
            }
            printf("The nicest part of route %d is between stops %d and %d\n",j,begin,end+1);
        }
    }
    return 0;
}
               另外,lrj书上有一个分治法。还需要深刻理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值