HDOJ HDU 1086 You can Solve a Geometry Problem too

HDOJ 1086 You can Solve a Geometry Problem too

题目

点此查看 HDOJ 1086 You can Solve a Geometry Problem too

分类

几何 判断线段交叉

题意

给出 N 个点
求叫点数

题解

逐个扫描 线段是否相交
主要是判断相交的算法
首先看

快速排斥实验
快速排斥实验 图例 
快速排斥实验是一种 快速判断线段是否相交的实验
思想 是 判断以线段做对角线的矩形是否相交 来判断线段是否相交
如上图 可以说明 快速排斥实验不相交的线段一定不相交 但是 相交的的不一定线段相交如中间图
P1 = (x1, y1), P2 = (x2, y2), Q1 = (x3, y3), Q2 = (x4, y4)
算法描述 如 最右方图 可见 矩形不想交 意味着 min(x1,x2) >= max(x3,x4)(P1P2 在 Q1Q2上面) 或者 max(x1,x2) <= min(x3,x4)(P1P2 在 Q1Q2下面) 或者 min(y1,y2) >= max(y3,y4)(P1P2 在 Q1Q2左面)或者 max(y1,y2) <= min(y3,y4)(P1P2 在 Q1Q2下面)
意义 快速判断 只能确定是否不相交

由于 快速排斥实验 不能确定是否相交 所以 引出一个能确定的算法

跨立实验
跨立实验 图示
判断直线是否 可以被另一个相交
有 下式  (P1 - Q1)*(Q2 - Q1) * (Q2 - Q1)* (P2 - Q1) > 0 ,当 (P1 - Q1) * (Q2 - Q1) = 0 表示共线 所以通过跨立实验 的 线段 相交条件为 (P1 - Q1)*(Q2 - Q1) * (Q2 - Q1) * (P2 - Q1) >= 0

 技巧

由于 先进行 快速排斥实验 后 排斥实验
也已用 && 连接

&& 短路
例如 A && B
若 A 为假 则 B 不被执行 

代码

#include <iostream>
#define N 101

using namespace std;

struct Point
{
    double x;
    double y;
    friend bool operator==(const Point & p,const Point & q)
    {
        return (p.x == q.x && p.y == q.y);
    }
    friend bool operator<(const Point & p,const Point & q)
    {
        return p.x < q.x;
    }
};

struct Line
{
    Point p;
    Point q;
};

Line ln[N];

bool IsCross(Line u,Line v);

int main() 
{
    int mn,ans;
    Point cp;
    while(cin >> mn && mn)
    {
        ans = 0;
        for(int i = 1;i <= mn;i++)
        {
            cin >> ln[i].p.x >> ln[i].p.y >> ln[i].q.x >> ln[i].q.y;
        }
        for(int i = 1;i < mn;i++)
            for(int j = i+1;j <= mn;j++)
                if(IsCross(ln[i],ln[j]))
                    ans++;
        cout << ans << endl;
    }
    return 0;
}

float Mul(Point a,Point b,Point c)
{
    return (a.x - c.x)*(b.y - c.y)-(b.x - c.x)*(a.y - c.y);
}

bool IsCross(Line u,Line v)
{
    return (max(u.p.x,u.q.x) >= min(v.p.x,v.q.x)) &&
            (max(v.p.x,v.q.x) >= min(u.p.x,u.q.x)) &&
            (max(u.p.y,u.q.y) >= min(v.p.y,v.q.y)) &&
            (max(v.p.y,v.q.y) >= min(u.p.y,u.q.y)) &&
            (Mul(v.p,u.q,u.p) * Mul(u.q,v.q,u.p) >= 0) &&
            (Mul(u.p,v.q,v.p) * Mul(v.q,u.q,v.p) >= 0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值