您的位置:首页 > 其它

POJ 3304 Segments

2016-03-08 14:33 316 查看
题目链接: http://poj.org/problem?id=3304

------------------------------------------------------------------------------------------------------

由于几乎没写过计算几何 只要$WA$了第一反应是调$eps$ 然而这题坑点并不是调$eps$

对于一条直线是否穿过一条线段 如果线段比较短的话 只要看看线段两端点是否都贴在直线旁就好

然而如果直线的方向向量由两个非常接近的点确定 那么与其他的向量做叉积的时候几乎都是$0$

所以我们枚举确定直线方向的两端点的时候要把这一种情况跳过

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int N = 110;
struct node
{
double x, y;
}a[N << 1];
int t, n, n2;
double cross(node &aa, node &bb, node &cc)
{
return (bb.x - aa.x) * (cc.y - aa.y) - (cc.x - aa.x) * (bb.y - aa.y);
}
bool check(node &aa, node &bb, node &cc, node &dd)
{
double t1, t2;
t1 = cross(aa, bb, cc);
t2 = cross(aa, bb, dd);
return (t1 <= eps && t2 >= -eps) || (t1 >= -eps && t2 <= eps);
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lf%lf%lf%lf", &a[i * 2 - 1].x, &a[i * 2 -1].y,
&a[i * 2].x, &a[i * 2].y);
n2 = n << 1;
bool gain = 0;
for(int i = 1; i < n2 && !gain; ++i)
for(int j = i + 1; j <= n2 && !gain; ++j)
{
if(abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y) < eps * 2)
continue;
for(int k = 1; k < n2; k += 2)
if(!check(a[i], a[j], a[k], a[k + 1]))
break;
else if(k == n2 - 1)
{
gain = 1 ;
break;
}
}
if(gain)
puts("Yes!");
else
puts("No!");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: