首页 > 代码库 > POJ 3304
POJ 3304
题目可以转化成是否存在这样的一条直线,穿过所有的线段。这是很容易就能想到的。
然后,假如只有一个端点重合,那么我们可以知道,必定会有属于两条线段的某两个端点连出的直线可以穿过所有线段。这是枚举的思想。
那么,我们该怎么判定直线与线段有交点呢?不妨通过跨立的定义来做,这是经人点醒了才想到的。
在求线段是否有交点的时候用到过跨立,但我认为,跨立的定义应该是延长的线后是否存在交点(当前包括开始就存在交点的。)
假设枚举两点得到的线段是A1A2,判断是否有交点的线段是B1B2,则要求A1A2跨立B1B2。
设P1=向量(O->B1),P2=(O->B2),Q1=(O->A1),Q2=(O->A2);
则((P1-Q1)x(Q2-Q1))*((Q1-P2)x(Q2-Q1))>=0
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #include <math.h> 6 #define eps 0.00000001 7 using namespace std; 8 9 typedef struct po{10 double x,y;11 }Point;12 13 typedef struct pl{14 Point start,end;15 }Pleg;16 int how_point,how_pleg;17 Point pot[300];18 Pleg peg[300];19 Pleg Line;20 21 bool dbcmp(double x,double y){22 if(fabs(x-y)<eps) return false;23 return true;24 }25 26 double multi(Point a,Point b, Point c,Point d){27 return (a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x);28 }29 30 bool slove(int k){31 if(multi(peg[k].start,Line.start,Line.end,Line.start)*multi(Line.start,peg[k].end,Line.end,Line.start)>=0)32 return true;33 return false;34 }35 36 int main(){37 int T,n;38 scanf("%d",&T);39 while(T--){40 how_point=how_pleg=0;41 scanf("%d",&n);42 for(int i=1;i<=n;i++){43 scanf("%lf%lf",&pot[how_point].x,&pot[how_point].y);44 peg[how_pleg].start=pot[how_point];45 how_point++;46 scanf("%lf%lf",&pot[how_point].x,&pot[how_point].y);47 peg[how_pleg].end=pot[how_point];48 how_point++;49 how_pleg++;50 }51 bool flag=false;52 for(int i=0;i<how_point;i++){53 for(int j=i+1;j<how_point;j++){54 if(!dbcmp(pot[i].x,pot[j].x)&&!dbcmp(pot[i].y,pot[j].y))55 continue;56 Line.start=pot[i]; Line.end=pot[j];57 int k;58 for(k=0;k<how_pleg;k++){59 if(slove(k)){60 continue;61 }62 break;63 }64 if(k==how_pleg){65 flag=true;66 break;67 }68 }69 if(flag) break;70 }71 if(flag) printf("Yes!\n");72 else printf("No!\n");73 }74 return 0;75 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。