POJ2398计算几何、叉积判断点在线段左/右侧

题目

Toy Storage

二维平面中有一个矩形,放入n块隔板,将矩形分成n+1个区域,隔板保证不相交且两端点在矩形的两条横向线段中。形如下图:

请添加图片描述

给出m个点,求包含t个点的区域数量。

求解思路

可以用叉积判断一个点在线段的左侧还是右侧。

O A ⃗ × O B ⃗ = ∣ O A ∣ × ∣ O B ∣ × sin ⁡ θ \vec{OA} \times \vec{OB}=|OA|\times|OB|\times \sin\theta OA ×OB =OA×OB×sinθ

叉积为负,说明 θ 大 于 π \theta 大于\pi θπ

请添加图片描述

如果 O A ⃗ × O B ⃗ > 0 \vec{OA} \times \vec{OB} >0 OA ×OB >0 并且 O C ⃗ × O D ⃗ < 0 \vec{OC} \times \vec{OD}<0 OC ×OD <0,说明点O在区域ABCD内。

代码

#include <iostream>
#include <map>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 1e4 + 5;

struct node
{
    int u, d;
    bool operator<(const node temp) const
    {
        return u < temp.u;
    }
} s[N];
int tong[N];
int ans[N];
int n, m, sx, sy, ex, ey;

typedef struct Point
{
    double x, y;
} Vector;

bool check(Vector A, Vector B)
{
    if (A.x * B.y - A.y * B.x <= 0)
        return 0;
    return 1;
}

void solve()
{
    memset(tong, 0, sizeof tong);
    memset(ans, 0, sizeof ans);
    scanf("%d %d %d %d %d", &m, &sx, &sy, &ex, &ey);
    for (int i = 1; i <= n; i++)
        scanf("%d %d", &s[i].u, &s[i].d);
    sort(s + 1, s + 1 + n);
    s[n + 1].u = s[n + 1].d = ex;

    for (int i = 1; i <= m; i++)
    {
        int x, y;
        scanf("%d %d", &x, &y);
        for (int j = 1; j <= n + 1; j++)
        {
            Vector A, B, C, D;
            A.x = s[j - 1].u - x;
            A.y = sy - y;
            B.x = s[j - 1].d - x;
            B.y = ey - y;

            C.x = s[j].u - x;
            C.y = sy - y;
            D.x = s[j].d - x;
            D.y = ey - y;

            if (check(A, B) && !check(C, D))
            {
                tong[j]++;
                break;
            }
        }
    }
    for (int i = 1; i <= n + 1; i++)
    {
        if (tong[i])
            ans[tong[i]]++;
    }
    printf("Box\n");

    for (int i = 1; i <= n + 1; i++)
        if (ans[i])
            printf("%d: %d\n", i, ans[i]);
}

int main()
{
    while (scanf("%d", &n) && n)
        solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值