7_4_P题 Toy Storage 题解[Poj 2398](计算几何,点线关系,二分)

题目链接

题意

给出一个矩形,和矩形内的一些线段,将矩形划分为若干box,再在矩形内放置若干点,问box内点的数量有有哪些,分别有几个box内有这么多的点。

思路

通过叉积来判断点和线的关心,设点为 p0 ,线段为 p1p2 ,则若 det(p0p1,p0p2) 小于0,则点在线的左侧,大于0 则点在直线的右侧,以此为依据二分(要先将线段排序),求得点所在盒子的编号。

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e3+5;

// -------------------- 通用基本常数 --------------------

const double eps = 1e-8;
const double pi  = acos(-1.0);

// -------------------- 二维点(向量)类 --------------------

struct Point {
    int x, y;
    Point() {}
    Point(int x, int y): x(x), y(y) {}
    // 输入一个点
    void input() {
        scanf("%lf%lf", &x, &y);
    }
    friend Point operator + (const Point& a, const Point& b) {
        return Point(a.x + b.x, a.y + b.y);
    }
    friend Point operator - (const Point& a, const Point& b) {
        return Point(a.x - b.x, a.y - b.y);
    }
    friend Point operator * (const Point& a, const double& b) {
        return Point(a.x * b, a.y * b);
    }
    friend Point operator * (const double& a, const Point& b) {
        return Point(a * b.x, a * b.y);
    }
    friend Point operator / (const Point& a, const double& b) {
        return Point(a.x / b, a.y / b);
    }
};

// -------------------- 向量与向量运算 --------------------

// 计算两个向量的叉积
double det(const Point& a, const Point& b) {
    return a.x * b.y - a.y * b.x;
}

// 计算两个向量的点积
double dot(const Point &a, const Point& b) {
    return a.x * b.x + a.y * b.y;
}


// -------------------- 线段(直线)类 --------------------

struct Line {
    Point a, b;
    Line() {}
    Line(Point x, Point y): a(x), b(y) {}
};

bool cmp(Line &a, Line &b){
    return a.a.x < b.a.x;
}

Line line[maxn];
Point toy;
int box[maxn];
int ans[maxn];
int main (){
    Point LT,RL;
    int n,m;
    while(~scanf("%d",&n) && n){
        scanf("%d %d %d %d %d",&m,&LT.x,&LT.y,&RL.x,&RL.y);
        for(int i = 0 ; i < n ; i ++){
            int Ui,Li;
            scanf("%d %d", &Ui,&Li);
            line[i] = Line(Point(Ui,LT.y),Point(Li,RL.y));
        }
        line[n] = Line(Point(RL.x,LT.y),RL);
        sort(line,line + n+1, cmp);
        memset(box,0,sizeof box);
        memset(ans,0,sizeof ans);
        for(int i = 0 ; i < m ; i ++){
            int x,y;
            scanf("%d %d", &x,&y);
            toy = Point(x,y);
            int l = 0 , r = n;
            int loc = 0;
            while(l <= r){
                int mid = (l+r) >> 1;
                if (det(line[mid].a - toy,line[mid].b - toy) < 0){
                    loc = mid;
                    r = mid -1;
                }
                else {
                    loc = mid +1;
                    l = mid + 1;
                }
            }
            box[loc] ++;
        }
        puts("Box");
        for(int i = 0 ; i <= n ; i ++)
            ans[box[i]] ++;
        for(int i = 1 ; i <= n ; i ++)
            if(ans[i])
                printf("%d: %d\n",i,ans[i]);
    }
    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值