Problem Description
给出x轴上N条线段的坐标,从中选择一些线段来覆盖住区间[0,M],要求所用线段数目最少。
Input Description
第一行输入两个整数0<N<10000,0<M<1000000,分别表示线段的数量和需要覆盖的区间[0,M]。
接下来N行,每行输入两个整数,分别表示第i条线段的左端点和右端点。
Output Description
在一行中输出 "the answer is 所选线段数量"。
若无解则输出 "wrong!"
Sample Input
3 1 -1 0 -5 -3 2 5 6 4 -1 0 -1 1 0 3 2 4 2 5 4 5
Sample Output
wrong! the answer is 2
个人分析:
解决本题使用的是贪心算法
首先我们需要将数据进行排序,排序是基于线段的左端点进行排序的,将左端点,由小到大进行排序(我是用的插空排序)
然后,在线段的左端满足last_right的情况下,选择右端尽可能最长的线段进行覆盖(设置一个noew_right代表已经覆盖的线段的右端,因为now_right是不断更新的,所以用last_right记录上一次的now_right)。
#include<stdio.h>
typedef struct Line
{
int left;
int right;
}Line;
void sort(Line a[], int n)
{
for(int i = 1; i < n; i++)
{
Line tmp = a[i];
int j = i - 1;
while(a[j].left > tmp.left && j >= 0)
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = tmp;
}
}
int main()
{
int n, m;
while(scanf("%d %d", &n, &m) != EOF)
{
Line line[n];
Line tmp[n];
for(int i = 0; i < n; i++)
{
scanf("%d %d", &line[i].left, &line[i].right);
}
for(int i = 0; i < n; i++)
{
tmp[i] = line[i];
}
int num = 0;
sort(line, n);
int last_right = 0, now_right = 0;
int i = 0;
int e = 0;
while(now_right < m)
{
last_right = now_right;
while(i < n && line[i].left <= last_right)
{
if(line[i].right > now_right)
{
now_right = line[i].right;
}
i++;
}
num++;
e++;
if(i == n && now_right < m || now_right == last_right)
{
break;
}
}
if(now_right < m)
{
printf("wrong!\n");
}
else
{
printf("the answer is %d\n", num);
}
}
return 0;
}