水平可见直线
来源:互联网 发布:2017淘宝如何提高销量 编辑:程序博客网 时间:2024/05/16 09:42
【题目描述】
在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条直线两两不重合.求出所有可见的直线。
【输入格式】
第一行为N(0 < N < 50000)
接下来的N行输入Ai,Bi
【输出格式】
从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格
【样例输入】
3
-1 0
1 0
0 0
【样例输出】
1 2
【分析】
如果只有1条直线就太简单了,肯定可以看见。
如果有2条直线,也不难解决,如果两直线平行就遮住了一条,反之都能看见。
接下来的分析不考虑平行。
如果有3条直线,会组成一个三角形,不难发现三角形底边所在直线被遮住了。于是可以得出结论:若斜率最大的直线与斜率次大(或次次大)的直线的交点在斜率次大和斜率次次大的直线的交点的左边,则斜率次大的直线被覆盖。
于是可以得出算法:先把所有直线按斜率排序,然后枚举斜率次次大的直线,分别求出与斜率最大和次大的直线的交点,看交点的位置。
可以用栈来维护,有覆盖的就直接弹栈。最后栈里存放的直线就是没有被覆盖的。
至于求交点,可以列方程组:
A1x+B1=y
A2x+B2=y
然后解一下就可以。
#include<cstdio>#include<cmath>#include<algorithm>using namespace std;struct Line { int k,b,i;//k表示斜率,b表示截距,i表示序号 bool operator < (const Line& rhs) const//重载运算符“<” { if (k==rhs.k) return b>rhs.b; return k<rhs.k; }} line[50001];int stack[50001]={0},ans[50001];double find_intersection_point(int i,int j) { int k1=line[i].k, b1=line[i].b, k2=line[j].k, b2=line[j].b; return (double)(b2-b1)/(k1-k2);//求交点,方程不解释}int main(){ int n,top=1; scanf("%d",&n); if (n==1) { printf("1 \n");return 0; }//特判 for (int i=0;i<n;i++) { int k,b; scanf("%d%d",&k,&b); line[i]=(Line){k,b,i+1}; } sort(line,line+n);//排序 //其实这里少了一步stack[0]=0,即斜率最大的直线先进栈,但是不影响结果 if (line[1].k!=line[0].k) stack[top++]=1;//若两直线不平行则斜率次大的进栈 for (int i=2;i<n;i++) { if (line[i].k==line[i-1].k) continue;//平行肯定覆盖了 while (top>1 && find_intersection_point(i,stack[top-1])-find_intersection_point(stack[top-2],stack[top-1])<=1e-6) top--;//判断交点 stack[top++]=i;//入栈 } for(int i=0;i<top;i++) ans[i]=line[stack[i]].i;//找到栈中的直线编号 sort(ans,ans+top);//栈里的直线不一定是按编号递增排列的 for(int i=0;i<top;i++) printf("%d ",ans[i]); return 0;}
3 0
- [HNOI2008]水平可见直线
- BZOJ_1007 水平可见直线
- 水平可见直线
- [HNOI2008] 水平可见直线
- [HNOI2008]水平可见直线
- BZOJ [HNOI2008]水平可见直线
- HNOI 2008 水平可见直线
- bzoj1007 [HNOI2008]水平可见直线
- BZOJ1007: [HNOI2008]水平可见直线
- BZOJ1007【HNOI2008】水平可见直线
- HYSBZ 1007 水平可见直线
- 【BZOJ1007】【HNOI2008】水平可见直线
- 【BZOJ】1007 水平可见直线
- bzoj1007【hnoi2008】水平可见直线
- 【HNOI2008】【BZOJ1007】水平可见直线
- BZOJ1007 HNOI2008 水平可见直线
- bzoj1007 [HNOI2008]水平可见直线
- 【BZOJ】1007 水平可见直线
- LCA 类问题
- 正交表测试用例设计
- Lab01 Editing text files on the command line
- 分布式系统的事务处理(转)
- The 7 stages of refactoring(转)
- 水平可见直线
- 学习简单自定义TitleBar
- 【Z10】引水入城
- 从10万条(int)数组中找到重复的数
- 弹性盒模型的实际应用
- 地图切片详解
- C#语言之“实例化的正确顺序”
- php pear基本使用方法
- Windows7如何进入应用程序的安装目录