1. 程式人生 > >2376 貪心-區間問題

2376 貪心-區間問題

題目容易陷入的誤區:

題目表面上是儘可能少的去覆蓋區間,其實是儘可能的去覆蓋點,這點容易導致大家WA

思路:

按照結束時間倒敘排列,從末端開始向前儘可能向前去包含更多的點

注意:

WA多半是你想成了包含區間段而不是點(去試一試下面的樣例1,答案是4)

RE多半是你省略了不存在的情況,迴圈沒有跳出

TLE多半是寫的太暴力,優化下時間

程式碼:  

#include <iostream>
#include <algorithm>
#include <cstdio>

#define     max(x, y)   x >= y ? x : y
#define     min(x, y)   x < y ? x :y

#define     INF         0x3f3f3f3f

#define     sd(x)       scanf("%d", &x)
#define     pd(x)       printf("%d\n", x)
#define     slld(x)     scanf("%lld", &x)
#define     plld(x)     printf("%lld\n", x)

#define     sdd(x, y)    scanf("%d%d", &x, &y)

using namespace std;

const int maxn = 250005;

typedef long long ll;

typedef struct node
{
    int s, e;

}node;

node a[maxn];
int n, t;

bool cmp(node s1, node s2)
{
    if (s1.e == s2.e) return s1.s <= s2.s;
    else return s1.e > s2.e;
}

int main()
{
    sdd(n, t);
    for (int i = 0; i < n; i++) sdd(a[i].s, a[i].e);

    sort(a, a + n, cmp);
//print();
    if (a[0].e < t) {cout << -1 << endl; return 0;}

    int now = a[0].s - 1;
    int ans = 1;
    int inx = 1;
    while (now >= 1)
    {
        int Min = INF;
        int sign, flag = 0;

        while (a[inx].e >= now) {
                flag = 1;
            if (a[inx].s < Min) {
                sign = inx;
                Min = a[inx].s;
            }
            inx++;
        }

        if (flag) {
            ans++;
            now = a[sign].s - 1;
        }
        else inx++;
        if (inx == n && now >= 1) {ans = -1; break;}
    }
    pd(ans);
    return 0;
}

奉獻一組資料:

/*
input:
10 10
1 3
2 4
3 5
4 6
5 7
6 8
7 9
8 10
9 10
10 10

output: 4
/*