题目链接
题解数学:计算几何。
提示: 这题默认好像是顺时针或逆时针输入坐标,也就是说先后输入的两个点一定是多边形的一条边。
前置知识:PNPoly算法 何为PNPoly算法算法? 通俗的来讲,这个算法用于判断一个点是否位于一个封闭的多边形中。 判断方式是以这个点为始端向一个选定的方向作射线,若射线穿过奇数条多边形的边,则说明点位于多边形内,为偶数则说明不在多边形内。 原理很简单,若这个点位于多边形内部,那么这条射线第一次穿过多边形的一条边必然是到达了多边形的外面,若又穿过了一条边,则必然是又回到了多边形内部,……,如此下去,存在交替的规律;同样的,若点处于多边形外面,则射线第一次穿过多边形的一条边一定是进入到多边形的内部了,再穿过一条就出多边形了,……。
如下图的蓝色和红色的射线均穿过奇数条边,因此属于多边形内部;而紫色的穿过偶数条边,属于多边形外部。
伪代码:
bool check(要判断的点的横坐标x, 要判断的点的纵坐标y) {
bool flag = false;
for(多边形上相邻的点:i和j) {
x1=i的横坐标, x2=j的横坐标, y1=i的纵坐标, y2=j的纵坐标
if(x在y1、y2的范围内) {
tmp_x = 将y代入到(x1, y2)、(x2, y2)构成的直线的两点式中,求出对应的tmp_x
if(tmp_x 位于 x 左侧,即x>tmp_x) flag = !flag;
}
}
return false;
}
知道了这个算法本题就相当于解决了一大半了。
整体思路: 我们确定出输入的点中x坐标的上界和下界,y坐标的上界和下界,满足要求的格子一定是在这个坐标范围内的,因此我们对这个范围内的格子的四个点执行PNPoly算法进行判断即可,若四个点都处于多边形内部,则说明这个格子也处于多边形内部,此时记录个数的ans++。
此时你可以先理解一下下面的“非完美AC代码”,有助于你理解下面如何修改成完美代码。
看起来这样就结束了,确实结束了,可以AC,但是很多数据是过不了的,举个简单的例子:
4
0 0
0 1
1 1
1 0
对应的图像为:
很显然答案是1,但是很多博主或者AC代码的解都为0,具体原因可以模拟分析一遍。
我为了解决健壮性的问题,再三考虑后,终于想出解决方法了。
在向check中传入参数时,我们不再传格子四个点的坐标,而是取稍小于格子一点的四个坐标,如下图为1×1的方格: 我们不再以红色区域的四个点的坐标作为方格的四个角的坐标了,而是以绿色虚线区域的四个角的坐标作为方格四个角的坐标。 这个绿色区域的大小其实与红色区域的大小所差无几,这只是为了解决对于有些方案无法输出正确答案的问题。
因此在这里我设置了一个det常量,表示绿色边框与红色边框的距离,每次向check中传入的是绿框的四个角的位置。
举几个比较奇葩的例子:
例子1
8
0 0
0 3
3 3
3 0
2 0
2 2
1 2
1 0
7
例子2
12
0 2
1 4
2 4
2 3
1 3
1 2
3 2
3 3
4 3
4 2
3 1
4 0
3
例子1例子2对应的图像分别是:
#include
using namespace std;
const int N = 1010;
const double det = 0.00001;
struct node {
int x, y;
} po[N];
int upx, lox, upy, loy, n, ans;
int check(int x, int y) {
bool flag = false;
for(int i = 1, j = n;i n;
for(int i = 1;i >po[i].x>>po[i].y;
upx = max(upx, po[i].x);
lox = min(lox, po[i].x);
upy = max(upy, po[i].y);
loy = min(loy, po[i].y);
}
for(int i = lox;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?