博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj 3304(直线与线段相交)
阅读量:7237 次
发布时间:2019-06-29

本文共 4741 字,大约阅读时间需要 15 分钟。

 

传送门:

题意:线段在一个直线上的摄影相交 求求是否存在一条直线,使所有线段到这条直线的投影至少有一个交点 

分析:可以在共同投影处作原直线的垂线,则该垂线与所有线段都相交<==> 是否存在一条直线与所有线段都相交。 去盗了一份bin神的模板,用起来太方便了。。。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);const int N = 110;int sgn(double x){ if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1;}struct Point{ double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } //点积 double operator *(const Point &b)const { return x*b.x + y*b.y; } //绕原点旋转角度B(弧度值),后x,y的变化 void transXY(double B) { double tx = x,ty = y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); } //绕点p逆时针旋转角度B(弧度值) void rotate(Point p,double B) { Point v=(*this)-p; double tx = v.x,ty = v.y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); }};struct Line{ Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } //两直线相交求交点 //第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交 //只有第一个值为2时,交点才有意义 pair
operator &(const Line &b)const { Point res = s; if(sgn((s-e)^(b.s-b.e)) == 0) { if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);//重合 else return make_pair(1,res);//平行 } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); }};//*两点间距离double dist(Point a,Point b){ return sqrt((a-b)*(a-b));}//*判断线段相交bool inter(Line l1,Line l2){ return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 && sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;}//判断直线和线段相交bool Seg_inter_line(Line l1,Line l2) //判断直线l1和线段l2是否相交{ return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0;}//点到直线距离//返回为result,是点到直线最近的点Point PointToLine(Point P,Line L){ Point result; double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); result.x = L.s.x + (L.e.x-L.s.x)*t; result.y = L.s.y + (L.e.y-L.s.y)*t; return result;}//点到线段的距离//返回点到线段最近的点Point NearestPointToLineSeg(Point P,Line L){ Point result; double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); if(t >= 0 && t <= 1) { result.x = L.s.x + (L.e.x - L.s.x)*t; result.y = L.s.y + (L.e.y - L.s.y)*t; } else { if(dist(P,L.s) < dist(P,L.e)) result = L.s; else result = L.e; } return result;}//计算多边形面积//点的编号从0~n-1double CalcArea(Point p[],int n){ double res = 0; for(int i = 0;i < n;i++) res += (p[i]^p[(i+1)%n])/2; return fabs(res);}//*判断点在线段上bool OnSeg(Point P,Line L){ return sgn((L.s-P)^(L.e-P)) == 0 && sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 && sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;}//*判断点在凸多边形内//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)//点的编号:0~n-1//返回值://-1:点在凸多边形外//0:点在凸多边形边界上//1:点在凸多边形内int inConvexPoly(Point a,Point p[],int n){ for(int i = 0;i < n;i++) { if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0)return -1; else if(OnSeg(a,Line(p[i],p[(i+1)%n])))return 0; } return 1;}//*判断点在任意多边形内//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1//返回值//-1:点在凸多边形外//0:点在凸多边形边界上//1:点在凸多边形内int inPoly(Point p,Point poly[],int n){ int cnt; Line ray,side; cnt = 0; ray.s = p; ray.e.y = p.y; ray.e.x = -100000000000.0;//-INF,注意取值防止越界 for(int i = 0;i < n;i++) { side.s = poly[i]; side.e = poly[(i+1)%n]; if(OnSeg(p,side))return 0; //如果平行轴则不考虑 if(sgn(side.s.y - side.e.y) == 0) continue; if(OnSeg(side.s,ray)) { if(sgn(side.s.y - side.e.y) > 0)cnt++; } else if(OnSeg(side.e,ray)) { if(sgn(side.e.y - side.s.y) > 0)cnt++; } else if(inter(ray,side)) cnt++; } if(cnt % 2 == 1)return 1; else return -1;}//判断凸多边形//允许共线边//点可以是顺时针给出也可以是逆时针给出//点的编号1~n-1bool isconvex(Point poly[],int n){ bool s[3]; memset(s,false,sizeof(s)); for(int i = 0;i < n;i++) { s[sgn( (poly[(i+1)%n]-poly[i])^(poly[(i+2)%n]-poly[i]) )+1] = true; if(s[0] && s[2])return false; } return true;}Line seg[N];int n;bool judge(Point a,Point b){ if(sgn(dist(a,b))==0)return false; Line l=Line(a,b); for(int i=1;i<=n;i++) if(!Seg_inter_line(l,seg[i]))return false; return true;}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); seg[i]=Line(Point(a,b),Point(c,d)); } bool flag=false; for(int i=1;i<=n&&!flag;i++) { for(int j=1;j<=n;j++) if(judge(seg[i].s,seg[j].s)||judge(seg[i].s,seg[j].e)|| judge(seg[i].e,seg[j].s)||judge(seg[i].e,seg[j].e)) { flag=true;break; } } if(flag)puts("Yes!"); else puts("No!"); } return 0;}
View Code

 

转载于:https://www.cnblogs.com/lienus/p/4331388.html

你可能感兴趣的文章
工作周记 - 第四周 (2016/06/12 - 2016/06/18) 我没喝多,但是今天话多了 - -
查看>>
动手动脑问题
查看>>
wp8扩展器大全
查看>>
hdu Online Judge
查看>>
数组各种方法-读书笔记
查看>>
第三次实验
查看>>
saltstack安装和配置
查看>>
cocos2dx游戏资源加密之XXTEA
查看>>
文本处理的一些使用总结
查看>>
运维自动化 第一章 git
查看>>
数据分析入门-01-数据科学的世界观:科学方法论与贝叶斯过程
查看>>
iOS--------手势识别的详细使用:拖动、缩放、旋转、点击、手势依赖、自定义手势...
查看>>
nginx转发请求
查看>>
Hadoop集群安装注意事项
查看>>
20165226 实验四 Android程序设计
查看>>
Oracle查看某个用户下所有表的记录总数和所有表的字段总数、记录数
查看>>
剑指offer-面试题9.斐波拉契数列
查看>>
Windows多线程同步系列之三-----事件对象
查看>>
C/C++里的const(2)
查看>>
Java基础小记
查看>>