每日四題打卡-4.16:貪心-區間覆蓋/貪心-區間分組/貪心-最大不相交區間數量/貪心-區間選點

貪心-區間覆蓋

給定N個閉區間[ai,biai,bi]以及一個線段區間[s,ts,t],請你選擇儘量少的區間,將指定線段區間完全覆蓋。

輸出最少區間數,如果無法完全覆蓋則輸出-1。

輸入格式

第一行包含兩個整數s和t,表示給定線段區間的兩個端點。

第二行包含整數N,表示給定區間數。

接下來N行,每行包含兩個整數ai,biai,bi,表示一個區間的兩個端點。

輸出格式

輸出一個整數,表示所需最少區間數。

如果無解,則輸出-1。

數據範圍

1≤N≤1051≤N≤105,
−109≤ai≤bi≤109−109≤ai≤bi≤109,
−109≤s≤t≤109−109≤s≤t≤109

輸入樣例:

1 5
3
-1 3
2 4
3 5

輸出樣例:

2

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
struct Range
{
    int l, r;
    bool operator< (const Range &w)const
    {
        return l < w.l;
    }
}range[N];
int main()
{
    int st, ed;
    cin >> st >> ed >> n;
    //cin >> n;
    for (int i = 0; i < n; i ++)
    {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    sort(range, range + n);
    int res = 0;
    bool success = false;
    for (int i = 0; i < n; i ++)
    {
        int j = i, r = -2e9;
        while (j < n && range[j].l <= st)//找到一個能覆蓋st並且右端點最長的值
        {
            r = max(r, range[j].r);
            j ++;
        }
        if (r < st)//如果最後找到的值沒有能覆蓋st的就break,如果沒有這一步,遇到全部都是大於st的區間就會TLE
        {
            res = -1;
            break;
        }
        res ++;
        if (r >= ed)//如果st已經大於ed了就break
        {
            success = true;
            break;
        }
        st = r;//更新st
        i = j - 1;
    }
    if (!success) res = -1;//判斷一下最後覆蓋到的區間是否已經過了ed
    cout << res << endl;
    return 0;
}

貪心-區間分組

給定N個閉區間[ai,bi],請你將這些區間分成若干組,使得每組內部的區間兩兩之間(包括端點)沒有交集,並使得組數儘可能小。

輸出最小組數。

輸入格式

第一行包含整數N,表示區間數。

接下來N行,每行包含兩個整數ai,biai,bi,表示一個區間的兩個端點。

輸出格式

輸出一個整數,表示最小組數。

數據範圍

1≤N≤1051≤N≤105,
−109≤ai≤bi≤109−109≤ai≤bi≤109

輸入樣例:

3
-1 1
2 4
3 5

輸出樣例:

2

分情況討論貪心決策:

1.如果一個區間的左端點比當前每一個組的最右端點都要小,那麼意味着要開一個新區間了,這個條件還可以優化成,一個區間左端點比最小組的右端點都要小就開一個新組。
2.如果一個區間的左端點比最小組的右端點大,那麼就放在該組,這其實也是一個貪心,因爲是先考慮最容易放入一個區間的組

這道題對於數據結構上的選擇也要考慮,用一個小頂堆,也就是優先隊列來存儲每一個組的最右端點是最好的數據結構了。
 

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
int n;
struct Range
{
    int l, r;
    //< 排序
    bool operator< (const Range &w)const
    {
        return l < w.l;
    }
}range[N];
int main()
{
    //輸入
    cin >> n;
    for (int i = 0; i < n; i ++)
    {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    //排序
    sort(range, range + n);
    //定義小根堆,定義語法如下
    //來維護所有組的最大值
    priority_queue<int, vector<int>, greater<int>> heap;
    for (int i = 0; i < n; i ++)
    {
        //用r來代表區間
        auto r = range[i];
        //如果堆爲空或者堆頂最小值>=i區間左端點,區間需要開一個新的組
        if (heap.empty() || heap.top() >= r.l) heap.push(r.r);
        else
        {//否則這個區間放在最小值組中
            int t = heap.top();
            heap.pop();//出堆,把最小值堆頂刪掉刪掉
            heap.push(r.r);//加入新的右端點放進去
        }
    }
    cout << heap.size() << endl;//最後輸出組的數量
    return 0;
}

貪心-最大不相交區間數量

給定N個閉區間[ai,biai,bi],請你在數軸上選擇若干區間,使得選中的區間之間互不相交(包括端點)。

輸出可選取區間的最大數量。

輸入格式

第一行包含整數N,表示區間數。

接下來N行,每行包含兩個整數ai,biai,bi,表示一個區間的兩個端點。

輸出格式

輸出一個整數,表示可選取區間的最大數量。

數據範圍

1≤N≤1051≤N≤105,
−109≤ai≤bi≤109−109≤ai≤bi≤109

輸入樣例:

3
-1 1
2 4
3 5

輸出樣例:

2

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
//結構體排序
struct Range
{
    int l, r;
    bool operator< (const Range &w)const
    {
        return r < w.r;
    }
}range[N];
int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)
    {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    sort(range, range + n);
    int res = 0, ed = -2e9;
    //枚舉每個區間
    for (int i = 0; i < n; i ++)
        if (range[i].l > ed)
        {
            res ++;
            ed = range[i].r;
        }
    cout << res << endl;
    return 0;
}

貪心-區間選點

給定N個閉區間[ai,biai,bi],請你在數軸上選擇儘量少的點,使得每個區間內至少包含一個選出的點。

輸出選擇的點的最小數量。

位於區間端點上的點也算作區間內。

輸入格式

第一行包含整數N,表示區間數。

接下來N行,每行包含兩個整數ai,biai,bi,表示一個區間的兩個端點。

輸出格式

輸出一個整數,表示所需的點的最小數量。

數據範圍

1≤N≤1051≤N≤105,
−109≤ai≤bi≤109−109≤ai≤bi≤109

輸入樣例:

3
-1 1
2 4
3 5

輸出樣例:

2
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
//結構體排序
struct Range
{
    int l, r;
    bool operator< (const Range &w)const
    {
        return r < w.r;
    }
}range[N];
int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++)
    {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    sort(range, range + n);
    int res = 0, ed = -2e9;
    //枚舉每個區間
    for (int i = 0; i < n; i ++)
        if (range[i].l > ed)
        {
            res ++;
            ed = range[i].r;
        }
    cout << res << endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章