CodeVS1302 小矮人 解题报告【计算几何】【凸包】【凸包与直线判交】
来源:互联网 发布:考古知 编辑:程序博客网 时间:2024/05/18 01:00
题目描述 Description
矮人们平时有走亲访友的习惯。一天,矮人国要修一条高速公路,矮人们希望他们走亲访友的时候,能够不必穿越高速公路,这样会更安全一些。现在有M个高速公路的修建方案,请你判断这M条高速功能是否能满足矮人们的期望。也就是说给出平面上的N个点(矮人们的住所位置),对于M条直线(高速公路),依次判断这N个点是否在每条直线的同一侧。是输出GOOD,不是输出BAD。
N,M≤100000
输入描述 Input Description
第一行一个整数N,表示矮人的住所数。
接下来N行每行一个坐标代表矮人的住所坐标。
接下来的若干行(到文件结尾)每行4个整数,代表高速公路上的2个点。
所有坐标均在-109到109之间
输出描述 Output Description
对合法的方案输出GOOD,否则输出BAD。
样例输入 Sample Input
4
0.0 0
6.00 -0.001
3.125 4.747
4.747 0.47
5 3 7 0
4 -4.7 7 4.7
4 47 4 94
样例输出 Sample Output
GOOD
BAD
BAD
解题报告
这道题的题意是给我们n个点,依次给m每个边,问这n个点是否在这条边的同一侧。
我们很容易想到,要把这n个点看做一个整体,最好的办法莫过于搞一个凸包把这n个囊括其中。然后判断这条直线是否穿过这个凸包。
怎样判定直线是否穿过凸包呢?如果一条直线穿过这个凸包,这条直线一定在凸包两个最远点的中间(向量叉乘小于零)。怎样找最远点呢?
二分查找第一个大于直线斜率的边,它的起点一定是一个最远点,因为他后面的边斜率比它大,也就相当于走的离凸包中心越来越近。然后把斜率取相反数,再找第一个斜率大于它的边,起点是另一个最远点。
代码如下:
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define NAME ""#define Point Vectorusing namespace std;const double eps=1e-8;const double PI=acos(double(-1));const int N=100000;struct Vector{ double x,y; double len(){return sqrt(x*x+y*y);} double ang(){double ret=atan2(y,x);return ret<-PI/2?ret+2*PI:ret;} Vector(int a=.0,int b=.0):x(a),y(b){} Vector operator+(const Vector &s)const{return Vector(x+s.x,y+s.y);} Vector operator-(const Vector &s)const{return Vector(x-s.x,y-s.y);} Vector operator*(int s)const{return Vector(x*s,y*s);} Vector operator/(int s)const{return Vector(x/s,y/s);} bool operator<(const Point &s)const { if(s.x==x)return y<s.y; else return x<s.x; }}p[N+5],ch[N+5];int n;double ang[N+5];double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//向量叉积 int sign(double a){return a>eps?1:(a<-eps?-1:0);}bool cmp(double a,double b){return sign(b-a)==1;}bool onleft(Point a,Point b,Point p){ return sign(cross(b-a,p-a))>0;}int ComvexHull(){ sort(p+1,p+n+1); int m=0; for(int i=1;i<=n;++i) { while(m>1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; ch[m++]=p[i]; } int k=m; for(int i=n-1;i>=1;--i) { while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; ch[m++]=p[i]; } if(n>1) m--; return m;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { double x,y; scanf("%lf%lf",&x,&y); p[i]=Point(x,y); } int m=ComvexHull(); for(int i=0;i<m;i++)ang[i]=(ch[i+1]-ch[i]).ang(); Point A,B; while(scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y)==4) { if(n<=1)printf("GOOD\n"); else { Point u=ch[upper_bound(ang,ang+m,(B-A).ang(),cmp)-ang]; Point v=ch[upper_bound(ang,ang+m,(A-B).ang(),cmp)-ang]; if(sign(cross(B-A,u-A)*cross(B-A,v-A))<eps)printf("BAD\n"); else printf("GOOD\n"); } } return 0;}
- CodeVS1302 小矮人 解题报告【计算几何】【凸包】【凸包与直线判交】
- codevs 1302 小矮人 凸包 解题报告
- CodeVS1298 凸包周长 解题报告【计算几何】【凸包】
- 计算几何-凸包
- 【计算几何】多边形与凸包
- [计算几何]凸包算法
- 计算几何之凸包
- 计算几何-凸包问题
- 计算几何 --- 凸包 模板
- 计算几何凸包详解
- 大白 计算几何专题 凸包、半平面交、平面区域 部分例题练习题总结
- 计算几何中的凸包计算
- 计算几何:线段判交模板--ACM
- 计算几何__凸包算法
- [计算几何]凸包算法 收藏
- [计算几何-凸包]pku1113-Wall
- 计算几何 Graham_scan凸包 pku 1113
- POJ 1113 WALL(凸包-计算几何)
- FPGA跨时钟域设计的一点总结
- 模块化开发的时候,sqlsession如何配置多个typeAliasesPackage,mapperLocations
- Jquery UI 案例
- JAVA web配置 Maven环境变量配置
- 【算法学习】全排列算法(java实现)
- CodeVS1302 小矮人 解题报告【计算几何】【凸包】【凸包与直线判交】
- 浏览器缓存
- UVA
- 求1+2+3+...+n(剑指Offer)
- Telnet4种操作方式
- Primer (十一)
- Math.js库的使用
- Windows合并音频
- 从源码理解Spring原理,并用代码实现简易Spring框架