题目链接:传送门
分析:给出长度的有边界点坐标,然后再给出多组线段的左右坐标,判断所给出的线段是否能够覆盖完题目要求的区间。
解题思路:开个结构数组记录线段左右点,排序,左边小的在前面,然后用那些左边小于要求,右边又比较远的线段填充进去。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct line { //记录线段的左右点
int left,right;
} k[100000],map[100000]; //k是用来记录线段,map用来记录路径
bool cmp(line a,line b) {
if(a.left=b.left) return a.right>b.right;
else return a.left<b.left;
}
int main() {
int T;
cin>>T;
cout<<endl;
while(T--) {
int m;
cin>>m;
int l,r,ans=0;
while(cin>>l>>r) {
if(l==0&&r==0) break;
k[ans].left=l;
k[ans++].right=r;
}
sort(k,k+ans,cmp); //排序
line N; 初始的左边点
N.left=0;
N.right=0;
int maxr=0,maxl;
int num=0;//记录区间数量
int flag; //用来判断是否有更新,如果没更新就跳不出循环也代表着无法覆盖
while(N.right<m) { //当坐标右点大于m时就覆盖完了
flag=0;
for(int i=0; i<ans; i++) {
if(k[i].left<=N.left&&k[i].right>N.right&&k[i].right>maxr) {
maxr=k[i].right;//遍历一次记录符合条件并且右边坐标延申最远的点
maxl=k[i].left;
flag=1;
}
}
if(flag==0) break;
N.left=maxr; //再次将初始坐标记录为右点
N.right=maxr;
map[num].left=maxl; //记录路径
map[num++].right=maxr;
}
if(flag==0) cout<<"0"<<endl<<endl;
else {
cout<<num<<endl;
for(int i=0; i<num; i++)
cout<<map[i].left<<" "<<map[i].right<<endl;
}
}
}