【半平面交】BZOJ1007(HNOI2008)[水平可见直线]题解
来源:互联网 发布:国内人工智能专业排名 编辑:程序博客网 时间:2024/06/05 06:30
题目概述
二维直角坐标系中,给出n条直线,从y轴正无穷大处向下看,输出可以看见的直线。
解题报告
全部搞在一起看不可能分析清楚,肯定要先两两分析:
设交点是(x,y),那么对于斜率小的直线,大于等于x的部分都被遮住了,而对于斜率大的直线,小于等于x的部分都被遮住了。
假设一条直线小于等于
于是问题转化为求
……
反正我是没想到!所以上述想法很难实现!看了讨论发现了个关键词:半平面交。虽然我不太了解半平面交,但是我发现不一定要用代数做法,可以用几何做法解决这道题。
先按照k排序(k相同的只留下b最大的),然后储存一个栈,表示目前能看见的直线。每次加入一条直线时,求出这条直线与栈顶的交点A,然后求出栈顶和栈顶下面元素的交点B,如果A的横坐标小于等于B的横坐标,那么当前栈顶就被遮掉了(也就是简化版半平面交):
最后栈内存在的元素就可见直线。
示例程序
#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int maxn=50000;int n,top,stk[maxn+5];struct Point{ double x,y; Point (double X=0,double Y=0) {x=X;y=Y;}};int fcmp(double x,double y) {if (fabs(x-y)<=1e-10) return 0;if (x<y) return -1; else return 1;}struct Line{ double k,b;int id; bool operator < (const Line &a) const {return fcmp(k,a.k)<0||!fcmp(k,a.k)&&fcmp(b,a.b)>0;}};Line l[maxn+5];Point getPoint(const Line &a,const Line &b) {double x=(b.b-a.b)/(a.k-b.k);return Point(x,a.k*x+a.b);}int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lf%lf",&l[i].k,&l[i].b),l[i].id=i; sort(l+1,l+1+n); int num=1;for (int i=2;i<=n;i++) if (l[i-1].k<l[i].k) l[++num]=l[i];n=num; for (int i=1;i<=n;i++) { while (top>1&&fcmp(getPoint(l[stk[top]],l[i]).x,getPoint(l[stk[top-1]],l[stk[top]]).x)<=0) top--; //删除堆顶 stk[++top]=i; } for (int i=1;i<=top;i++) stk[i]=l[stk[i]].id; sort(stk+1,stk+1+top); for (int i=1;i<=top;i++) printf("%d ",stk[i]); return 0;}
0 0
- 【半平面交】BZOJ1007(HNOI2008)[水平可见直线]题解
- 【BZOJ1007】[HNOI2008]水平可见直线【半平面交】
- [半平面交] BZOJ1007: [HNOI2008]水平可见直线
- BZOJ1007(HNOI2008)[水平可见直线]--半平面交+单调栈
- [HNOI2008]水平可见直线 半平面交
- BZOJ 1007 HNOI2008 水平可见直线 半平面交
- 【BZOJ 1007】[HNOI2008]水平可见直线 半平面交
- bzoj1007 [HNOI2008]水平可见直线
- BZOJ1007: [HNOI2008]水平可见直线
- BZOJ1007【HNOI2008】水平可见直线
- 【BZOJ1007】【HNOI2008】水平可见直线
- bzoj1007【hnoi2008】水平可见直线
- 【HNOI2008】【BZOJ1007】水平可见直线
- BZOJ1007 HNOI2008 水平可见直线
- bzoj1007 [HNOI2008]水平可见直线
- bzoj1007[HNOI2008]水平可见直线
- bzoj1007: [HNOI2008]水平可见直线
- BZOJ1007: [HNOI2008]水平可见直线
- Java 24 点 杭电1427
- android学习(二十) 执行网络操作(二) 管理网络使用
- 常用正则表达式
- 《JAVA设计模式》之单例模式
- 最短距离
- 【半平面交】BZOJ1007(HNOI2008)[水平可见直线]题解
- AspectJ 使用技巧
- 论述各种不同调度算法的优劣
- C++沉思录-第7章 句柄二 引用计数的分离
- docker mysql镜像忽略表名大小写
- 单例模式
- 使用Java实现面向对象编程-->异常
- CodeForces 448 C.Painting Fence(区间DP)
- 【JavaScript】1.概述