poj2954 Triangle【Pick定理】

来源:互联网 发布:查看java jdk版本 编辑:程序博客网 时间:2024/05/22 13:39

题目大意:

给你一个由3个整点构成的三角形,要你求出该三角形内部的整点个数.

解题思路:

用了一个非常神奇的小定理:Pick定理。
由Pick定理,一个多边形如果每个顶点都由整点构成,该多边形的面积为S,该多边形边上的整点为L,内部的整点为N,则有:2S=2N+L-2。
那么我们要求的N即为(2S+2-L)/2。

S可由向量叉积得到,关键是求三角形各边上有多少个整点。
假设有一条由两个整点构成的线段,该线段该线段X方向的增量绝对值为DX, Y方向的增量绝对值为DY. 设线段内部(不含端点)整点个数为ans:
DX=DY=0时, ans=0
DX=0时, ans=DY-1(等价于gcd(DX,DY)-1 )
DY=0时, ans=DX-1 (等价于gcd(DX,DY)-1 )
DX!=0且DY!=0时, ans=gcd(DX,DY)-1

PS:poj编译器太老了,bits不能用,读入优化也会出问题。

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#define ll long longusing namespace std;const int N=100005;struct point{    int x,y;    point(){}    point(int _x,int _y):x(_x),y(_y){}    inline friend point operator - (const point &a,const point &b)    {return point(a.x-b.x,a.y-b.y);}    inline friend int operator * (const point &a,const point &b)    {return a.x*b.y-a.y*b.x;}};int gcd(int a,int b){    return b?gcd(b,a%b):a;}int calc(point a){    if(!a.x&&!a.y)return 0;    return gcd(abs(a.x),abs(a.y))-1;}int main(){    //freopen("lx.in","r",stdin);    point a,b,c;    while(scanf("%d%d%d%d%d%d",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y))    {        if(!a.x&&!a.y&&!b.x&&!b.y&&!c.x&&!c.y)break;        int S=abs((c-a)*(b-a));        int num=calc(a-b)+calc(a-c)+calc(b-c)+3;        cout<<(S+2-num)/2<<'\n';    }    return 0;}
原创粉丝点击