USACO天梯--Milking Cows

Milking Cows

Three farmers rise at 5 am each morning and head for the barn to milk three cows. The first farmer begins milking his cow at time 300 (measured in seconds after 5 am) and ends at time 1000. The second farmer begins at time 700 and ends at time 1200. The third farmer begins at time 1500 and ends at time 2100. The longest continuous time during which at least one farmer was milking a cow was 900 seconds (from 300 to 1200). The longest time no milking was done, between the beginning and the ending of all milking, was 300 seconds (1500 minus 1200).

Your job is to write a program that will examine a list of beginning and ending times for N (1 <= N <= 5000) farmers milking N cows and compute (in seconds):

  • The longest time interval at least one cow was milked.
  • The longest time interval (after milking starts) during which no cows were being milked.

PROGRAM NAME: milk2

INPUT FORMAT

Line 1:The single integer
Lines 2..N+1:Two non-negative integers less than 1,000,000, respectively the starting and ending time in seconds after 0500

SAMPLE INPUT (file milk2.in)

3
300 1000
700 1200
1500 2100

OUTPUT FORMAT

A single line with two integers that represent the longest continuous time of milking and the longest idle time.

SAMPLE OUTPUT (file milk2.out)

900 300


标标准准的竞赛题,很考验思维的严密性。因为一个小细节,博主卡住了半个小时...可能还是手生吧!由于是大数据long long就不用我多说了!

我还是要来详细解答一下这题,要一次性把这题完全AC,我只能说你是搞OI的料子。【类似于楼教主那样的人吧......大犇!】

要想把这题搞懂,拿出纸和笔来画一个数轴吧~

详细解答:

在进行判断前,我们首先要做的就是快排。这类题跟线段覆盖是一类题型,也就是NOIP的Day1第一大题(也有可能是第二题难度)的难度吧!

算法是贪心算法+模拟。

这类题的顺序一般是:

①快排②记录最优解并进行比较,始终保留最优解直至搜索结束③讨论特殊情况④检查最终结果(自己卡数据)。

注意:这里的快排是有技巧的~将每行的第二个数据进行排序(一般是定义一个结构体)。

1)关于idle time(空闲时间)【要搞OI和ACM的朋友,英语一定不要差!】

①先来考虑特殊情况:

快排后先比较最后一行的起始值,若小于等于第一行的起始值,很明显这里的空闲时间就是0.

②一般情况:

思考空余时间是如何产生的???答案:是后一行数据的起始值大于前一行数据的末尾值产生的!

但是如果你写的程序表达的意思是下图所示:

|______|

                    |_______|

很抱歉你错了!因为有可能是下面这样的情况:

|______|

                    |_______|

     |_________________|

这样的话空闲时间就是0.所以你要做的就是排除这样的情况。其他的就没有什么好说的了。关于idle time我就说到这儿。

2)关于milk time(相当于工作时间)

①第一种情况:

     |_______|

|______________|

这个简单,时间就是:第二行的末尾值减去第二行的起始值。

②第二种情况:

|__________|

                               |____________|

这个也很容易:时间=max(第一行末尾值-第一行起始值,第二行末尾值-第二行起始值);

③第三种情况:

最不容易思考全面的情况!!!

1.

|_________|

            |__________|

                             |_________|

2.

|_________|

          |___________|

      |________________|

3.

|_________|

       |_____________|

            |_______________|

4.

|_________|

                              |______|

            |______________________|

以上就是所有的情况,我想图形已经很明确的给出了提示。

还是想不明白的朋友可以看一下我的代码,再来思考~

要值得注意的是下面代码中的break(我已经标注),当初博主就是因为这个break没写导致TLE,在最后一个测试点上卡了半小时。

以下是我的AC代码:

/*
ID:wang ming
PROG:milk2
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node
{
	long long x,y;

}a[5010];

int cmp(node x1,node x2)
{
	return x1.y<x2.y;
}

int main()
{
	freopen("milk2.in","r",stdin);
	freopen("milk2.out","w",stdout);
	int num,j,i,k,cal;
	scanf("%d",&num);
	for(int i=0;i<num;i++)
	{
		scanf("%lld%lld",&a[i].x,&a[i].y);
	}
	sort(a,a+num,cmp);
	long long milk=0,idle=0,rr=0,ll=0,temp=0;
	if(num==1)
	{
		milk=a[0].y-a[0].x;
	}
	else
	{
		for(i=1;i<num;i++)
		{
			if(a[i].x<=a[i-1].y&&a[i].x>=a[i-1].x)
			{
				for(j=i+1;j<num;j++)
				{
					if(a[j].x<=a[j-1].y&&a[j].x>=a[i-1].x)
					{
						continue;
					}
					else if(a[j].x>a[j-1].y)
					{
					    cal=0;
					    for(k=j+1;k<num;k++)
					    {
					        if(a[k].x<=a[j-1].y&&a[k].x>=a[i-1].x)
					        {
					            cal++;break;                  /*记录是否存在数比a[j-1].y要小*/--/*这个break极为重要超不超时全看这个*/
					        }
					    }
					}
					if(cal!=0)
					continue;
					else
					break;
				}
				ll=a[j-1].y-a[i-1].x;
			}
			else if(a[i].x<a[i-1].x)
			ll=a[i].y-a[i].x;
			else if(a[i].x>a[i-1].y)
			{
				ll=max(a[i].y-a[i].x,a[i-1].y-a[i-1].x);
			}
			if(milk<ll)
			milk=ll;

            if(a[i].x>a[i-1].y)
	    		{
	    		    temp=a[i].x;
	    		    for(j=i+1;j<num;j++)
	    		    {
	    		        if(a[j].x<temp)
	    		        {
	    		            temp=a[j].x;

	    		        }
	    		    }
	    		    rr=temp-a[i-1].y;
				}
				if(idle<rr)
	    		idle=rr;

		}
	}
    if(a[num-1].x<=a[0].x)
    idle=0;
	printf("%lld %lld\n",milk,idle);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值