題目:蓄欄保留問題
總時間限制: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.
如果有更優的解法,希望朋友能分享給我,謝謝了。