http://poj.org/problem?id=3304
题意是问是否存在一条直线,使得所有线段在这直线上的投影都有至少一个公共点。
我们假设存在这样的一条直线,在直线公共部分作一垂线,那么垂线必定过所有的线段,所以,我们可以反过来考虑,那么题目就变成求是否存在一直线过所有的线段,然后我们就可以枚举每一个点,具体方法:先取两不同点,然后在余下的点进行枚举,用叉乘来判断是否相交,叉乘判断方法如下:
设线段端点为从 A(x1, y1)到 B(x2, y2), 线外一点 P(x0,y0),
判断该点位于有向线 A→B 的那一侧。
a = ( x2-x1, y2-y1)
b = (x0-x1, y0-y1)
a x b = | a | | b | sinφ (φ为两向量的夹角)
| a | | b | ≠ 0 时, a x b 决定点 P的位置
所以 a x b 的 z 方向大小决定 P位置
(x2-x1)(y0-y1) – (y2-y1)(x0-x1) > 0 左侧
(x2-x1)(y0-y1) – (y2-y1)(x0-x1) < 0 右侧
(x2-x1)(y0-y1) – (y2-y1)(x0-x1) = 0 线段上
AC代码:
#include<iostream>
#include<vector>
#include<map>
#include<stack>
#include<algorithm>
#include<queue>
#include<list>
#include<set>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<stdio.h>
#include<ctype.h>
#include<iomanip>
using namespace std;
#define LL long long
#define pi acos(-1)
#define N 6000
#define INF 9999999999
struct node
{
double x,y;
}p[210];
double cal(node a,node b,node c)
{
return (a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y);
}
int main()
{
//freopen("a.txt","r",stdin);
int t;
int n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int i,j,k;
for(i=1;i<=2*n;i+=2)
scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i+1].x,&p[i+1].y);
int flag=0;
for(i=1;i<=2*n;i++)
for(j=1;j<=2*n;j++)
{
node a=p[i],b=p[j];
if(a.x==b.x && a.y==b.y)
continue;
for(k=1;k<=2*n;k+=2)
{
if(p[k].x==a.x&&p[k].y==a.y && p[k+1].x==b.x&&p[k+1].y==b.y)
continue;
if(cal(p[k],a,b)*cal(p[k+1],a,b)>1e-8)
{
break;
}
}
if(k>2*n)
{flag=1;break;}
}
if(flag)
printf("Yes!\n");
else
printf("No!\n");
}
return 0;
}