一句话题意:
0-7八个数字表示8个方向,给你一串表示方向的数字,问按这种走法围成的多边形里面包含几个像素(保证是一个多边形)。
分析:
这题一看毫无头绪,甚至想上扫描线线段树…
后来问同学,才恍然大悟。
pick定理+多边形求面积
- Pick定理
什么是pick定理呢?
pick定理是对于点阵图来说的。
一个公式:2S = 2 * a + b - 2。
其中S表示像素围成的点阵图的面积,a 表示点阵图除边界外内部的像素个数,b 表示边界的像素个数。
举个栗子。(图是百度偷的)
拿下面的那个较小的三角形来说吧
对于这个三角形,其边界在格点上有四个点,内部没有完整的点。
即a = 0, b = 4.
他的面积可以表示为:2S = 2 * 0 + 4 - 2 = 2,即s = 1。
我们可以简单的通过三角形面积公式得到s = 2 * 1 / 2 = 1。
与实际情况吻合。
好了pick定理现在我们理解了,那么在这个题中是怎么运用的呢?
我们发现,对于 b ,也就是边界点的个数,我们是已知的,他的大小就等于字符串的长度。
内部的点与面积是未知的。
怎么求呢?
就是求多边形面积啦。
- 多边形求面积
再上图。
对于一个 n 边形,我们可以把它分为 n - 2 个三角形。
对于每个三角形,我们可以通过向量得到面积。
那么把多边形分解成多个三角形,就可以求出多边形的总面积了
好了,知道了多边形面积,和边界的像素个数,就可以求出内部的点的个数了。
那么答案就是 边界的点的个数+内部点的个数。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int dirx[8] = {0, -1, -1, -1, 0, 1, 1, 1};
int diry[8] = {1, 1, 0, -1, -1, -1, 0, 1};
int main()
{
string s;
long long x = 0, y = 0, area = 0;
while (cin >> s)
{
x = y = area = 0;
long long len = s.size();
for (int i = 0; i < s.size(); i++)
{
int dir = s[i] - '0';
long long tx = x + dirx[dir];
long long ty = y + diry[dir];
//tx和ty表示从第0个点到当前点的向量
//x和y表示从第0个点到当前点的上一个点的向量
area += x * ty - y * tx;
//area是2S的值,也就是每次求的不是三角形的面积,而是平行四边形的面积
x = tx;
y = ty;
}
area = abs(area);//面积最后求出来会有正有负,只需要得到他们的绝对值即可
cout << (area + len) / 2 + 1 << endl;//Pick定理
}
return 0;
}