編程練習(二)——調度所有區間

題目:蓄欄保留問題
總時間限制:1000ms 內存限制:65536kB
題目來源:OpenJudge

描述

農場有N頭牛,每頭牛會在一個特定的時間區間[A, B](包括A和B)在畜欄裏擠奶,且一個畜欄裏同時只能有一頭牛在擠奶。現在農場主希望知道最少幾個畜欄能滿足上述要求,並要求給出每頭牛被安排的方案。對於多種可行方案,主要輸出一種即可。

輸入

輸入的第一行包含一個整數N(1 ≤ N ≤ 50, 000),表示有N牛頭;接下來N行每行包含兩個數,分別表示這頭牛的擠奶時間[Ai, Bi](1 ≤ A≤ B ≤ 1, 000, 000)。

輸出

輸出的第一行包含一個整數,表示最少需要的畜欄數;接下來N行,第i+1行描述了第i頭牛所被分配的畜欄編號(從1開始)。

樣例輸入

5
1 10
2 4
3 6
5 8
4 7

樣例輸出

4
1
2
3
2
4

題解:C++

時間:243ms

#include <iostream>   
#include <queue>  
using namespace std;
struct node_cow
{   
    int start, end;//區間開始時間和結束時間
    int index;//牛的編號
    friend bool operator < (node_cow a, node_cow b) {
        //start小的優先級高;
        return a.start > b.start;
    }
};
struct node_end {
    int min_end;
    int num_class;
    friend bool operator <(node_end a, node_end b) {
        return a.min_end > b.min_end;
    }
};
priority_queue<node_cow>nc;
priority_queue<node_end>ne;
int main() {
    int n;
    int num = 0;
    cin >> n;
    node_cow temp_nc;
    node_end temp_ne;
    int *r = new int[n];
    for (int i = 0; i < n; i++) {
        cin >> temp_nc.start >> temp_nc.end;
        temp_nc.index = i;
        nc.push(temp_nc);
    }
    while (!nc.empty()) {
        temp_nc = nc.top();
        nc.pop();
        if (ne.empty()) {//如果已分配隊列爲空
            num++;
            temp_ne.min_end = temp_nc.end;
            temp_ne.num_class = num;
            ne.push(temp_ne);
            r[temp_nc.index ] = num;
        }
        else {
            temp_ne = ne.top();
            if (temp_nc.start <= temp_ne.min_end) {//分配新桶
                num++;
                temp_ne.min_end = temp_nc.end;
                temp_ne.num_class = num;
                ne.push(temp_ne);
                r[temp_nc.index ] = num;
            }
            else {
                ne.pop();
                temp_ne.min_end = temp_nc.end;
                ne.push(temp_ne);
                r[temp_nc.index ] = temp_ne.num_class;
            }
        }
    }//end while
    cout << num << endl;
    for (int i = 0; i < n; i++)
        cout << r[i] << endl;
    return 0;
}

總結

這是一道調度所有區間使所用資源數達到最小的問題。首先對於區間按照開始時間依次遞增排序,然後對已經分配的區間,記錄最小結束時間的區間以及其所在的蓄欄。對於每一個未曾分配的區間,如果其開始時間不大於最小結束時間,那麼需要分配新的資源(蓄欄),如果其開始時間大於最小結束時間,那麼就不需要新的資源,把該區間分配給最小結束時間所在的資源,然後更新已分配資源最小結束時間。
需要注意的是,用優先隊列可能纔不至於超時。我第一次用了vector容器和sort排序函數,結果一直時間超限,最後用了優先隊列才避免了這個問題。但是最終程序的時間也是243ms.
如果有更優的解法,希望朋友能分享給我,謝謝了。

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