bzoj 1007: [HNOI2008]水平可见直线
Posted CXCXCXC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1007: [HNOI2008]水平可见直线相关的知识,希望对你有一定的参考价值。
Submit: 5308 Solved: 1990
[Submit][Status][Discuss]
Description
在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.
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
题解:
先按斜率排序,再将最小的一条线入栈,然后依次处理2~N条线,如果第i条直线与stack[top]直线的交点在stack[top]和stack[top-1]直线度左边,则top--,具体可以画几条线模拟一下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<vector> 9 using namespace std; 10 const double eps=1e-6; 11 const int maxn=50010; 12 struct bian{ 13 double k,b; 14 int id; 15 }str[maxn]; 16 int cmp(const bian &x1,const bian &x2){ 17 return x1.k<x2.k||(fabs(x1.k-x2.k)<eps&&x1.b<x2.b); 18 } 19 inline double crossx(int x1,int x2){ 20 return (str[x2].b-str[x1].b)/(str[x1].k-str[x2].k); 21 } 22 int stack[maxn],top; 23 int N,ans[maxn]; 24 int main(){ 25 scanf("%d",&N); 26 for(int i=1;i<=N;i++){ 27 scanf("%lf%lf",&str[i].k,&str[i].b); 28 str[i].id=i; 29 } 30 sort(str+1,str+N+1,cmp); 31 32 stack[++top]=1; 33 for(int i=2;i<=N;i++){ 34 while(top!=0){ 35 if(fabs(str[i].k-str[stack[top]].k)<eps) top--; 36 if((crossx(stack[top-1],i)<=crossx(stack[top-1],stack[top]))&&top>=2) 37 top--; 38 else break; 39 } 40 stack[++top]=i; 41 } 42 for(int i=1;i<=top;i++) ans[str[stack[i]].id]=1; 43 for(int i=1;i<=N;i++){ 44 if(ans[i]==1) printf("%d ",i); 45 } 46 return 0; 47 }
以上是关于bzoj 1007: [HNOI2008]水平可见直线的主要内容,如果未能解决你的问题,请参考以下文章