[POJ2318]TOYS(计算几何+二分)

55 篇文章 0 订阅
45 篇文章 0 订阅

题目描述

传送门
题意:一些直线把一个矩形分割成了若干个部分。给出一些点问每一个部分里有多少个点

题解

叉积的性质: a×b ,如果ba的左边,叉积为正,右边为负,ab共线即为0
可以二分出所在部分的右边界,是否在某一条直线的右边可以用叉积判断一下

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ctime>
using namespace std;
#define N 10005

const double eps=1e-9;
int dcmp(double x)
{
    if (x<=eps&&x>=-eps) return 0;
    return (x>0)?1:-1;
}
struct Vector
{
    double x,y;
    Vector(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
};
typedef Vector Point;
struct Line
{
    Point p;
    Vector v;
    Line(Point P=Point(0,0),Vector V=Vector(0,0))
    {
        p=P,v=V;
    }
};
Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}

int n,m;
double a,b,c,d,ui,li,x,y;
Line l[N];
int ans[N];

void clear()
{
    memset(ans,0,sizeof(ans));
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
bool check(int mid,Point pt)
{
    Point st=l[mid].p;
    Vector c=Vector(pt.x-st.x,pt.y-st.y);
    double t=Cross(l[mid].v,c);
    if (dcmp(t)>0) return true;
    else return false;
}
int find(Point pt)
{
    int l=1,r=n+1,mid,ans=0;
    while (l<=r)
    {
        mid=(l+r)>>1;
        if (check(mid,pt)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    return ans;
}

int main()
{
    while (~scanf("%d",&n))
    {
        if (!n) break;
        clear();
        scanf("%d",&m);
        scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
        for (int i=1;i<=n;++i)
        {
            scanf("%lf%lf",&ui,&li);
            l[i]=Line(Point(li,d),Vector(ui-li,b-d));
        }
        l[n+1]=Line(Point(c,d),Vector(0,b-d));
        for (int i=1;i<=m;++i)
        {
            scanf("%lf%lf",&x,&y);
            int loc=find(Point(x,y));
            ++ans[loc];
        }
        for (int i=0;i<=n;++i)
            printf("%d: %d\n",i,ans[i+1]);
        puts("");
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值