簡單的區間覆蓋問題

問題描述:用i表示x軸上座標爲[i-1,i]的區間(區間長度爲1),並給出M個不同的整數來表示M個這樣的區間。現在要求畫出幾條線段覆蓋住所有的區間,條件是:每條線段可任意長,但要求所畫線段長度之和最小,並且線段的數目不超過N

分析
    1) 整型數組p[M]表示所有從0開始的區間長度,假設p[M]已經
按從小到大的順序排好


    2) 如果N>=M,
那麼用 M條長度爲 1 的線段可以覆蓋住所有的區間,所求的線段總長爲 M;


3)如果N<M,可以按照如下的貪心準則解決:


① 如果N=1,即要用一條線段覆蓋住所有區間。


      線段總長:p[M-1]-p[0]+1。


bb


其中:p[0]=1  ,  p[1]=3  ,   p[2]=4 , ……,p[M-1]=M--區間總長度


② 如果N=2,即要用 2 條線段覆蓋住所有區間,相當於把N=1中的線段分爲兩部分,各覆蓋左、右區間。


如果線段在M個區間中不相鄰的區間之間斷開(如在p[0]與p[1]之間),這樣總長度小於斷開之前。【不相鄰的很多怎麼辦?】


線段總長度減少: p[1]-p[0]-1


cc


回顧我們的題目要求:求最小線段總長。



找到間隔最大的兩個相鄰區間,將之斷開。


   這一過程相當於找:d[i]=p[i]-p[i-1]-1(1<i<M)的最大值



如果N=3,相當於在N=2的方案下,將某條線段斷成兩截,並作可能的端點調整。


爲了得到當前情況下最小的總長度,同樣應該在間隔最大的兩個相鄰區間之間斷開


    如果原來的方案是N=2時總長最小的方案,這一操作是N=3時總長最小的方案。



當N=k(k>1)時依此類推,只需在N=k-1時最小總長的覆蓋方案下,找到被同一條線段覆蓋的間隔最大的兩個相鄰區間


------“貪心”地從間隔處斷開並調整兩邊線段的端點,就可以得到總長最小的方案



貪心策略就是每次從找到當前間隔最大的相鄰區間

例題

用i來表示x座標軸上座標爲[i-1,i]的長度爲1的區間,並給出N(1≤N≤200)個不同的整數,表示N個這樣的區間。

現在要求畫m條線段覆蓋住所有的區間,
條件是:每條線段可以任意長,但是要求所畫線段的長度之和最小,
並且線段的數目不超過N。
 

輸入

 輸入包括多組數據,每組數據的第一行表示點n,和所需線段數m,後面的n行表示點的座標

輸出

 輸出每組輸出佔一行表示線段的長度。

示例輸入

5 3
1 3 5 8 11

示例輸出

7

代碼

#include <iostream>
#include <algorithm>
using namespace std;
int a[1000];
int s[1000];
int cmp(int a,int b)
{
  return a>b;
}
int main()
{
    int n,m;
    int len;
    int sum;
    while(cin>>n>>m)
    {
     for(int i=0;i<=n-1;i++)
     {
      cin>>a[i];
     }
     sort(a,a+n);
     len=a[n-1]-a[0]+1;
     for(int i=0;i<n-1;i++)//求區間的間隔距離
     {
      s[i]=a[i+1]-a[i]-1;
     }
     sort(s,s+n-1,cmp);
     sum=len;
     for(int i=0;i<m-1;i++)
     {
      sum=sum-s[i];
     }
    cout << sum << endl;
    }
    return 0;
}


整個過程說白了就是排序,沒啥。

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