uva11343 - Isolated Segments(两线段相交)

题意:给你一些线段,求没有和其他线段相交的线段数量

公式:p1*p2=(x1*x2,y1*y2)(内积),p1xp2=(x1*y2,x2*y1)(外积)

判断q是否在线段p1-p2上面,根据(p1-q)x(p2-q)=0来判断q是否在直线p1-p2上。

利用内积(p1-q)*(p2-q)<0判断q是否在p1-p2之间。

p1-p2,q1-q2的交点:

(x,y)=p1+(p2-p1)*((q2-q1)x(q1-p1)/((q2-q1)x(p2-p1)));

推理:把p1-p2直线写成点p1+t(p2-p1),然后就是点和q1-q2直线了,最后计算得出上面的。

最后验证交点在两条线段上没有。

这道题主要是精度问题,看着绝对值 <1000,实则在计算的时候会出现超过int,所以需要用Long long,如果是用的double,注意精度,由于全是整数,EPS应该设置大一点,太小的话会由于double精度而wa。double下判断a==0,使用abs(a)<EPS。

#include <iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<list>
#include<cstring>
using namespace std;
#define EPS 1e-3
#define N 1005
int ans[N];
struct point
{
    double a,b;
    point(){}
    point(double a,double b):a(a),b(b){}
    point operator +(point p)
    {
        return point(p.a+a,p.b+b);
    }
    point operator -(point p)
    {
        return point(a-p.a,b-p.b);
    }
    point operator *(double p)
    {
        return point(a*p,b*p);
    }
    double dot(point p)//内积
    {
        return (p.a*a+p.b*b);
    }
    double det(point p)//外积
    {
        return (a*p.b-b*p.a);
    }
};
struct seg
{
    int index;
    point p1,p2;
};
point p1,p2;
vector<seg>v;
//判断q是否在线段p1-p2上
bool on_str(point p1,point p2,point q)
{
    return (abs((p1-q).det(p2-q))<EPS&&(p1-q).dot(p2-q)<EPS);
}
//求两直线交点
point intersection(point p1,point p2,point q1,point q2)
{
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
void solve(int a)
{
    for(int i=0;i<v.size();i++){

           point  q1=v[i].p1;
           point  q2=v[i].p2;
         if(abs((p1-p2).det(q1-q2))<EPS)//判断外积是否为0
         {
             if(on_str(p1,p2,q1)||on_str(p1,p2,q2)||on_str(q1,q2,p1)||on_str(q1,q2,p2))//判断是否有重合
              {
                  ans[a]=1;
                  ans[v[i].index]=1;
              }
         }
         else
         {
            point r=intersection(p1,p2,q1,q2);
             if(on_str(p1,p2,r)&&on_str(q1,q2,r))
             {
                 ans[a]=1;
                 ans[v[i].index]=1;
             }
         }
    }
}
int main()
{
    int t;
    scanf("%d",&t);

    while(t--)
    {
        int n;
            v.clear();
            memset(ans,0,sizeof(ans));
            scanf("%d",&n);
        for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf%lf",&p1.a,&p1.b,&p2.a,&p2.b);
                    solve(i);
                v.push_back(seg{i,p1,p2});
        }
        int t=0;
        for(int i=1;i<=n;i++)
        {
            if(ans[i]==0)
                t++;
        }
        printf("%d\n",t);
    }

    return 0;
}
时间: 2024-10-28 19:39:39

uva11343 - Isolated Segments(两线段相交)的相关文章

ACM1558两线段相交判断和并查集

Segment set Problem Description A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set. Input In the first line ther

You can Solve a Geometry Problem too (hdu1086)几何,判断两线段相交

You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6837 Accepted Submission(s): 3303 Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. A

两线段相交求交点

算法一 #include #include #include struct POINT { int x; int y; }; bool IsLineSegmentCross(POINT pFirst1, POINT pFirst2, POINT pSecond1, POINT pSecond2) { //每个线段的两点都在另一个线段的左右不同侧,则能断定线段相交 //公式对于向量(x1,y1)->(x2,y2),判断点(x3,y3)在向量的左边,右边,还是线上. //p=x1(y3-y2)+x2

poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are

[poj] 3304 Segments || 判断线段相交

原题 给出n条线段,判断是否有一条直线与所有线段都有交点 若存在这样一条直线,那么一定存在一条至少过两个线段的端点的直线满足条件. 每次枚举两条线段的两个端点,确定一条直线,判断是否与其他线段都有交点. 判断交点: 判断AB和CD是否相交,即判断AC×BD(叉积)和AD×BC(叉积)是否同号 #include<cstdio> #define eps 1e-13 #define N 110 using namespace std; int t,n; struct point { double x

BNUOJ33566 Cycling Roads(并查集+判断两线段相交)

Cycling Roads Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on Ural. Original ID: 1966 64-bit integer IO format: %lld      Java class name: (Any) Prev Submit Status Statistics Discuss Next Font Size:  +   - Type:   None Graph T

判断两线段相交

#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <stdlib.h> using namespace std; int n; struct point { double x; double y; }; struct v { point s; point e; } q[102]; int sum; double multi

判断两线段是否相交

今日集训第一日,遇到了判断线段相交问题.跟面积问题一样,这个同样可以用叉积来解决. 数学原理证明: 首先引出计算几何学中一个最基本的问题:如何判断向量在的顺时针方向还是逆时针方向? 把p0定为原点,p1的坐标是(x1,y1),p2的坐标是(x2,y2).向量的叉积(cross product)实际上就是矩阵的行列式: 代码实现: 1 int direction(Point p0, Point p1, Point p2) { 2 int px02 = p2.x - p0.x; 3 int py02

判断两线段是否相交 模板

1 struct point 2 { 3 double x, y; 4 point( double _x = 0, double _y = 0 ) 5 { 6 x = _x; 7 y = _y; 8 } 9 point operator-( point t ) 10 { 11 return point( x - t.x, y - t.y ); 12 } 13 double operator*( point t ) 14 { 15 return x * t.y - y * t.x; 16 } 17