POJ 2653 || Pick-up sticks (線段相交

在二維平面隨機扔木棍,找出最頂上的沒有被別的木棍壓着的木棍,輸出這些木棍的序號。


核心算法就是線段相交:

函數最後兩句是判斷這兩條直線的相交,因爲是線段,所以要加上線段端點的約束。

bool inter(pline l1,pline l2)
{
    return
        max(l1.st.x,l1.ed.x) >= min(l2.st.x,l2.ed.x) &&
        max(l2.st.x,l2.ed.x) >= min(l1.st.x,l1.ed.x) &&
        max(l1.st.y,l1.ed.y) >= min(l2.st.y,l2.ed.y) &&
        max(l2.st.y,l2.ed.y) >= min(l1.st.y,l1.ed.y) &&
       dcmp((l2.st-l1.st)^(l1.ed-l1.st))*dcmp((l2.ed-l1.st)^(l1.ed-l1.st)) <= 0 &&
        dcmp((l1.st-l2.st)^(l2.ed-l2.st))*dcmp((l1.ed-l2.st)^(l2.ed-l2.st)) <= 0;
}

代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define FOR(i,n) for(int i=0;i<n;++i)
const double epx = 1e-8;
struct pnode
{
    double x,y;
    pnode(){}
    pnode( double a,double b):x(a),y(b){}
    double operator ^ (const pnode &b)const
    {
        return x*b.y - y * b.x;
    }
    double operator *(const pnode&b)const
    {
        return x*b.x + y * b.y;
    }
    pnode operator - (const pnode &b)const
    {
        return pnode(x-b.x,y-b.y);
    }
};
double cross( pnode p0,pnode p1,pnode p2)
{
    return (p1-p0) ^ (p2-p0);
}
int dcmp( double x)
{
    if( fabs(x) <epx )
        return 0;
    return x < 0 ? -1:1;
}
struct pline
{
    pnode st,ed;
    pline (){}
    pline(pnode a,pnode b):st(a),ed(b){}
    void readl(){ scanf("%lf %lf %lf %lf",&st.x,&st.y,&ed.x,&ed.y); }
};

const int MX = 100005;
bool vis[MX];
pline line[MX];
bool inter(pline l1,pline l2)
{
    return
        max(l1.st.x,l1.ed.x) >= min(l2.st.x,l2.ed.x) &&
        max(l2.st.x,l2.ed.x) >= min(l1.st.x,l1.ed.x) &&
        max(l1.st.y,l1.ed.y) >= min(l2.st.y,l2.ed.y) &&
        max(l2.st.y,l2.ed.y) >= min(l1.st.y,l1.ed.y) &&
       dcmp((l2.st-l1.st)^(l1.ed-l1.st))*dcmp((l2.ed-l1.st)^(l1.ed-l1.st)) <= 0 &&
        dcmp((l1.st-l2.st)^(l2.ed-l2.st))*dcmp((l1.ed-l2.st)^(l2.ed-l2.st)) <= 0;
}
int main()
{
    int n;
    double x,y,x1,y1;
    while( scanf("%d",&n) && n)
    {
        for( int i=0;i<n;++i)
        {
            scanf("%lf %lf %lf %lf",&x,&y,&x1,&y1);
            line[i] = pline( pnode(x,y),pnode(x1,y1) );
            vis[i] = true;
        }

        for( int i = 0;i<n;++i)
            for( int j = i+1;j<n;++j)
                if(  inter(line[i],line[j]))
                {
                    vis[i] = false;
                    break;
                }
        printf("Top sticks: ");
        int f = 0;
        FOR(i,n)
        {
            if( vis[i])
            {
                if( f == 0)
                    f = 1;
                else printf(", ");

                printf("%d",i+1);
            }
        }
        printf(".\n");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章