POJ 2398 Toy Storage 线段相交

本文介绍了一种解决线段交集问题的方法,并通过具体的C++代码实现了解决方案。该方法首先定义了点和线段的数据结构,然后利用向量叉乘等数学工具判断线段是否相交。此外,还提供了对多个线段和点进行查询的功能。

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

和poj的2318一样的思路

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

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

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

bool cmpbys(Line a1,Line a2) {
   if(a1.s.x == a2.s.x)
        return a1.s.y < a2.s.y;
    else 
        return a1.s.x < a2.s.x;
}

void input() {
    memset(ans,0,sizeof(ans));
    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);
    }
    sort(A+1,A+N+1,cmpbys);
    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(j==2) {
            //        Line(Point(my_x1,my_y2),B[i]).print();
            //    }
            //if(cross(A[j].s,A[j].e,B[i])<0) {
                ans[j-1]++;
                break;
            }
        }
    }
    for(int i = 0 ; i <= N ; i++) {
        ANS[ans[i]]++;
        //printf("%d: %d\n",i,ans[i]);
    }
    for(int i = 1 ; i <= 5000 ; i++) {
        if(ANS[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("");
        puts("Box");
        input();
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值