题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1303
题目大意:读入一个整数m(1<=m<=5000)。
接下来若干行,表示若干条线段。
从l[i]到r[i](最多50000条线段)到一行0 0为止。
求最少要用多少条线段可以覆盖区间[0,m]。
输出第一行一个数字,表示最少线段数。
接下来若干行表示选择的线段。按照顺序!!!
若无解则输出'No solution'。
题解:ural把这道分到dp里面,其实是道贪心
先排序,然后去掉重复数据,然后贪心找一个起点距离坐标0最近并且覆盖了0的线段,选中,然后找下一个距离上一条选中线段终点最近(舍弃其他较远的线段,也可用反证法证明)并且覆盖了终点的线段,选中……直到覆盖到了坐标M
还是太菜太菜,参考别人的思路,还wa了两次%>_<%
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct line{
int x,y;
}l[100000],ans[100000];
bool cmp(line a,line b)
{
return (a.x<b.x ||(a.x==b.x&&a.y>b.y));
}
int main()
{
int n=0,x,y,m,i;
scanf("%d",&m);
while(scanf("%d%d",&x,&y)!=EOF)
{
if(x==0&&y==0)
break;
l[n].x=x;
l[n++].y=y;
}
sort(l,l+n,cmp);
int k=0,cnt=0,j=0;
for(i=1;i<n;i++)
{
if((l[i].x>l[j].x)&&(l[i].y>l[j].y))
l[++j]=l[i];
}
n=j;
l[n+1].x=m+1;l[n+1].y=m+1;
for(i=0;i<=n;i++)
{
if(l[i+1].x>k&&l[i].x<=k)
{
k=l[i].y;
ans[cnt++]=l[i];
if(l[i].y>=m)
{
printf("%d\n",cnt);
for(j=0;j<cnt;j++)
printf("%d %d\n",ans[j].x,ans[j].y);
return 0;
}
}
}
printf("No solution\n");
return 0;
}