POJ_3304

    这个题一开始不知道project什么意思,理解成了判断是否存在一条直线能够和所有线段相交,后来百度project的意思之后发现原来是看是否存在一条直线使得当所有线段先直线投影之后,这些投影至少有一个公共点。理解对意思后反倒没什么思路了,后来想了一下突然发现原来就是要转化成我一开始那个“错误”的理解去做……

    我们不妨设存在这样的一条直线,那么当直线在合理的范围内旋转过程中一定会出现过某两个线段的端点的情况,所以我们只要枚举任意两个端点作为这样的直线即可。

需要注意的是,当枚举的两个端点很近的时候,fabs(x1-x2)<1e-8&&fabs(y1-y2)<1e-8,那么这两个点是可以认为重合的,由于如果把这两点的连线作为向量,向量的模会很小,就可能导致无论怎么做叉积结果都为0从而认为各个点都是和这两个点共线的。因此,在枚举两个端点的时候要避免这种情况,同时,避免枚举这种情况之后也一定不会丢解。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAXD 210
#define zero 1e-8
int N;
double x[MAXD], y[MAXD];
int dcmp(double i)
{
if(fabs(i) < zero)
return 0;
if(i < 0)
return -1;
return 1;
}
void init()
{
int i;
scanf("%d", &N);
for(i = 0; i < N; i ++)
scanf("%lf%lf%lf%lf", &x[2 * i], &y[2 * i], &x[2 * i + 1], &y[2 * i + 1]);
}
double det(double x1, double y1, double x2, double y2)
{
return x1 * y2 - x2 * y1;
}
int check(int a, int b)
{
int i, t1, t2;
for(i = 0; i < N; i ++)
{
t1 = dcmp(det(x[a] - x[b], y[a] - y[b], x[2 * i + 1] - x[b], y[2 * i + 1] - y[b]));
t2 = dcmp(det(x[a] - x[b], y[a] - y[b], x[2 * i] - x[b], y[2 * i] - y[b]));
if(t1 * t2 == 1)
return 0;
}
return 1;
}
void solve()
{
int i, j, k;
for(i = 2 * N - 1; i >= 0 ; i --)
for(j = i - 1; j >= 0; j --)
if(dcmp(x[i] - x[j]) || dcmp(y[i] - y[j]))
{
if(check(i, j))
{
printf("Yes!\n");
return ;
}
}
printf("No!\n");
}
int main()
{
int t = 0;
scanf("%d", &t);
while(t --)
{
init();
solve();
}
return 0;
}


posted on 2012-02-07 08:50  Staginner  阅读(755)  评论(0编辑  收藏  举报