poj 2653 线段相交

题意就是给你一堆线段,按顺序扔下,输出最后在最上层的是哪几个线段

题解:给每条线段赋一个id,用一个队列维护目前所有在顶层的线段,每次加入一条线段的时候,判断这条线段是否与队列的线段相交,如果相交则队列里的那个线段出队,新的线段入队。否则两条一起再次入队列。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define MIN(x , y) (x < y ? x : y)
#define infinity 1e20
#define EP 1e-10
const int mmx = 100010;
const int MAXV = 300;
const double PI = 2.0*asin(1.0);
int ans[mmx];
struct Lpoint
{
    double x,y;
};
struct Llineseg
{
    Lpoint a,b;
    int id;
} line[mmx];
struct Ldir
{
    double dx, dy;
};
struct Lline
{
    Lpoint p ;
    Ldir dir;
    int id;
};
struct Lrad
{
    Lpoint Sp;
    Ldir dir;
};
struct Lround
{
    Lpoint co;
    double r;
};

double xmulti(Lpoint p1,Lpoint p2,Lpoint p0)
{
    return((p1.x-p0.x) * (p2.y-p0.y) -
           (p2.x-p0.x) * (p1.y-p0.y));
}

double mx(double t1,double t2)
{
    if(t1>t2) return t1;
    return t2;
}
double mn(double t1,double t2)
{
    if(t1<t2) return t1;
    return t2;
}
int lsinterls(Llineseg u,Llineseg v)
{
    return( (mx(u.a.x,u.b.x)>=mn(v.a.x,v.b.x))&&
            (mx(v.a.x,v.b.x)>=mn(u.a.x,u.b.x))&&
            (mx(u.a.y,u.b.y)>=mn(v.a.y,v.b.y))&&
            (mx(v.a.y,v.b.y)>=mn(u.a.y,u.b.y))&&
            (xmulti(v.a,u.b,u.a)*xmulti(u.b,v.b,u.a)>=0)&&
            (xmulti(u.a,v.b,v.a)*xmulti(v.b,u.b,v.a)>=0));
}

int ponls(Llineseg l,Lpoint p)
{
    return( (xmulti(l.b,p,l.a)==0) &&
            ( ((p.x-l.a.x)*(p.x-l.b.x)<0 ) ||
              ((p.y-l.a.y)*(p.y-l.b.y)<0 )) );
}

int Euqal_Point(Lpoint p1,Lpoint p2)
{
    return((fabs(p1.x-p2.x)<EP)&&(fabs(p1.y-p2.y)<EP));
}


int lsinterls_A(Llineseg u,Llineseg v)
{
    return((lsinterls(u,v)) && (!Euqal_Point(u.a,v.a))&&
           (!Euqal_Point(u.a,v.b)) &&
           (!Euqal_Point(u.b,v.a))&&
           (!Euqal_Point(u.b,v.b)));
}
using namespace std;
bool vis[mmx];

int main()
{
//    freopen("2653.txt","r",stdin);
    int n;
    while(scanf("%d",&n),n)
    {
        queue<Llineseg> q[2];
        memset(line,0,sizeof(line));
        for(int i=1; i<=n; i++)
        {
            scanf("%lf %lf %lf %lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y);
            line[i].id = i;
        }
        q[0].push(line[1]);
        int a = 1;
        int b = 0;
        for(int i=2; i<=n; i++)
        {
            swap(a , b);
            while(!q[a].empty())
            {
                Llineseg one = q[a].front();
                q[a].pop();
                if(lsinterls_A(one , line[i]) == true)
                {
                    if(!vis[line[i].id])
                        q[b].push(line[i]),vis[line[i].id] = true;
                }
                else
                {
                    if(!vis[line[i].id])
                        q[b].push(line[i]), vis[line[i].id] = true;
                    if(!vis[one.id])
                        q[b].push(one), vis[one.id] = true;
                }
            }
            memset(vis,0,sizeof(vis));

//            queue<ln> :: iterator it;
//            for(it = q[b].begin(); it != q[b].end(); it++)
//                printf(" %d",tem.id);
//            printf("\n");

        }
        printf("Top sticks:");
        int num = 0;
        while(!q[b].empty())
        {
            Llineseg tem = q[b].front();
            q[b].pop();
            ans[++num] = tem.id;
        }
        sort(ans+1, ans+1+num);
        printf(" %d",ans[1]);
        for(int i=2; i<=num; i++)
            printf(", %d",ans[i]);
        printf(".\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值