题目大意:给定一些线段,问是否有直线L存在,使得所有线段到L的投影有至少一个公共点。
分析:实际上就是问,是否存在一条直线K, 和所有这些线段都相交。L是K的垂线即可。若存在一条直线与所有线段相交,该直线必定经过这些线段的某两个端点(否则可以平移或转动使之靠上端点)。枚举任意两个端点构造直线并看它是否与每条线段相交即可。
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define eps 1e-8
struct P {
double x, y;
P() {}
P(double x, double y):x(x), y(y) {}
}p[300];
struct Seg {
P p1, p2;
}ss[110];
int n;
P operator -(P p, P q) {
return P(p.x-q.x, p.y-q.y);
}
double dist(P v1, P v2){
return sqrt((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y));
}
double Cross(const P & v1, const P & v2) {
return v1.x * v2.y - v1.y * v2.x;
}
bool ok(P p1, P p2) {
if(dist(p1, p2) < eps) return false;
else {
for(int i = 0; i < n; i++) {
if(Cross(p2 - p1, ss[i].p1 - p1)*
Cross(p2 - p1, ss[i].p2 - p1) > eps)
return false;
}
}
return true;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%lf%lf%lf%lf", &ss[i].p1.x, &ss[i].p1.y, &ss[i].p2.x, &ss[i].p2.y);
int flag = 0;
if(n == 1) {
flag = 1;
}
else {
for(int i = 0; i < n-1 && !flag; i++)
for(int j = i+1; j < n && !flag; j++) {
if(ok(ss[i].p1, ss[j].p1) ||
ok(ss[i].p1, ss[j].p2) ||
ok(ss[i].p2, ss[j].p1) ||
ok(ss[i].p2, ss[j].p2))
flag = 1;
}
}
if(flag) printf("Yes!\n");
else printf("No!\n");
}
return 0;
}