首页 > 代码库 > geometry2653

geometry2653

题意解释:

    给出几根棍子扔出的顺序,抛出方式任意,有的会重叠有的不会,问最后哪些棍子不被其他的棍子压住。

 

选题原因:

计算几何中判断直线的相交是一个热门问题,通过此题向大家介绍判断直线相交的几种基本方法。几何问题的解决离不开图,所以建议大家在面对几何问题时多借助做图来理解题意。

 

1.判断两条直线相交

    先来看一个简单的情况,即判断两条直线是否相交。

第一个可能会想到的办法,就是判断斜率,这个在中学时代就学过了,不过斜率需要考虑垂直的特殊情况,比较麻烦。更好的办法或许是计算两个向量的叉积,如果为0,则是平行或者重合的,否则两直线相交。

 

2判断两线段相交

经典方法,就是跨立试验了,即如果一条线段跨过另一条线段,则线段的两个端点分别在另一条线段的两侧。但是,还需要检测边界情况,即两条线段中可能某条线段的某个端点正好落在另一条线段上。这也是算法导论中介绍的算法。

 

 

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

 

const int N=100001;

const double eps=1e-10;

struct node

{

    double x,y;

}p[N],b[N];

 

bool ans[N];

double min(double a,double b) {return a<b?a:b;}

double max(double a,double b) {return a>b?a:b;}

bool judge(node p1,node p2,node p3,node p4)

{

    if(min(p1.x,p2.x)>max(p3.x,p4.x)||//这个判断是快速排斥实验

                                                        

       min(p1.y,p2.y)>max(p3.y,p4.y)||

       min(p3.x,p4.x)>max(p1.x,p2.x)||

       min(p3.y,p4.y)>max(p1.y,p2.y))

       return 0;

 

       double a,b,c,d;//以下是跨立实验,原则是

       a=(p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);

       b=(p2.x-p1.x)*(p4.y-p1.y)-(p2.y-p1.y)*(p4.x-p1.x);

       c=(p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x);

       d=(p4.x-p3.x)*(p2.y-p3.y)-(p4.y-p3.y)*(p2.x-p3.x);

 //前面已经经过排斥实验,所以不用担心上图4的情况

       return a*b<=eps&&c*d<=eps;

}

int main()

{

    int n;

    int res[N];

    while(scanf("%d",&n)!=EOF&&n)

    {

        memset(ans,0,sizeof(ans));

        for(int i=0;i<n;i++)

        {

            scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&b[i].x,&b[i].y);

     }

        for(int i=0;i<n;i++)

        {

            for(int j=i+1;j<n;j++)

            {

                if(judge(p[i],b[i],p[j],b[j]))

                {

                    ans[i]=1;

                    break;

                }

            }

        }

        int cc=0;

        printf("Top sticks:");

        for(int i=0;i<n;i++)

        {

            if(!ans[i]) res[cc++]=i+1;

        }

        for(int i=0;i<cc-1;i++)

        printf(" %d,",res[i]);

        printf(" %d.\n",res[cc-1]);

    }

    return 0;

}

geometry2653