用i来表示x坐标轴上坐标为[i-1,i]的长度为1的区间,并给出n个不同的整数,表示n个这样的区间。
现在要求画m条线段覆盖住所有的区间,
条件是:每条线段可以任意长,但是要求所画线段的长度之和最小,
并且线段的数目不超过m。
输入格式:
输入包括多组数据,每组数据的第一行表示区间个数n(1≤n≤200) 和所需线段数m(1≤m≤50),第二行表示n个点的坐标i(1≤i≤200)。
输出格式:
每组输出占一行,输出m条线段的最小长度和。
输入样例:
5 3
11 1 3 8 5
输出样例:
线段为3条时总长最小
线段的最小长度和为7
//区间覆盖问题实际上就是通过增加所画线段的条数来减少所画线段的长度之和
#include<stdio.h>
//升序
void sort1(int a[],int n)
{
int i,j,t;
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
//降序
void sort2(int a[],int n)
{
int i,j,t;
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]<a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
}
int main()
{
int m,n,i;
int p[200];//存放每个区间的右端点
int d[200];//存放区间之间的距离
scanf("%d %d",&n,&m);//n为区间个数,m为可使用的线段总数
for(i=0;i<n;i++)
{
scanf("%d",&p[i]);
}
sort1(p,n);//对区间进行升序排列(降序排列也可以,后面的计算区间距离和总长度也要改)
for(i=0;i<n-1;i++)
{
d[i]=p[i+1]-p[i]-1;//区间距离=区间的右端点-区间的右端点-区间长度
}
sort2(d,n-1);//对区间距离进行降序排列,以方便贪心过程中每次选择一个最大的区间间隔的要求。
if(m>=n)
{
printf("线段为%d条时总长最小\n",n);//如果m>=n,那么用n条长度为1的线段就可覆盖住所有区间
printf("线段的最小长度和为%d\n",n);
}
else
{
int nline=1;//用1条线段覆盖住所有区间
int totallength=p[n-1]-p[0]+1;//用1条线段覆盖住所有区间时的线段长度
int x=0;
while((nline<m)&&(d[x]>0))
{
nline++;
totallength=totallength-d[x];//线段为i条时的线段总长=线段为i-1条时的线段总长-最大的区间间隔
x++;
}
printf("线段为%d条时总长最小\n",nline);
printf("线段的最小长度和为%d\n",totallength);
}
return 0;
}