POJ 2376 Cleaning Shifts(區間貪心之區間覆蓋)

sunlanchang發表於2019-02-02

Description

有一些奶牛,每隻奶牛負責一個時間段。問覆蓋完全部的時間段最少需要多少隻奶牛。若不能全部覆蓋,輸出-1

Input

第一行為兩個整數N和T表示奶牛數量和總時間,之後N行每行兩個整數表示該頭奶牛負責的時間段

Output

若能覆蓋完全部的時間段輸出最少奶牛數量,若不能全部覆蓋,輸出-1

Sample Input

3 10
1 7
3 6
6 10

Sample Output

2

Solution

區間覆蓋貪心。設T為當前所有已確定區間的最右端,那我們可以每次都取所有可選的小區間(左端點<=T+1)中右端點最大的值,然後更新最右端點ans++,初始時t=0。而由於如果有解t的值是遞增的,那每次選區的區間的左端點也必然是遞增的,所以先排序然後掃描 。

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 25555;
struct Cow
{
    int start, end;
    bool operator<(const Cow &t) const
    {
    //開始時間從小到大
        if (start != t.start)
            return start < t.start;
      //結束時間從大到小
        return end > t.end;
    }
} cow[maxn];

int main()
{
    // freopen("in.txt", "r", stdin);
    int N, T;
    while (~scanf("%d%d", &N, &T))
    {
        for (int i = 0; i < N; i++)
            scanf("%d%d", &cow[i].start, &cow[i].end);
        sort(cow, cow + N);
        int last_y = 0, ans = 0, i = 0;
        while (last_y < T && i < N)
        {
            ans++;
            int tmp_y = last_y;
            if (cow[i].start > last_y + 1) //中途缺失,無法全部覆蓋。
                break;
            while (cow[i].start <= last_y + 1 && i < N) //在可選區間內選取右端點最大值
            {
                tmp_y = max(tmp_y, cow[i].end);
                i++;
            }
            last_y = tmp_y; //更新最右端點
        }
        if (last_y >= T)
            printf("%d\n", ans);
        else
            printf("-1\n");
    }
    return 0;
}

參考https://blog.csdn.net/V5ZSQ/article/details/46828461

相關文章