poj 2954 Triangle (pick定理应用)

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84142929

题目链接:bang

题意:给你三个点,每个点的坐标都是整数,问这个三角形内部有多少个整数点?

题解:pick定理解决,至于证明pick定理的,这有一篇强行解释的:

http://blog.sina.com.cn/s/blog_a1c409e30101efme.html

再来一篇强行解释的:

http://www.matrix67.com/blog/archives/768

参考链接:

https://blog.csdn.net/u013480600/article/details/39269265?utm_source=blogxgwz4

这篇博客证明边上有多少个整数点证明得很好。这里就直接不加修饰的搬了。

Pick定理,一个多边形如果每个顶点都由整点构成,该多边形的面积为S,该多边形边上整点为L,内部整点为N,则有:

       N+L/2-1=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!=0DY!=0时, ans=gcd(DX,DY)-1

       简单说明一下上面结论:

       端点是整点的线段内部如果有整点, 那线段一定是被内部的整点均匀分割的.

假设线段内部有5个整点(这5个整点一定是均匀排列的),那么包括两端点共7个整点,线段被分成了6等份. 其实就是DX和DY分别被分成了6等份,那么说明DX和DY的最大公约数==6. 如果DX与DY的最大公约数==8,那么线段一定且最多能被分成8等份,且由于线段端点是整点,所以8等份的每个点都是整点.
 

///pick定理 面积=内部隔点数+边上隔点数/2-1

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

struct point{
    int x,y;
    point(){}
    point(int _x,int _y){
        x=_x;y=_y;
    }
}p[5];

point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,int p) { return point(a.x*p,a.y*p);}
point operator / (point a,int p){ return point(a.x/p,a.y/p);}

bool operator < (const point &a,const point &b){
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-8;
int dcmp(double x){
    if(fabs(x)<esp) return 0;
    else return x<0?-1:1;
}
bool operator ==(const point &a,const point &b){
    return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}


int Cross(point a,point b) { return fabs(a.x*b.y-a.y*b.x);}

int gcd(int a,int b){
    if(!b) return a;
    else return gcd(b,a%b);
}

int solve(point a,point b){ ///求解ab边上不包括端点的整点个数
    int dx=fabs(a.x-b.x),dy=fabs(a.y-b.y);

    if(dx==0&&dy==0) return 0;
    return gcd(dx,dy)-1;
}

int main()
{
    int x1,x2,x3,y1,y2,y3;

    while(~scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3))
    {
        if(x1==0&&x2==0&&x3==0&&y1==0&&y2==0&&y3==0) break;

        p[0]=point(x1,y1);
        p[1]=point(x2,y2);
        p[2]=point(x3,y3);

        int area=Cross(p[1]-p[0],p[2]-p[0])/2; ///叉积求面积

        int edgenode=3+solve(p[0],p[1])+solve(p[0],p[2])+solve(p[1],p[2]);

        printf("%d\n",area+1-edgenode/2); ///pick定理


    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/84142929