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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值