POJ 1265 Area (Pick定理)

题意:

求多边形边上的顶点数,多边形内部的顶点数,多边形的面积。

题解:Pick定理:http://episte.math.ntu.edu.tw/articles/sm/sm_25_10_1/index.html

定理一:Pick 定理,1899年
设Γ 为平面上以格子点为顶点之单纯多边形,则其面积为 

\begin{displaymath} A=\frac{b}{2}+i-1\eqno{(8)} \end{displaymath}

其中 b为边界上的格子点数, i为内部的格子点数。(8)式叫做Pick公式。

在上述证明中,单纯多边形经过原子化后,成为一个连通的平面图枝(a connected plane graph)。著名的尤拉(Euler) 公式告诉我们,对于任何连通的平面图枝(不限于格子点图枝)恒有: 

\begin{displaymath}V-E+F=2\eqno{(9)}\end{displaymath}

其中 V 表示图枝的顶点(vertices)个数(即 V = b + i ), E 表示棱线(edges)的个数, F 表示平面被图枝分割所成的块数(其中最外的一块是无界的)。例如,在图十六中, V =20  ,  E =49  ,  F =31

因为每一个原子三角形的面积为$\frac{1}{2}$,并且总共有F -1个,所以原来单纯多边形的面积为: 

\begin{displaymath} A=\frac{1}{2}(F-1)\eqno{(10)} \end{displaymath}

由尤拉公式与 V = b + i 得到: 

\begin{displaymath} A=\frac{1}{2}-\frac{b}{2}-\frac{i}{2}+\frac{E}{2}\eqno{(11)} \ end{displaymath}

再由Pick 公式,可知: 

\begin{displaymath} \frac{1}{2}-\frac{b}{2}-\frac{i}{2}+\frac{E}{2}=\frac{b}{2}+ i-1 \end{displaymath}

于是我们得到棱线的个数为: 

\begin{displaymath} E=2b+3i-3\eqno{(12)} \end{displaymath}

事实上,这个公式对于一般连通的三角形化的平面图枝(不限于格子点图枝)都成立。

定理二:(棱线定理,Edge Theorem)
对于任意连通的三角形化的平面图枝,其棱线的个数恒为 

\begin{displaymath}E=2b+3i-3\eqno{(13)}\end{displaymath}

其中 bi分别表示图枝边界上的顶点数与内部的顶点数。

证明: 我们分成三个步骤:

(i)最简单的情形是 b =3i =0,图枝只含一个三角形,此时 E =3,故公式(13)成立。
(ii)若在三角形的内部增加一个顶点,则 E增加3。此时(13)式也成立。
(iii)假设一个连通的三角形化的平面图枝满足(13)式(即 E =2 b +3 i -3),今在其外部增加一个新的边界顶点,使得原来图枝的边界顶点有 m个变成内部顶点( m可能等于0),则 E增加 m +2。于是由 E =2 b +3 i-3得: 

E + m +2=2( b +1- m )+3( i + m )-3

换言之,对于新的图枝而言,(13)式仍然成立。按数学归纳法,我们就证明了(13)式。

由棱线定理与尤拉公式,我们也可以推导出Pick 定理,这就是下面要介绍的Pick 定理之第二种证法:

根据V = b + i , E =3 i +2 b -3 , V - E + F =2,以及面积 $A=\frac{1}{2}(F-1)$,立即可算得: 

\begin{displaymath} A=\frac{b}{2}+i-1 \end{displaymath}
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>

struct Point { double x, y; };
Point p[1000];

double area ( Point p1, Point p2 )
{
    return p1.x * p2.y - p2.x * p1.y;
}

int gcd ( int x, int y )
{
    int tmp;
    if ( x < 0 ) x = -x;
    if ( y < 0 ) y = -y;
    if ( x < y ){ tmp = x; x = y; y = tmp; }
    while ( y ){tmp = y; y = x % y; x = tmp;}
    return x;
}

int main()
{
    double s;
    int t, n, I, E, dx, dy;
    scanf("%d",&t);
    for ( int k = 1; k <= t; k++ )
    {
        scanf("%d",&n );
        s = p[0].x = p[0].y = 0; E = 0;
        for ( int i = 1; i <= n; i++ )
        {
            scanf("%d%d",&dx,&dy);
            p[i].x = p[i-1].x + dx;
            p[i].y = p[i-1].y + dy;
            s += area ( p[i-1], p[i] );
            if ( dx == 0 || dy == 0 ) E += abs(dx+dy);
            else E += gcd(dx,dy);
         }
         s = fabs(s) / 2;
        I = (int)(s+1-E/2);
        printf("Scenario #%d:\n",k);
        printf("%d %d %.1lf\n\n",I,E,s);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值