题目描述:http://poj.org/problem?id=3304
解题思路:
所有线段在直线上的投影有公共区域,那么这条直线存在一条法线通过所有的线段。如果存在这么一条直线,那么这条直线必定至少通过所有端点中的两个。因为我们总可以移动这条直线使之被线段的端点卡住。所以只需要枚举端点和判断直线与线段相交就行了。
#include "stdio.h"
#include "math.h"
#define MAXN 107
#define eps 1e-8
struct point {
double x, y;
} p[MAXN*4];
struct line {
struct point a, b;
} l[MAXN];
int n ,np;
bool eql(int i, int j) {
if (fabs(p[i].x-p[j].x)<eps && fabs(p[i].y-p[j].y)<eps)
return true;
else
return false;
}
double xProduct(struct point a, struct point b, struct point c) {
double x1 = b.x-a.x, y1 = b.y-a.y;
double x2 = c.x-a.x, y2 = c.y-a.y;
return (x1*y2 - x2*y1);
}
bool intersect(int x, int y) {
int i;
for (i=1; i<=n; i++) {
if (xProduct(p[x], p[y], l[i].a) * xProduct(p[x], p[y], l[i].b) > eps) {
return false;
}
}
return true;
}
void init() {
double ax, ay, bx, by;
int i;
scanf("%d", &n);
np = 0;
for (i=1; i<=n; i++) {
scanf("%lf %lf %lf %lf", &ax, &ay, &bx, &by);
l[i].a.x = ax; l[i].a.y = ay;
l[i].b.x = bx; l[i].b.y = by;
++np;
p[np].x = ax; p[np].y = ay;
++np;
p[np].x = bx; p[np].y = by;
}
}
int main() {
int i, t, j;
bool exist;
scanf("%d", &t);
while (t--) {
exist = false;
init();
for (i=1; i<=np; i++)
for (j=i+1;j<=np; j++) {
if (!eql(i, j) && intersect(i, j)) {
exist = true;
break;
}
}
if (exist) {
printf("Yes!\n");
} else {
printf("No!\n");
}
}
return 0;
}