bzoj1007 [HNOI2008]水平可见直线 - 几何 - hzwer.com
Description
Input
第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi
Output
从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格
Sample Input
3
-1 0
1 0
0 0
-1 0
1 0
0 0
Sample Output
1 2
题解
算法比较直观,先按斜率排序,再将最小的两条线入栈,然后依次处理每条线,如果其与栈顶元素的交点在上一个点的左边,则将栈顶元素出栈 ;这样为什么对呢?因为对如任意一个开口向上的半凸包,从左到右依次观察每条边和每个顶点,发现其斜率不断增大,顶点的横坐标也不断增大。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #define eps 0.0000001 7 using namespace std; 8 9 int top,n; 10 bool boo[50007]; 11 struct Node 12 { 13 double x,y; 14 int num; 15 }a[50007],stack[50007]; 16 17 double rope(Node x,Node y) 18 { 19 return (y.y-x.y)/(x.x-y.x); 20 } 21 bool cmp(Node x,Node y) 22 { 23 if (fabs(x.x-y.x)<eps) return x.y<y.y; 24 else return x.x<y.x; 25 } 26 void solve() 27 { 28 for (int i=1;i<=n;i++) 29 { 30 while(top) 31 { 32 if (fabs(stack[top].x-a[i].x)<=eps) top--;//后者b大 33 else if (top>1&&rope(a[i],stack[top-1])<=rope(stack[top],stack[top-1])) top--; 34 else break; 35 } 36 stack[++top]=a[i]; 37 } 38 for (int i=1;i<=top;i++) 39 boo[stack[i].num]=1; 40 for (int i=1;i<=n;i++) 41 if (boo[i]) printf("%d ",i); 42 } 43 int main() 44 { 45 scanf("%d",&n); 46 for (int i=1;i<=n;i++) 47 { 48 scanf("%lf%lf",&a[i].x,&a[i].y); 49 a[i].num=i; 50 } 51 sort(a+1,a+n+1,cmp); 52 solve(); 53 }