http://www.lydsy.com/JudgeOnline/problem.php?id=1007
题意:略
思路:容易想到最后的可见直线会围成个开口向上的半个凸包,所以我们可以先把直线汗斜率排序(凸包的边从左到右斜率递增),再将斜率最小的两条线入栈,然后依次处理每条线,如果其与栈顶元素的交点在上一个点的左边(凸包顶点横坐标递增),则将栈顶元素出栈 。
代码:
#include <cmath>
#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int maxn = 50005;
struct Point{
Point(double x = 0, double y = 0){
this->x = x;
this->y = y;
}
double x, y;
};
struct Line{
int id;
double a, b;
};
int n;
Line line[maxn];
int sta[maxn], top;
bool cmp1(const Line a, const Line b){
if(fabs(a.a - b.a) < eps)
return a.b < b.b;
return a.a < b.a;
}
bool cmp2(const int a, const int b){
return line[a].id < line[b].id;
}
Point GetPoint(Line a, Line b)
{
Point res;
res.x = (b.b - a.b) / (a.a - b.a);
res.y = res.x * a.a + a.b;
return res;
}
void Insert(int pos)
{
while(top){
if(fabs(line[sta[top]].a - line[pos].a) < eps){
top--;
}else if(top > 1 && GetPoint(line[sta[top - 1]], line[pos]).x <= GetPoint(line[sta[top - 1]], line[sta[top]]).x){
top--;
}else{
break;
}
}
sta[++top] = pos;
}
int main()
{
while(~scanf("%d", &n)){
for(int i = 0; i < n; i++){
line[i].id = i + 1;
scanf("%lf%lf", &line[i].a, &line[i].b);
}
sort(line, line + n, cmp1);
top = 0;
for(int i = 0; i < n; i++){
Insert(i);
}
sort(sta + 1, sta + top + 1, cmp2);
for(int i = 1; i <= top; i++){
printf("%d ", line[sta[i]].id);
}
printf("\n");
}
return 0;
}