Ocean
  • 1.6k

计算几何 - XOJ 1171 线段求交

问题

Description
线段求交即给定一组线段求出这些线段的相交情况,它是计算几何的基础问题之一,有着广泛的应用.
Input
 第一行为一个正整数n表示线段的个数(n<=10000)
 第二行到第n+1行每行包括4个正整数x1,y1,x2,y2, (0 <= x1,y1,x2,y2 <= 1000) x1,x2表示线段两端点的横坐标,y1,y2表示线段两端点的纵坐标
 注意线段的两端点可能重合 即(x1,y1)有可能等于(x2,y2)
Output
 一个正整数k, 表示相交的线段对数,这里只要两线段有接触即为相交.数据保证k<=100000.
Sample Input
8
10 13 20 56
37 60 40 7
87 57 113 5
96 16 125 51
171 4 231 4
200 4 211 43
268 36 354 36
283 4 314 36
Sample Output
3

TLE代码

#include<stdio.h>
#define N 10002
 
/**
算法适用于整形点,不适用于浮点型 
**/
 
typedef struct Point
{
    int x;
    int y;
}Point;
 
double min(int x, int y)
{
    return x<y?x:y;
}
 
double max(int x, int y)
{
    return x>y?x:y;
}
 
//排斥实验
bool IsRectCross(const Point &p1,const Point &p2,const Point &q1,const Point &q2)
{
    bool ret = min(p1.x,p2.x) <= max(q1.x,q2.x)  &&
                min(q1.x,q2.x) <= max(p1.x,p2.x) &&
                min(p1.y,p2.y) <= max(q1.y,q2.y) &&
                min(q1.y,q2.y) <= max(p1.y,p2.y);
    return ret;
}
//跨立判断
bool IsLineSegmentCross(const Point &P1,const Point &P2,const Point &Q1,const Point &Q2)
{
    if(
        ((Q1.x-P1.x)*(Q1.y-Q2.y)-(Q1.y-P1.y)*( Q1.x-Q2.x)) * ((Q1.x-P2.x)*(Q1.y-Q2.y)-(Q1.y-P2.y)*(Q1.x-Q2.x)) < 0 ||
        ((P1.x-Q1.x)*(P1.y-P2.y)-(P1.y-Q1.y)*(P1.x-P2.x)) * ((P1.x-Q2.x)*(P1.y-P2.y)-(P1.y-Q2.y)*( P1.x-P2.x)) < 0
    ) 
        return true;
    else
       return false;
}
 
 
 
int main() //O(n^2)
{
    int n,i,j;
    Point arr[N][2];
    int count;  
 
    while(scanf("%d",&n)!=EOF && n!=0)//第一行为一个正整数n表示线段的个数(n<=10000)
    {
        count=0;
        for(i=1;i<=n;i++)
            scanf("%d %d %d %d", &arr[i][0].x,  &arr[i][0].y, &arr[i][1].x,&arr[i][1].y); //第二行到第n+1行每行包括4个正整数x1,y1,x2,y2, (0 <= x1,y1,x2,y2 <= 1000) 
 
        for(i=1; i<=n; i++)
            for(j=i+1; j<=n; j++)
                if(IsRectCross(arr[i][0],arr[i][1],arr[j][0],arr[j][1])&&IsLineSegmentCross(arr[i][0],arr[i][1],arr[j][0],arr[j][1]))
                    count++;
        printf("%d\n",count);
    }
    return 0;   
}
 
/** 
8
10 13 20 56
37 60 40 7
87 57 113 5
96 16 125 51
171 4 231 4
200 4 211 43
268 36 354 36
283 4 314 36            
**/
 
/**************************************************************
    Problem: 1171
    User: cld378632668
    Language: C++
    Result: Time Limit Exceed
****************************************************************/

AC 代码

#include <stdio.h>
#include <string.h>
#define p(x1,y1,x2,y2,a,b) ((y2-y1)*(a-x1)+(y1-b)*(x2-x1))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
//    freopen("1.out","w",stdout);
    #endif // ONLINE_JUDGE
    int n,m;
    scanf("%d",&n);
    int x1[n+1],y1[n+1],x2[n+1],y2[n+1],i,j,a,b,c,d,sum=0;
    for (i=1;i<=n;i++)
        scanf("%d%d%d%d",x1+i,y1+i,x2+i,y2+i);
    for (i=1;i<n;i++)
        for (j=i+1;j<=n;j++)
        {
            a=p(x1[j],y1[j],x2[j],y2[j],x1[i],y1[i]);
            b=p(x1[j],y1[j],x2[j],y2[j],x2[i],y2[i]);
            c=p(x1[i],y1[i],x2[i],y2[i],x1[j],y1[j]);
            d=p(x1[i],y1[i],x2[i],y2[i],x2[j],y2[j]);
            if (!a && !b && !c && !d)
            {
                if (max(x1[i],x2[i])>=min(x1[j],x2[j]) && max(x1[j],x2[j])>=min(x1[i],x2[i]) && max(y1[i],y2[i])>=min(y1[j],y2[j]) && max(y1[j],y2[j])>=min(y1[i],y2[i]))
                    sum++;
            }
            else
            {
                if ((a<=0 && b>=0 || a>=0 && b<=0) && (c<=0 && d>=0 || c>=0 && d<=0))
                {
                    sum++;
                    //printf("%d %d\n",i,j);
                }
            }
        }
    printf("%d\n",sum);
    return 0;
}
 
阅读 1.3k

推荐阅读
飞翔的大象
用户专栏

写博客:一方面,为了找到更多志同道合的人;另一方面,为了更好地学习研究SEO,扩大影响力。 我的博客...

23 人关注
72 篇文章
专栏主页