求最小子覆盖的问题,
想法是把输入的区间集,按照左端点进行升序排序,最左边的开始找右边,找伸展得最远的一个点,
然后在0到这个点之内循环直到覆盖(0,m)否则就没有输出结果。
#include "stdio.h"
#define MAX 100001
int left[MAX] , right[MAX] , ansl[MAX] , ansr[MAX];
void qs(int s , int e)
{
int x = left[s] , l = s , r = e , t;//以第一个数为参照做比较
if(l >= r)
return;
while(l < r)
{
while(l < r && left[r] >= x)
r--; //不小于分界值的留在右边,遇到小于的停止
left[l] = left[r];
t = right[l];
right[l] = right[r];
right[r] = t;
while(l < r&& left[l] <= x)
l++; //小于分界值的留在左边,遇到不小于的停止
left[r] = left[l];
t = right[l];
right[l] = right[r];
right[r] = t;
}
left[r] = x;
qs(s,r-1);
qs(r+1,e);//递归
}
int main()
{
int q , m , tot = 0 , i , j , k = 1 , l , r , n = 0 , count = 0 , max_p = 0 , pos;
scanf("%d",&m);
while(1)
{
scanf("%d %d",&l,&r);
if( l == 0 && r == 0 )
break;
else
{
n++;
left[k] = l;
right[k] = r;
k++;
}
}
qs(1,n);
j = 1 ;
for( i = 2 ; i <= n ; i++ )
{
if(left[i] > left[j] && right[i] > right[j])
{
left[++j] = left[i];
right[++j] = right[i];
}
}
n = j ;
j = 0 ;
left[n+1] = m+1 ;
right[n+1] = m+1 ;
for( i = 1 ; i <= n ; i++ )
{
if(left[i+1] > j && left[i] <= j)
{
j = left[i];
ansl[++tot] = left[i];
ansr[tot] = right[i];
if(right[i] >= m)
{
printf("%d\n",tot);
for( q = 1 ; q <= tot ; q++ )
printf("%d %d",ansl[q],ansr[q]);
return 0;
}
}
}
printf("No solution\n");
return 0;
}