洛谷 P1204 [USACO1.2] 挤牛奶Milking Cows

题目链接:https://www.luogu.com.cn/problem/P1204

知识点:贪心

即若当前时间段不连续,则取当前最大的连续时间段与最大空闲时间段。

思路:

1.首先将所有农夫的工作时间,以起始时间最早进行排序

2.寻找最长连续时间,最长空闲时间

flag1=当前连续时间起始点;        flag2=当前连续时间结束点;

如果当前农夫的工作起始时间 > flag2,即有空闲时间,那么:

①计算更新此前的最长连续时间

sum1 =  max ( sum1, flag2 - flag1);

②计算更新此时的最长空闲时间

sum0 = max ( sum0,  当前农夫的工作起始时间 - flag2 );

③更新当前连续时间起始点,当前连续时间结束点

flag1 = 当前农夫工作起始时间;

flag2 = 当前农夫工作结束时间;

如果当前农夫的工作起始时间 <= flag2,即当前连续时间段增长,那么

①更新当前连续时间结束点

flag2 = 当前农夫工作结束时间

3.由于最后一次连续时间段没有进入循环计算,故最后再更新一次最长连续时间

sum1 = ( sum1, flag2 - flag1 );

完整代码如下:

#include <iostream>
#include <algorithm>

using namespace std;

struct Time{
    long long begin;
    long long end;
}p[ 5005 ];
int n;
long long sum1, sum0;

int cmp ( Time a, Time b )
{
    return a.begin < b.begin;
}

void print()
{
    puts( "" );
    for ( int i = 0; i < n; ++ i )
    {
        printf ( "%lld %lld\n", p[ i ].begin, p[ i ].end );
    }
    puts( "" );
}

void solve ( )
{
    sort ( p, p + n, cmp );
    //print();
    int flag1, flag2;
    flag1 = p[ 0 ].begin;   // 最早连续时间
    flag2 = p[ 0 ].end;     // 最迟连续时间
    int flag = p[ 0 ].begin;

    for ( int i = 1; i < n; ++ i )
    {
        if ( p[ i ].begin > flag2 ) // 有空闲时间段
        {
            // 更新最长空闲时间
            sum0 = sum0 > ( p[ i ].begin - flag2 ) ? sum0 : ( p[ i ].begin - flag2 );
            // 更新最长连续时间
            sum1 = sum1 > ( flag2 - flag1 ) ? sum1 : ( flag2 - flag1 );
            flag1 = p[ i ].begin;               // 标记新的连续时间段起始点
            flag2 = p[ i ].end;                 // 标记新的连续时间段结束点
        }
        else    // 更新连续时间段结束点
        {
            flag2 = flag2 > p[ i ].end ? flag2 : p[ i ].end;
        }
    }
    
    // 由于最后一次连续时间没有进入循环计算,故再更新一次
    sum1 = sum1 > ( flag2 - flag1 ) ? sum1 : ( flag2 - flag1 );

    printf ( "%lld %lld\n", sum1, sum0 );
}

int main ( )
{
    scanf ( "%d", &n );
    for ( int i = 0; i < n; ++ i )
    {
        scanf( "%lld %lld", &p[ i ].begin, &p[ i ].end );
    }
    solve();

    system( "pause" );
    return 0;
}

 

学海无涯

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值