• 判断点是否在不规则多边形内(预处理优化)


    RPG的地图

    题意

    判断点是否在不规则多边形内,

    分析

    首先,所有横、纵坐标都+1000,方便标记和累加。

    1. 在边上也满足条件,对于垂直或平行于 x 轴的线段,直接在枚举线段的时候标记下其中的所有点即可。对于其它线段,表示成 y = k * x + b 的形式,枚举 x 找到,整数 y 即可。
    2. 对于在里面的点,通过射线法判断,但是查询的点过多,考虑通过预处理优化,考虑一条垂直于 x 轴向下的射线,对于每条边,对应的 x ,得到的上面的 y ,比如代入 x ,得到的是小数的 y ,向上取整即可,标记+1,表示这一点即上面的点发出的射线都会与这条线段产生交点,对于垂直于 x 轴的直线要特殊判断。对于一条线段,端点值判断一个。标记数组从下向上累加,预处理出前缀和,表示当前这个点向下发出射线会有几个交点,通过奇偶性(奇数在多边形内,偶数不在)得到答案。

    射线法
    射线法

    code

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    using namespace std;
    typedef long long ll;
    const ll MOD = 1e9 + 7;
    const int MAXN = 1e5 + 5;
    const int INF = 1e9;
    int x[MAXN], y[MAXN];
    int vis[2005][2005];
    int bj[2005][2005];
    int main()
    {
        int n, m;
        while(~scanf("%d%d", &n, &m))
        {
            memset(vis, 0, sizeof vis);
            memset(bj, 0, sizeof bj);
            for(int i = 0; i < n; i++)
            {
                scanf("%d%d", &x[i], &y[i]);
                x[i] += 1000;
                y[i] += 1000;
                vis[x[i]][y[i]] = 1;
            }
            x[n] = x[0]; y[n] = y[0];
            x[n + 1] = x[1]; y[n + 1] = y[1];
            for(int i = 1; i <= n; i++)
            {
                int j = i - 1;
                if(x[i] == x[j])
                {
                    int mn = min(y[i], y[j]);
                    int mx = max(y[i], y[j]);
                    for(int k = mn; k <= mx; k++) vis[x[i]][k] = 1;
                    if(n > 3)
                    {
                        int x1 = (j == 0 ? x[n - 1] : x[j - 1]);
                        int x2 = x[i + 1];
                        if(x1 > x[i] && x2 < x[i]) bj[x[i]][mx + 1]++;
                        if(x1 < x[i] && x2 > x[i]) bj[x[i]][mx + 1]++;
                    }
                }
                else if(y[i] == y[j])
                {
                    int mn = min(x[i], x[j]);
                    int mx = max(x[i], x[j]);
                    for(int k = mn; k <= mx; k++)
                    {
                        vis[k][y[i]] = 1;
                        if(k != mn && k != mx)
                            bj[k][y[i] + 1]++;
                    }
                    if(x[i + 1] > x[i] && x[j] < x[i]) bj[x[i]][y[i] + 1]++;
                    if(x[i + 1] < x[i] && x[j] > x[i]) bj[x[i]][y[i] + 1]++;
     
                }
                else
                {
                    double k = 1.0 * (y[i] - y[j]) / (x[i] - x[j]);
                    double b = 1.0 * (x[i] * y[j] - x[j] * y[i]) / (x[i] - x[j]);
                    int mn = min(x[i], x[j]);
                    int mx = max(x[i], x[j]);
                    for(int i = mn; i <= mx; i++)
                    {
                        double y1 = i * k + b;
                        int y2 = (int)y1;
                        int y3 = int(ceil(y1));
                        if(i != mn && i != mx)
                        {
                            bj[i][y3]++;
                        }
                        if(y2 == y1)
                        {
                            vis[i][y2] = 1;
                        }
                    }
                    double y1 = x[i] * k + b;
                    int y3 = int(ceil(y1));
                    if(x[i + 1] > x[i] && x[j] < x[i]) bj[x[i]][y3]++;
                    if(x[i + 1] < x[i] && x[j] > x[i]) bj[x[i]][y3]++;
     
                }
            }
            for(int i = 0; i <= 2000; i++)
            {
                for(int j = 0; j <= 2000; j++)
                {
                    bj[i][j + 1] += bj[i][j];
                }
            }
            for(int i = 0; i < m; i++)
            {
                int qx, qy;
                scanf("%d%d", &qx, &qy);
                qx += 1000; qy += 1000;
                int f = vis[qx][qy];
                if(!f)
                {
                    f = (bj[qx][qy] & 1);
                }
                puts(f ? "Yes" : "No");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Codeforces Round #417 C. Sagheer and Nubian Market
    linux 终端抓包命令
    计算机网络体系结构分析
    排序算法-快速排序
    排序算法-堆排序
    排序算法-希尔排序
    排序算法-插入排序
    排序算法-冒泡排序
    排序算法-选择排序
    杂谈:终端小工具
  • 原文地址:https://www.cnblogs.com/ftae/p/6791426.html
Copyright © 2020-2023  润新知