1. 程式人生 > >(貪心)區間問題大致思路

(貪心)區間問題大致思路

1.選擇不相交區間。

a.描述:

數軸上有n個開區間(ai, bi)。選擇儘量多個區間,使得這些區間兩兩 沒有公共點。

b.思路總結:

1.區間x完全包含y,選y
2.按照bi從小到大排序,從第一個區間開始選
3.把所有和上一個區間相交的區間排除在外

c.思路分析:

首先明確一個問題:假設有兩個區間x,y,區間x完全包含y。那麼,選x是不划算的,因 為x和y最多隻能選一個,選x還不如選y,這樣不僅區間數目不會減少,而且給其他區間留出 了更多的位置。接下來,按照bi從小到大的順序給區間排序
貪心策略是:一定要選第一個 區間。

現在區間已經排序成b1≤b2≤b3…了,考慮a1和a2的大小關係。

情況1:a1>a2,如圖所示,
這裡寫圖片描述
區間2包含區間1。前面已經討論過,這種情況下一 定不會選擇區間2。不僅區間2如此,以後所有區間中只要有一個i滿足a1>ai,i都不要選。在 今後的討論中,將不考慮這些區間。
情況2:排除了情況1,一定有a1≤a2≤a3≤…,如圖所示。
這裡寫圖片描述

如果區間2和區間1完全 不相交,那麼沒有影響(因此一定要選區間1),否則區間1和區間2最多隻能選一個。如果 不選區間2,區間1的1部分其實是沒有任何影響的(它不會擋住任何一個區間),區間1的有效部 分其實變成了2部分,它被區間2所包含!由剛才的結論,區間2是不能選的。依此類推, 不能因為選任何區間而放棄區間1,因此選擇區間1是明智的。
選擇了區間1以後,需要把所有和區間1相交的區間排除在外

,需要記錄上一個被選擇的 區間編號。這樣,在排序後只需要掃描一次即可完成貪心過程,得到正確結果。

2.區間選點問題。

a.描述:

數軸上有n個閉區間[ai, bi]。取儘量少的點,使得每個區間內都至少有 一個點(不同區間內含的點可以是同一個)。

b.思路總結:

1.按b從小到大排序(b相同時a從大到小排序)
2.區間包含的情況 下,大區間不需要考慮。
3.取最後一個點

c.思路分析:

如果區間i內已經有一個點被取到,則稱此區間已經被滿足。受上一題的啟發,下面先 討論區間包含的情況。由於小區間被滿足時大區間一定也被滿足,所以在區間包含的情況 下,大區間不需要考慮。


把所有區間按b從小到大排序(b相同時a從大到小排序),則如果出現區間包含的情 況,小區間一定排在前面。第一個區間應該取哪一個點呢?此處的貪心策略是:取最後一個 點
這裡寫圖片描述
根據剛才的討論,所有需要考慮的區間的a也是遞增的,可以把它畫成圖8-8的形式。如 果第一個區間不取最後一個,而是取中間的,如a點,那麼把它移動到最後一個點b後,被 滿足的區間增加了,而且原先被滿足的區間現在一定被滿足。不難看出,這樣的貪心策略是 正確的。

3.區間覆蓋問題。

a.描述:

數軸上有n個閉區間[ai, bi],選擇儘量少的區間覆蓋一條指定線段[s,t]。

b.思路總結:

1.每個區間在[s, t] 外的部分都應該預先被切掉
2.按照a從小到大排序,選擇起點在s的最長區間[ai,bi]
3.新的起點應 該設定為bi,忽略所有區間在bi之前的部分

c.思路分析:

本題的突破口仍然是區間包含和排序掃描,不過先要進行一次預處理每個區間在[s, t] 外的部分都應該預先被切掉,因為它們的存在是毫無意義的。預處理後,在相互包含的情況 下,小區間顯然不應該考慮
把各區間按照a從小到大排序。如果區間1的起點不是s,無解(因為其他區間的起點更 大,不可能覆蓋到s點),否則選擇起點在s的最長區間。選擇此區間[ai, bi] 後,新的起點應 該設定為bi,並且忽略所有區間在bi之前的部分,就像預處理一樣。雖然貪心策略比上題復 雜,但是仍然只需要一次掃描
這裡寫圖片描述
s為當前有效起點(此前部分已被覆蓋),則 應該選擇區間2。