貪心法——區間的最大覆蓋數



此題來源於BestCode第20期第二題。

簡單介紹下題意:

給一組區間,求在大的區間覆蓋數。每組測試數據小於100000,每個區間的範圍數Xi、Yi小於10的9次方.

想法:

看完題的第一反應聯想到的是校門外的數,可以類似的開一個相應的數組表示區間,初始化爲0,表示被覆蓋的次數。每輸入一個區間,將對應的區間+1。最後遍歷一遍數組,輸出最大值即可。但是仔細審題後發現不可以這麼做,Xi與Yi的最大值過大,開不出這麼大的數組。所以此種想法PASS

既然開不出這麼大的數組,只能考慮着存每個區間的範圍。開一個100000的二維數組a存每個區間的範圍,然後用每個區間的start值在各個區間中進行比較存於數組b中,對數組b快速排序,輸出最大值即可。但是此種方法超時,PASS

貪心就是我們的最終解法。當然這麼巧妙地解法也不是我們的原創的,還是VID想起之前做的一道題,稍作該做改動才AC的。


算法:

設m表示區間個數,times初始化爲0表示覆蓋次數

1.對每組區間按左端點值sta進行排序.

2.當m不爲0時循環以下操作.

①選出未被訪問的全部兩兩不相交的區間,對每個區間做訪問標記,同時m--;

②times++

這個方法的核心思想還是貪心。每次選出的不相交的區間可以想象成:選出不相交的區間,間斷連接組成一條連線。剩下的區間之所以沒被選中,肯定是因爲與此條線的某個線段有交集(沒交集就被合併了)。所以下次循環選出的連線,與之前的連線至少會有一點相交。所以說,我們能選出幾條這樣的連線,我們的區間最大覆蓋數就是幾。


這種算法的典型應用還有活動安排的問題和CPU處理進程問題。


附AC代碼,其中先輸入測試組數,其次輸入每組區間數,最後輸入各個區間(sta,end)。

#include<stdio.h>  
#include<stdlib.h>  
struct Table  
{  
   int sta;  
   int end;  
   int vist;  
};  
struct Table table[100005];  
int cmp(const void *a,const void *b)  
{  
  return (*(struct Table *)a).sta-(*(struct Table *)b).sta;  
}  
  
int main()  
{  
    int test,n,m,i,s,t,times,temp;  
    scanf("%d",&test);  
    while(test--)  
    {  
      scanf("%d",&n);  
      for(i=0;i<n;i++)  
      {  
        scanf("%d%d",&s,&t);  
        if(s>t)  
        {  
           s=s+t;  
           t=s-t;  
           s=s-t;  
        }  
  
        table[i].sta=s;  
        table[i].end=t;  
        table[i].vist=0;  
      }  
      qsort(table,n,sizeof(struct Table),cmp);  
      temp=0;  
      times=0;  
      m=n;  
      while(m)  
      {  
        for(i=0;i<n;i++)  
        {  
            if(!table[i].vist&&table[i].sta>temp)  
            {  
                temp=table[i].end;  
                table[i].vist=1;  
                m--;  
            }  
        }  
        temp=0;  
        times++;  
      }  
      printf("%d\n",times);  
    }  
  return 0;  
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章