小Q在进行一场竞技游戏,这场游戏的胜负关键就在于能够能争夺一条长度为L的河道,即可以看作是[0,L]的一条数轴。
这款竞技游戏当中有n个可以提供视野的道具-真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在小Q想知道至少用几个真视守卫就可以覆盖整段河道。
输入:
输入包括n+1行。
第一行包括两个整数n和L(1<=n<=10^5,1<=L<=10^9)
接下来的n行,每行两个正整数xi,yi(0<=xi<=yi<=10^9),表示第i个真视守卫覆盖的区间。
输出:
一个整数,表示最少需要的守卫的数量,如果无解,输出-1。
分析:典型的贪心法。首先,关键的一点是需要将数组进行排序,我的解法是:首先对于输入的看做结构体,对其按照起始点进行排序。排序之后,设置当前的找到的末端,然后寻找起始点在当前末端之前的,能够向最远延伸的绳子,并且把这个绳子的结束点当做目前的末端。
结束条件:当前末端>=L,成功;没有找到满足上面条件的,返回-1.
代码如下:
struct guard{
int start;
int end;
};
bool cmp(guard &g1, guard &g2){
if (g1.start == g2.start) return g1.end < g2.end;
else{
return g1.start < g2.start;
}
}
int main(){
//贪心法来做
int n, L;
cin >> n >> L;
vector<guard> GA;
guard g;
for (int i = 0; i < n; i++){
cin >> g.start >> g.end;
GA.push_back(g);
}
sort(GA.begin(), GA.end(), cmp);
//贪心法
int ret = 0;
int rowstart = -1;
int rowend = 0;
int index = -1;
int cnt = 0;
bool noresult = false;
while (rowend<L)
{
int tmpend = rowend;
bool find = false;
for (int i = index + 1; i < n; i++){
if (GA[i].end <= rowend) continue;
//如果起始点都已经大于目前的末端了,就跳出循环,因为是按照起始点的升序排列的,后面的更不可能满足条件
if (GA[i].start > rowend) break;
/*要覆盖0~L的所有范围,所以对于每个点,选择之后都要尽量向远延伸*/
if (tmpend < GA[i].end){
find = true;
index = i;
tmpend = GA[i].end;
}
}
if (!find){//没有找到,说明不存在能接上去的绳子了
break;
}
else{
rowend = tmpend;
cnt++;
}
}
cout<< (rowend < L ? -1 : cnt);
system("pause");
return 0;
}
自己太菜了,要多学习,多思考。