poj2653(判断两线段相交)

题目链接:poj2653

大意:有很多根木棍,如果后面的木根和前面的木棍有交叉的话,后面的木棍就会覆盖掉前面的木棍,问最后没有被覆盖的木棍数

思路:运用队列模拟,如果当前输入的木棍和前面的木棍交叉,那么将前面的那个木棍取出队列,否则的话,将从队列中取出的木棍再次入队

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<double,double> pdd;
double direction(pdd p1, pdd p2, pdd p3)//求向量的叉积
{
    pdd d1 = make_pair(p3.first - p1.first, p3.second - p1.second);
    pdd d2 = make_pair(p2.first - p1.first, p2.second - p1.second);
    return d1.first*d2.second - d1.second*d2.first;
}
bool on_segment(pdd p1, pdd p2, pdd p3)//判断一条线段的端点是否在另一条线段上
{
    double min_x = p1.first < p2.first ? p1.first : p2.first;
    double max_x = p1.first > p2.first ? p1.first : p2.first;
    if(min_x <= p3.first && p3.first <= max_x)//判断p3的x坐标是否在p1和p2之间
        return true;
    else
        return false;
}
bool SegmentIntersect(pdd p1, pdd p2, pdd p3, pdd p4)
{
    double d1 = direction(p1, p2, p3);
    double d2 = direction(p1, p2, p4);
    double d3 = direction(p3, p4, p1);
    double d4 = direction(p3, p4, p2);
    if(d1*d2 < 0 && d3*d4 < 0)
        return true;
    else if(d1 == 0 && on_segment(p1, p2, p3))
        return true;
    else if(d2 == 0 && on_segment(p1, p2, p4))
        return true;
    else if(d3 == 0 && on_segment(p3, p4, p1))
        return true;
    else if(d4 == 0 && on_segment(p3, p4, p2))
        return true;
    else
        return false;
}
struct point
{
    double x1,y1,x2,y2;
    int id;
}s;
void solve(int n)
{
    queue <point> q;
    scanf("%lf%lf%lf%lf",&s.x1,&s.y1,&s.x2,&s.y2);
    s.id = 1;
    q.push(s);
    for(int i = 2; i <= n; i ++)
    {
        scanf("%lf%lf%lf%lf",&s.x1,&s.y1,&s.x2,&s.y2);
        s.id = i;
        q.push(s);
        while(!q.empty())
        {
            point tmp = q.front();
            q.pop();
            if(s.id == tmp.id)//队列中的所有元素都判断过了
            {
                q.push(s);
                break;
            }
            pdd p1 = make_pair(s.x1, s.y1);
            pdd p2 = make_pair(s.x2, s.y2);
            pdd p3 = make_pair(tmp.x1, tmp.y1);
            pdd p4 = make_pair(tmp.x2, tmp.y2);
            if(!SegmentIntersect(p1,p2,p3,p4))//不交叉
            {
                q.push(tmp);
            }
        }
    }
    s = q.front(); q.pop();
    printf("Top sticks: %d",s.id);
    while(!q.empty())
    {
        s = q.front();
        q.pop();
        printf(", %d",s.id);
    }
    printf(".\n");
}
int main()
{
    int n,i,j;
    while(scanf("%d",&n),n)
    {
        solve(n);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值