之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結:
區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題;
其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會;
一、區間不相交
當出現這鐘情況的時候,我們應該優先選擇i1,因為這樣的話就可以給其他區間騰出很多的空閒位置;
其次,當消除了所有子區間重疊問題的時候,我們會有如下的情況出現:
對於這種情況,我們採用的是對各個區間按照左端點的大小進行排序,此時就會形成上圖的情況,每個區間的有右邊節點有序;
**如下所示:
#include#include#includeusing namespace std;
修改為const int maxn=110;
struct intevali[maxn];
bool cmp(inteval a,inteval b){
if(a.x!=b.x)
return a.x>b.x;//左端從大到小進行排序
else
return a.y其實最難理解的應該是**中的處理,這裡給出詳細的解釋:
首先來看排序函式
bool cmp(inteval a,inteval b){
if(a.x!=b.x)
return a.x>b.x;//左端從大到小進行排序
else
return a.y這裡之所以要在左端大小相同的情況下對右端進行遞增排序,是為了找出包含區間中的最小的子區間;
這樣進行排序的時候,就會變成存在包含關係的區間在一起,但是首位肯定是包含區間中的最小區間;
之後就是主體處理;
while(scanf("%d",&n),n!=0){
for(int i=0;i這裡注意for迴圈,其實就是對陣列進行上述分析的第二部處理,從右向左,尋找不重合的區間(由於排序函式的操作,找到的必定是重合區間中的最小區間),迴圈從而使得每次選擇出來的都是最小的不重合的區間;
個人認為,區間不重疊的貪心思路主要體現在尋找最小的包含區間上;對於每一塊有重合情況的區間,我們只需要找出每一塊的重合區間中的最小區間,就可以組合成不重疊的區間,並且這些區間肯定數目最大,符合題意;
二、區間選點
區間選點可以視為第一種問題的衍生問題,目的是將給出開區間(注意,這裡是開區間)中選擇點,使得每個區間都至少有乙個點;
該問題也涉及重疊區間的問題。
還是一樣,當上述情況發生的時候,我們如果點放在i1內,就會使得i2內也存在點;所以根本上來說,我們還是尋找重疊區間內最小的區間;
因此,我們採用的還是第一類問題的操作,但是需要注意的就是點的選取;
對於有序的序列,我們應該把點選在左端點,而不是右端點;
關於這個問題,可以這樣想:
對於上述情況,如果選取右端點,就會出現選擇兩個的情況,但是如果選取左端點,就只用選取乙個;
所以,只需要對之前的**進行修改,修改乙個判定條件;
將i[i].y<=lastx
i[i]即可
關於區間貪心的補全
之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結 區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題 其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會 一 區間不相交 當出現這鐘...
關於區間貪心的補全
之前在部落格裡總結過貪心演算法的相關注意概念,但是由於當時理解不夠,並沒有很好的總結區間貪心問題,所以在這裡做乙個總結 區間貪心演算法總的來說有兩大題型,乙個是區間不相交問題,乙個是區間選點問題 其實第二種問題是第一種問題的子問題,並且對於貪心演算法中的概念一定要有所體會 一 區間不相交 當出現這鐘...
貪心 區間貪心
給出n個開區間 x,y 從中選擇盡可能多的開區間,使得這些開區間兩兩沒有交集。先對左端點 從大到小 排序,如果左端點相同就對右端點從小到大排序。區間不相交問題 include include using namespace std const int maxn 110 區間結構體 struct in...