UVA 10020 - Minimal Coverage

UVA 10020 - Minimal Coverage

LAVI

解題觀念

Greedy - 區間最小覆蓋

可以參考我的課程簡報:Greedy & Graph

題目敘述

給定多組線段座標 [Li, Ri] (在 x 軸上)
請選擇以最少數量的線段,使得選擇的線段完全覆蓋 [0, M]

Input

輸入的第一行有一整數 t,表示測茲的數量
接下來每組測資的第一行為空白行
第二行為一整數 M
表示需覆蓋的線段最右值 (1 <= M <= 5000)
接下來有多行
每行有兩個整數 Li、Ri
表示可用線段的最左值及最右值
(|Li|、|Ri| <= 50000,i <= 100000)
若 Li == Ri == 0 則此組測資結束

1
2
3
4
5
6
7
8
9
10
11
12
2

1
-1 0
-5 -3
2 5
0 0

1
-1 0
0 1
0 0

Output

每組測資輸出
第一行輸出最少須選擇多少線段以覆蓋 [0, M]
接下來多行輸出選擇的線段座標
(依據 Li 由小到大排序)
如果所有可用線段無法使 [0, M] 被完全覆蓋則輸出 “0”

每組輸出之間需相隔一行

1
2
3
4
0

1
0 1

解題觀念簡報參考

STL - Vector

Greedy - 區間最小覆蓋

Solution Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<bits/stdc++.h>
using namespace std;

struct Node{
int lef, rig;

// 左邊由小到大 右邊由大到小
bool operator < (const Node &rhs) const{
if(lef == rhs.lef) return rig > rhs.rig;
else return lef < rhs.lef;
}
};

int main(){
int t;
cin >> t;

bool space = false;
while(t--){
if(space) cout << endl;
space = true;

int M;
cin >> M;

vector<Node> seg;
int lef, rig;
while(cin >> lef >> rig && (lef || rig)){
seg.push_back({lef, rig});
}
sort(seg.begin(), seg.end());

int ptrLef = 0, ptrRig = -1;
vector<pair<int, int>> ans;
while(ptrRig < M){
int tmpLef = -50001;
for(int j = 0; seg[j].lef <= ptrLef && j < seg.size(); ++j){
if(seg[j].rig > ptrRig){
ptrRig = seg[j].rig;
tmpLef = seg[j].lef;
}
}

if(tmpLef == -50001) break;
ans.push_back({tmpLef, ptrRig});
ptrLef = ptrRig;
}

if(ptrRig >= M){
cout << ans.size() << endl;
for(int j = 0; j < ans.size(); ++j){
cout << ans[j].first << " " << ans[j].second << endl;
}
}
else cout << "0" << endl;

seg.clear();
ans.clear();
}
}