S=a+ b/2 - 1
(其中a表示多边形内部的点数,b表示多边形边界上的点数,S表示多边形的面积)
其实这个公式主要是用来求a的,s可由叉积得出,b可由gcd求出。
pick公式无比牛逼证明(感谢ldl提供出处)
Pick定理是说,假设平面上有一个顶点全在格点上的多边形P,那么其面积S(P)应该等于i+b/2-1,其中i为多边形内部所含的格点数,b是多边形边界上的格点数。绝大多数证明都是用割补的办法重新拼拆多边形。这里,我们来看一个另类的证明。
假设整个平面是一个无穷大的铁板;在0时间,每个格点上都有一个单位的热量。经过无穷长时间的传导后,最终这些热量将以单位密度均匀地分布在整个铁板上。下面我们试着求多边形P内的热量。考虑多边形的每一条线段e:它的两个端点均在格点上,因此线段e的中点是整个平面格点的对称中心,因而流经该线段的热量收支平衡(这半边进来了多少那半边就出去了多少),即出入该线段的热量总和实际为0。我们立即看到,P的热量其实完全来自于它自身内部的i个格点(的全部热量),以及边界上的b个格点(各自在某一角度范围内传出的热量)。边界上的b个点形成了一个内角和为(b-2)*180的b边形,从这b个点流入P的热量为(b-2)*180/360 = (b-2)/2 = b/2-1。再加上i个内部格点,于是S(P)=i+b/2-1。
原文见http://www.matrix67.com/blog/archives/768。实际上就是复制过来的一模一样的。
poj 2954
#include <cstdio>
#include <cstdlib>
struct point
{
long long x, y;
};
point a[10];
long long ans;
long long sora(struct point x,struct point y,struct point z)
{
long long tot1;
tot1=(x.x*y.y)-(x.y*y.x)+(y.x*z.y)-(y.y*z.x)+(z.x*x.y)-(z.y*x.x);
tot1=abs(tot1);
return tot1;
}
long long gcd(long long a,long long b)
{
if (a<b)
{
long long e=a;a=b,b=e;
}
long long t=a%b;
for (;t!=0;)
{
a=b;
b=t;
t=a%b;
}
return b;
}
long long po(struct point x,struct point y)
{
if (x.x==y.x) return (abs(x.y-y.y)+1);
if (x.y==y.y) return (abs(x.x-y.x)+1);
long long x1=abs(x.x-y.x),y1=abs(x.y-y.y);
long long tot1=gcd(x1,y1)+1;
return tot1;
}
void init()
{
long long tot,ans1;
tot=sora(a[1],a[2],a[3]);
ans1=(po(a[1],a[2])+po(a[1],a[3])+po(a[2],a[3])-3);
ans=tot+2-ans1;
printf("%d\n",ans/2);
}
int main()
{
freopen("2954.in","r",stdin);
freopen("2954.out","w",stdout);
for (;;)
{
scanf("%I64d%I64d%I64d%I64d%I64d%I64d\n",&a[1].x,&a[1].y,&a[2].x,&a[2].y,&a[3].x,&a[3].y);
if ((a[1].x==0)&&(a[1].y==0)&&(a[2].x==0)&&(a[2].y==0)&&(a[3].x==0)&&(a[3].y==0)) break;
init();
}
return 0;
}