POJ2954 Triangle
http://poj.org/problem?id=2954
题意
给你一个由3个整点构成的三角形,要你求出该三角形内部的整点个数。
输入
输入至文件结束,每组6个整数,表示3个顶点的坐标。
输出
每组输出对应一个整数,表示三角形内部的整点个数。
样例输入
0 0 1 0 0 1
0 0 5 0 0 5
0 0 0 0 0 0
样例输出
0
6
分析
https://blog.csdn.net/u013480600/article/details/39269265
由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!=0且DY!=0时, ans=gcd(DX,DY)-1
简单说明一下上面结论:
端点是整点的线段内部如果有整点, 那线段一定是被内部的整点均匀分割的.
假设线段内部有5个整点(这5个整点一定是均匀排列的),那么包括两端点共7个整点,线段被分成了6等份. 其实就是DX和DY分别被分成了6等份,那么说明DX和DY的最大公约数==6. 如果DX与DY的最大公约数==8,那么线段一定且最多能被分成8等份,且由于线段端点是整点,所以8等份的每个点都是整点。
C++程序
#include<iostream>
#include<cmath>
using namespace std;
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
//矢量减法
Point operator -(const Point &a)const
{
return Point(x-a.x,y-a.y);
}
//叉积
double operator ^(const Point &a)const
{
return x*a.y-y*a.x;
}
};
int gcd(int n,int m)
{
return m==0?n:gcd(m,n%m);
}
//计算端点是整点的线段内部的整点个数
int num(Point a,Point b)
{
int n=(int)(fabs(a.x-b.x));
int m=(int)(fabs(a.y-b.y));
if(n==0&&m==0)
return 0;
else
return gcd(n,m)-1;
}
int main()
{
Point a,b,c;
while(~scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y)&&(a.x||a.y||b.x||b.y||c.x||c.y))
{
double s=fabs(((b-a)^(c-a)))/2.0;
int L=3+num(a,b)+num(a,c)+num(b,c);//计算三角形边上的整点个数
int ans=(int)s+1-L/2;
printf("%d\n",ans);
}
return 0;
}