POJ 2318 || POJ 2398判断点和线段的位置

POJ 2318:

题意 : 给一个矩形,然后有n条不相交的线段,线段的两个端点在矩形的上下两条边上,这样就把矩形划分成了n+1个区域,然后给出m个点(不在线上),问最终每个区域中有几个点

思路 : 利用向量的叉乘来判断这个点在某线段的顺时针还是逆时针方向上,然后二分找到位置(线段已经排好序了)

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 5100;
const double PI = acos(-1);
struct POINT{
    int x;
    int y;
    POINT(int a = 0,int b = 0){x = a;y = b;}
};///点 定义
struct SEGMENT{///line segment
    POINT s;
    POINT e;
    SEGMENT(POINT a,POINT b){s = a;e = b;}
    SEGMENT(){}
};///线段 定义
struct LINE{///ax + by + c = 0&&a >= 0
    double a;
    double b;
    double c;
    LINE(double da,double db,double dc){a = da;b = db;c = dc;}
};
int multiply(POINT sp,POINT ep,POINT op){
    return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}///向量op->sp X op->ep的叉乘,小于0:ep在op->sp顺时针方向//大于0:0:ep在op->sp逆时针方向//等于0:三点共线
int main(){
    int n,m;
    POINT pp[maxn][2];
    int ans[maxn];
    while(cin>>n){
        if(n == 0)break;
        cin>>m;
        int x1,x2,y1,y2;
        POINT now;
        cin>>x1>>y1>>x2>>y2;
        int u,l;
        for(int i = 0;i < n;i ++){
            cin>>u>>l;
            now.x = u,now.y = y1;
            pp[i][0] = now;
            now.x = l,now.y = y2;
            pp[i][1] = now;
        }
        now.x = x2;now.y = y2;
        pp[n][1] = now;
        now.y = y1;
        pp[n++][0] = now;
        //for(int i = 0;i < n;i ++)cout<<pp[i][0].x<<' '<<pp[i][0].y<<' '<<pp[i][1].x<<' '<<pp[i][1].y<<' '<<endl;
        memset(ans,0,sizeof(ans));
        while(m --){
            int a,b;
            cin>>a>>b;
            now.x = a;
            now.y = b;
            int l = 0,r = n-1,m;
            while(r - l > 0){
                m = (l + r)>>1;//cout<<m<<endl;
                if(multiply(pp[m][0],now,pp[m][1]) < 0)l = m+1;
                else r = m;
            }//cout<<endl;
            ans[l] ++;
        }
        for(int i = 0;i < n;i ++)cout<<i<<": "<<ans[i]<<endl;//cout<<endl;
        cout<<endl;
    }
    return 0;
}


POJ 2398:

题意:跟上一道题差不多,只不过是边没有排序,自己排一下就行了,然后输出的解不太一样

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 5100;
const double PI = acos(-1);
struct POINT{
    int x;
    int y;
    POINT(int a = 0,int b = 0){x = a;y = b;}
};///点 定义
struct SEGMENT{///line segment
    POINT s;
    POINT e;
    SEGMENT(POINT a,POINT b){s = a;e = b;}
    SEGMENT(){}
};///线段 定义
struct LINE{///ax + by + c = 0&&a >= 0
    double a;
    double b;
    double c;
    LINE(double da,double db,double dc){a = da;b = db;c = dc;}
};
int multiply(POINT sp,POINT ep,POINT op){
    return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}///向量op->sp X op->ep的叉乘,小于0:ep在op->sp顺时针方向//大于0:0:ep在op->sp逆时针方向//等于0:三点共线
bool cmp(SEGMENT A,SEGMENT B){
    return A.s.x < B.s.x;
}
int main(){
    int n,m,x1,y1,x2,y2;
    while(cin>>n){
        if(n == 0)break;
        cin>>m>>x1>>y1>>x2>>y2;
        int ans[maxn];
        int nn[maxn];
        SEGMENT pp[maxn];
        for(int i = 0;i < n;i ++){
            POINT now;
            int a,b;
            cin>>a>>b;
            now.x = a;now.y = y1;
            pp[i].s = now;
            now.x = b;now.y = y2;
            pp[i].e = now;
        }
        POINT now;
        now.x = x2;
        now.y = y2;
        pp[n].e = now;
        now.y = y1;
        pp[n++].s = now;
        memset(ans,0,sizeof(ans));
        memset(nn,0,sizeof(nn));
        sort(pp,pp+n,cmp);
        //for(int i = 0;i < n;i ++)cout<<pp[i].e.x <<' '<< pp[i].e.y<<endl;
        while(m --){
            int l = 0,r = n-1,mid;
            cin>>now.x>>now.y;
            while(r > l){
                mid = (l + r)>>1;
                if(multiply(pp[mid].s,now,pp[mid].e) < 0)l = mid +1;
                else r = mid;
            }
            ans[l] ++;
        }
        cout<<"Box"<<endl;
        for(int i = 0;i < n;i ++)
            nn[ans[i]] ++;
        for(int i = 1;i < maxn;i ++){
            if(nn[i])cout<<i<<": "<<nn[i]<<endl;
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值