挑战程序设计竞赛2.2习题:Cleaning Shifts POJ - 2376

Cleaning Shifts

Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning chores around the barn. He always wants to have one cow working on cleaning things up and has divided the day into T shifts (1 <= T <= 1,000,000), the first being shift 1 and the last being shift T.

Each cow is only available at some interval of times during the day for work on cleaning. Any cow that is selected for cleaning duty will work for the entirety of her interval.

Your job is to help Farmer John assign some cows to shifts so that (i) every shift has at least one cow assigned to it, and (ii) as few cows as possible are involved in cleaning. If it is not possible to assign a cow to each shift, print -1.

Input

* Line 1: Two space-separated integers: N and T

* Lines 2..N+1: Each line contains the start and end times of the interval during which a cow can work. A cow starts work at the start time and finishes after the end time.

Output

* Line 1: The minimum number of cows Farmer John needs to hire or -1 if it is not possible to assign a cow to each shift.

Sample Input

3 10
1 7
3 6
6 10

Sample Output

2
翻译,就是把时间分段,每头奶牛可以工作一段时间,请问怎么安排最少的奶牛使得所有时间段都能有奶牛的头数?
解决的方法就是先按照开始时间排序,如果第一个奶牛都没办法从1时刻开始,那么直接没了,如果第一头奶牛能干完,就没其他什么事了。
如果不行,那就判断第二头奶牛能不能在第一头结束前或者当时接班,记住:奶牛能干完直到结束时刻的下一时刻前,但是把一天分成T时刻且从1时刻开始计时,那么,一定要有T时刻结束的奶牛,否则1-T之间只有T-1时间段,题意要求T个时间段。继续,如果不能则-1,能就把第二头奶牛计数,继续计算下一头需要的奶牛,我们知道,只要在第二头奶牛结束的下一个时刻和之前开始的奶牛都能接上第二头奶牛的工作,所以我们遍历的起始时间是在小于等于第二头结束的后一时刻。计算在这些符合能接上第二头工作的奶牛中最长久的能干多久,我们由于要尽可能的少,肯定选最长久的,这样下一次能遍历选择的奶牛就更多,更能选出符合答案要求的结果。如此循环直到某一次遍历的结束时间是T。
AC代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
struct cow{
    int s;
    int e;
    friend bool operator <(cow x, cow y) {
        return x.s < y.s;
    }
}cows[25005];
int next, tnext;//next本次结束的时刻,tnext,开始时间在next + 1之内且结束时间最久的那个值
int num;
bool flag;//能不能行
int main(void)
{
    int n, t;
    scanf("%d %d", &n, &t);
    for(int i = 0; i < n; i++)
    {
        scanf("%d %d", &cows[i].s, &cows[i].e);
    }
    sort(cows, cows + n);
    num = 1;//选第一头
    if(cows[0].s != 1)
        flag = false;
    else if(cows[0].e >= t)
        flag = true;
    else
    {
        tnext = next = cows[0].e;
        for(int i = 1; i < t; i++)
        {
            if(cows[i].s > next + 1)//没有牛接上工作了
                break;
            while(i < t && cows[i].s <= next + 1)//找到下一头能接上工作且结束最晚的牛
            {
                tnext = max(tnext, cows[i].e);
                i++;
            }
            i--;//由于执行前的i指向开始不符合能接上本头牛的牛,所以i--方便下一次i++遍历
            num++;//找到了接班牛就要++,管他是哪头
            if(tnext <= next)//能接上工作的牛最晚结束也是在本次牛的结束时间,要不要无所谓,那就没有能接班的牛使得继续下面的时间段了,那么就-1
                break;
            next = tnext;//找到接班牛就要把结束时间换掉
            if(next >= t)//欸?这头牛的结束时间刚好干到结束,不用找了,结束。
            {
                flag = true;
                break;
            }
        }
    }
    if(flag)
        printf("%d\n", num); 
    else
        printf("-1\n");
        return 0;
}

 


posted @ 2020-01-15 16:58  funforever  阅读(161)  评论(0编辑  收藏  举报