PICK定理及其证明(转)

本文介绍了皮克定理,该定理阐述了顶点坐标均为整数的简单多边形的面积与其内部和边界上的格点数量之间的关系。通过逐步证明,首先验证矩形和由矩形衍生的直角三角形满足此定理,进而推广到所有简单多边形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定顶点座标均是整点(或正方形 格点 )的简单多边形 皮克定理 说明了其面积 A 和内部格点数目i 、边上格点数目b 的关系:A = i + b /2 - 1。

 

证明

因为所有简单多边形都可切割为一个三角形 和另一个简单多边形。考虑一个简单多边形P ,及跟P 有一条共同边的三角形T 。若P 符合皮克公式,则只要证明P 加上TPT 亦符合皮克公式(I),与及三角形符合皮克公式(II),就可根据数学归纳法 ,对于所有简单多边形皮克公式都是成立的。

多边形

PT 的共同边上有c 个格点。

  • P 的面积: iP + bP /2 - 1
  • T 的面积: iT + bT /2 - 1
  • PT 的面积:
(iT + iP + c - 2) + (bT - c + 2 + bP - c + 2 ) /2 - 1
= iPT + bPT /2 - 1

三角形

证明分三部分:证明以下的图形符合皮克定理:

  1. 所有平行于轴线的矩形;
  2. 以上述矩形的两条邻边和对角线组成的直角三角形;
  3. 所有三角形(因为它们都可内接于矩形内,将矩形分割成原三角形和至多3个第二点提到的直角三角形)。

矩形

设矩形R 长边短边各有m ,n 个格点:

  • AR = (m -1)(n -1)
  • iR = (m -2)(n -2)
  • bR = 2(m+n)-4
iR + bR /2 - 1
= (m -2)(n -2) + (m+n) - 2 - 1
= mn - (m + n ) +1
= (m -1)(n -1)

直角三角形

易见两条邻边和对角线 组成的两个直角三角形全等,且i ,b 相等。设其斜边上有c 个格点。

  • b = m +n +c -3
  • i = ((m -2)(n -2) - c + 2)/2
i + b /2 - 1
= ((m -2)(n -2) - c + 2)/2 + (m +n +c -3)/2 - 1
= (m -2)(n -2)/2 + (m +n - 3)/2
= (m -1)(n -1)/2

一般三角形

推广

  • 取格点的组成图形的面积为一单位。在平行四边形 格点,皮克定理依然成立。套用于任意三角形格点,皮克定理则是A = 2i + b - 2。
  • 对于非简单的多边形P ,皮克定理A = i + b /2 - χ(P),其中χ(P )表示P 的欧拉特征数 。
  • 高维推广:Ehrhart多项式 ;一维:植树问题。
  • 皮克定理和欧拉公式(V-E+F=2)等价。
Pick定理用于计算简单多边形的面积,特别适用于格点多边形(顶点都在整数坐标点上的多边形)。Pick定理公式如下: $$ A = I + \frac{B}{2} - 1 $$ 其中: - $ A $ 是多边形的面积; - $ I $ 是多边形内部的格点数; - $ B $ 是多边形边界上的格点数。 根据引用[^1],提供了一段实现Pick定理的C++代码。该程序读取多边形顶点坐标,计算多边形的面积、边界上的格点数 $ B $,以及内部格点数 $ I $(通过 Pick 定理反推)。 以下是实现Pick定理的代码解析: 1. **结构体定义**: 定义了一个 `node` 结构体来存储每个顶点的坐标。 ```cpp struct node { int x; int y; } point[maxn]; ``` 2. **最大公约数计算**: 使用 `gcd` 函数计算两个数的最大公约数,用于统计边界上的格点数。 ```cpp int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } ``` 3. **计算多边形面积**: 使用叉积计算多边形的面积。 ```cpp double getArea(node a, node b) { return a.x * b.y - a.y * b.x; } ``` 4. **主函数逻辑**: - 读取输入数据; - 计算每条边上的格点数; - 利用叉积计算多边形的总面积; - 应用Pick定理反推出内部格点数 $ I $。 完整代码如下: ```cpp #include <iostream> #include <cstdio> #include <cmath> #include <stdlib.h> #include <cstring> using namespace std; #define maxn 107 struct node { int x; int y; } point[maxn]; int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } double getArea(node a, node b) { return a.x * b.y - a.y * b.x; } int main() { int T, n; double area; int total, dx, dy; scanf("%d", &T); for (int num = 1; num <= T; num++) { scanf("%d", &n); area = 0, total = 0; point[0].x = 0, point[0].y = 0; for (int i = 1; i <= n; i++) { scanf("%d%d", &point[i].x, &point[i].y); dx = abs(point[i].x); dy = abs(point[i].y); total += gcd(dx, dy); point[i].x += point[i-1].x; point[i].y += point[i-1].y; area += getArea(point[i], point[i-1]); } if (area < 0) area = -area; printf("Scenario #%d:\n", num); printf("%d %d %.1f\n\n", (int)(area / 2 - total / 2 + 1), total, area / 2); } return 0; } ``` 在上述代码中: - `total` 表示边界上的格点数 $ B $; - `(int)(area / 2 - total / 2 + 1)` 表示通过 Pick 定理计算出的内部格点数 $ I $; - `area / 2` 表示多边形的实际面积 $ A $。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值