POJ 2318 TOYS 计算几何 线段相交

本文介绍了一种用于判断线段是否相交及确定交点位置的算法,并提供了完整的C++实现代码。该算法适用于计算几何领域,特别是解决二维平面上线段之间的交叉问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(x2,y1)和(x,y)形成的一条线段和给出的线段的交点。

http://poj.org/problem?id=2318

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 4005;

const int eps = 1e-8;

int sgn(int x) {
    if(fabs(x) < eps) return 0;
    return x > 0 ? 1 : -1;
}

struct Point{
    int x,y;
    Point(){}
    Point(int _x,int _y){
        x = _x ; y = _y;
    }
    Point operator + (const Point B) const {
        return Point(x+B.x,y+B.y);
    }
    Point operator - (const Point B) const {
        return Point(x-B.x,y-B.y);
    }
    int operator ^ (const Point B) const {
        return x * B.y - y * B.x;
    } 
};

int cross(Point a1,Point a2,Point a3){ // >0 a3在a1_a2这条线的左边 <0 右边 =0 三点共线;
    return (a2.x-a1.x)*(a3.y-a2.y)-(a3.x-a2.x)*(a2.y-a1.y);
}

struct Line{
    Point s,e;
    Line() {}
    Line(Point _s,Point _e) {
        s = _s ; e = _e ;
    }
    Line(int x1,int y1,int x2,int y2) {
        s = Point(x1,y1); e = Point(x2,y2);
    }
    bool inter(const Line B) {
        return  max(s.x,e.x) >= min(B.s.x,B.e.x) &&
                max(B.s.x,B.e.x) >= min(s.x,e.x) &&
                max(s.y,e.y) >= min(B.s.y,B.e.y) &&
                max(B.s.y,B.e.y) >= min(s.y,e.y) &&
    sgn(cross(s,e,B.s))*sgn(cross(s,e,B.e)) <= 0 &&
    sgn(cross(B.s,B.e,s))*sgn(cross(B.s,B.e,e)) <= 0 ;
    }
    void print() {
        printf("%d  %d  %d  %d \n",s.x,s.y,e.x,e.y);
    }
};

bool cmp_x_y(Point a1,Point a2) {
    if(a1.y == a2.y)
        return a1.x < a2.x;
    else 
        return a1.y < a2.y;
}

int N,M;
int my_x1,my_x2,my_y1,my_y2;
Line A[5005];
Point B[5005];
int ans[5005];

void input() {
    memset(ans,0,sizeof(ans));
    scanf("%d",&M);
    scanf("%d %d %d %d",&my_x1,&my_y1,&my_x2,&my_y2);
    int Ui,Li;
    for(int i = 1 ; i <= N ; i++) { //N条线;
        scanf("%d %d",&Ui,&Li);
        A[i] = Line(Ui,my_y1,Li,my_y2);
    }
    A[N+1] = Line(my_x2,my_y1,my_x2,my_y2);
    int tempx,tempy;
    for(int i = 1 ; i <= M ; i++) { //M个点的查询;
        scanf("%d %d ",&tempx,&tempy);
        B[i] = Point(tempx,tempy);
    }
}

void solve() {
    for(int i = 1 ; i <= M ; i++) {
        for(int j = 1 ; j <= N + 1; j++) {
            if(A[j].inter(Line(Point(my_x1,my_y2),B[i])) == false) {
            //if(cross(A[j].s,A[j].e,B[i])<0) {
                ans[j-1]++;
                break;
            }
        }
    }
    for(int i = 0 ; i <= N ; i++) {
        printf("%d: %d\n",i,ans[i]);
    }
}

int main(void) {
    //freopen("a.in","r",stdin);
    int casenum = 0;    
    while(scanf("%d",&N),N) {
        if(casenum++)puts("");
        input();
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值