ACM知識點 之 貪心(3)區間選點問題
區間選點的問題大致可以描述為:
給定N個區間[a,b],取儘量少的點,使得每個區間內都至少有一個點(不同區間內含的點可以重複)。
關於貪心演算法的驗證過程就不再贅述,現在思考一下貪心策略的制定。
對於區間[a1, b1] 、[a2, b2]、 [a3, b3] 來說,
如果想選擇最少的點,那麼必須選擇每個區間的右端點,示意圖如下:
當你每一次都選擇區間的最右端,才能保證每一個選的點覆蓋的範圍都是最廣泛的,也就是說選的點才是最少的。
和之前不相交區間的思考方法類似,把區間進行預處理,按照端點的大小排序(同樣,按照右端點排序會好理解一點,但是左端點排序一樣可以起到作用,初學者不必迷信右端點排序)。
預處理過後,求解策略的思路和求不相交區間相似,如果下一個區間的左端點不被覆蓋,則答案+1,如下:
while(剩餘區間的數目不為0)
{
if(找到符合條件的下一個區間)
{
當前區間 = 下一個區間;
答案數+1;
}
區間數--;
}
非洲小孩
時間限制:1000 ms | 記憶體限制:65535 KB
難度:2
描述
家住非洲的小孩,都很黑。為什麼呢?
第一,他們地處熱帶,太陽輻射嚴重。
第二,他們不經常洗澡。(常年缺水,怎麼洗澡。)
現在,在一個非洲部落裡,他們只有一個地方洗澡,並且,洗澡時間很短,瞬間有木有!!(這也是沒有的辦法,缺水啊!!)
每個小孩有一個時間段能夠洗澡。並且,他們是可以一起洗的(不管你是男孩是女孩)。
那麼,什麼時間洗澡,誰應該來洗,由誰決定的呢?那必然是他們偉大的“澡”神啊。“澡”神有一個時間表,記錄著該部落的小孩,什麼時候段可以洗澡。現在,“澡”神要問你,一天內,他需要最少開啟和關閉多少次洗澡的水龍頭呢?因為,開啟和關閉一次水龍頭是非常的費力氣的,即便,這也是瞬間完成的。
輸入
多組資料
第一行一個n<=100。
接下來n行,每行一個時間段。H1H1:M1M1-H2H2:M2M2,24小時制。
保證該時間段是在一天之內的。但是,不保證,H1H1:M1M1先於H2H2:M2M2。
輸出
題目描述,“澡”神最少需要開啟和關閉多少次水龍頭呢?
樣例輸入
1
00:12-12:12
2
00:12-12:12
14:00-12:00
樣例輸出
1
1
提示
Ps:開啟和關閉為一次
這道題是完美的區間選點,但是資料有坑(不保證H1H1:M1M1先於H2H2:M2M2。) 所以讀入的時候要注意進行判斷。
解決程式碼如下:
/* ************************************ Title: NYOJ1036-非洲小孩 ************************************ Date:2015/07/23 ************************************ author:劉旭 ************************************ Memory:256KB Time:8ms ************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MAX 1005 struct Node { int x; int y; }; Node map[MAX]; bool cmp(Node a,Node b){ if(a.y != b.y){ return a.y < b.y; } return a.x < b.x; } int main() { int num = 0; while(EOF != scanf("%d", &num)){ memset(map, -1, sizeof(map)); int a1,b1,a2,b2; for(int i = 0; i < num; i++){ scanf("%d:%d-%d:%d",&a1,&b1,&a2,&b2); int key1 = a1*60+b1; int key2 = a2*60+b2; if(key1 > key2){ swap(key1, key2); } map[i].x = key1; map[i].y = key2; } sort(map, map+num, cmp); int start = map[0].y; int num_node = 0; int ans = 1; while(num - num_node){ if(map[num_node].x > start){ start = map[num_node].y; ans++; } num_node++; } printf("%d\n", ans); } return 0; }