問題描述:用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。
其中: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
回顧我們的題目要求:求最小線段總長。
找到間隔最大的兩個相鄰區間,將之斷開。
這一過程相當於找: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個這樣的區間。
輸入
輸出
示例輸入
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;
}
整個過程說白了就是排序,沒啥。