加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

POJ PKU 3304 计算几何 直线与线段相交

(2010-07-19 15:29:36)
标签:

poj

pku

3304

it

分类: 计算几何

题目描述:问你是否存在一条直线,使所有给你的线段到这条直线的投影有一个公共的交点。

解题报告:

文字部分转自:http://hi.baidu.com/ackyclouday/blog/item/205d1915c23677084b90a706.html

首先题中的要求等价于:存在一条直线l和所有的线段都相交。
证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线,所有线段投影的一个公共点即为垂足。(l和每条线段的交点沿l投影到m上的垂足处)
反过来,若存在m,所有线段在m上的投影有公共点,则过这点垂直于m作直线l,l一定和所有线段相交。

然后证存在l和所有线段相交等价于存在l过某两条线段的各一个端点且和所有线段相交。
充分性显然。必要性:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止(“移不动了”)。然后绕这个交点旋转。也是转到“转不动了”(和另一线段交于其一个端点)为止。这样就找到了一个新的l。

于是本题可归结为枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。

代码如下:
#include<iostream>
#include<cmath>
using namespace std;
struct pint
{
    double x, y;
}zzy[200];
int eps(double xx)
{
    if (fabs(xx) <= 0.00000001) return 0;
    else if (xx > 0) return 1;
    else return -1;
}
double direction(pint p1, pint p2, pint p3)
{
    return (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
}
bool insect(pint p1, pint p2, pint p3, pint p4) // 判断直线与线段是否相交,p1, p2是直线
{
    double d3 = direction(p1, p2, p3);
    double d4 = direction(p1, p2, p4);
    if (eps(d3) * eps(d4) < 0 || eps(d3) == 0 || eps(d4) == 0) return true;
    return false;
}
bool equals(pint p1, pint p2)
{
    return (sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y * p2.y)) <= 0.00000001)
}
int t, n;
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);int m = n * 2;
        for(int i = 0; i < m; i++)
            scanf("%lf%lf", &zzy[i].x, &zzy[i].y);
        bool flag = false;
        for(int i = 0; i < m && !flag; i++)
            for(int j = i + 1; j < m && !flag; j++)
                if (!equals(zzy[i], zzy[j]))
                {
                    bool flag2 = true;
                    for(int k = 0; k < n; k++)
                        if (!insect(zzy[i], zzy[j], zzy[2 * k], zzy[2 * k + 1]))
                        {
                            flag2 = false;
                            break;
                        }
                    flag = flag2;
                }
        if (flag) printf("Yes!\n");
        else printf("No!\n");
    }
    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有