题目:http://acm.hdu.edu.cn/showproblem.php?pid=3492
http://poj.org/problem?id=3304
注:这两题基本上是一样的,题意都是,所有线段在某条直线的投影有公共点,问:这条直线是否存在。
所有线段在某条直线的投影有公共点 等价于 所有线段与该条直线的垂线相交。
另外该直线存在的话一定会存在通过两条线段端点的直线。
枚举两两线段的组成的四条直线,看看该条直线是否与所有线段都相交。
注2:在判断某条直线是否与所有线段相交时,使用叉积,但poj的那一题要注意精度,
double cross( point a, point b,point c) //ac { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); }
源代码:double cross( point a, point b,point c) //wa { return (b.x-a.x)*c.y-b.x*a.y-(b.y*c.x-b.y*a.x-a.y*c.x); //把a.x*a.y约去,合并 }
#include <stdio.h> #include <math.h> #define exp 1e-10 #define N 405 typedef struct { double x,y; }point; point p[N],p1[N]; int n,cas,flag; double cross(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } double dist(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int judge(point a,point b) { if(dist(a,b)<exp) return 0; for(int i=0;i<n;i++) if(cross(a,b,p[i])*cross(a,b,p1[i])>exp) return 0; return 1; } int solve() { int flag=0,cnt=0; for(int i=0;i<n;i++) if(p[i].x==p[0].x&&p[i].y==p[0].y&&p1[i].x==p1[0].x&&p1[i].y==p1[0].y) cnt++; if(cnt==n) return 1; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(judge(p[i],p[j])||judge(p[i],p1[j])||judge(p1[i],p[j])||judge(p1[i],p1[j])) { flag=1; break; } } if(flag) break; } return flag; } int main() { scanf("%d",&cas); while(cas--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lf %lf %lf %lf",&p[i].x,&p[i].y,&p1[i].x,&p1[i].y); flag=solve(); if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }