题目链接
题意:
已知一个格点三角形的三个点,问其内部的格点数目。
因坐标范围较大,此题初看很难下手。
但其实就考了一个对Pick定理的应用。
Pick定理:
对于顶点坐标均为整数的简单多边形,皮克定理说明了其面积S和内部格点数目n,边上格点数目s的关系:
S
=
n
+
s
2
−
1
S = n + \frac{s}{2} - 1
S=n+2s−1
对于此题,n就是我们需要求解的量,移项得:
n
=
S
+
1
−
s
2
n = S + 1 - \frac{s}{2}
n=S+1−2s
面积可以直接用叉积求解。
边上格点数目可以利用GCD,因数据保证三角形存在,故无需特判
a
=
=
0
a
n
d
b
=
=
0
a == 0 \space and \space b==0
a==0 and b==0的情况。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int A = 5;
int x[A],y[A];
int gcd(int a,int b){
if(b == 0) return a;
return gcd(b,a%b);
}
int get_S(){return abs((x[2]-x[1])*(y[3]-y[1]) - (x[3]-x[1])*(y[2]-y[1]))/2;}
int get_num(int i,int j){
int a = abs(x[i] - x[j]);
int b = abs(y[i] - y[j]);
return gcd(a,b) - 1;
}
int main(){
while(~scanf("%d%d",&x[1],&y[1])){
for(int i=2 ;i<=3 ;i++) scanf("%d%d",&x[i],&y[i]);
bool flag = 1;
for(int i=1 ;i<=3 ;i++) if(x[i]||y[i]) flag = 0;
if(flag) break;
int S = get_S();
int s = 3 + get_num(1,2) + get_num(2,3) + get_num(1,3);
printf("%d\n",S+1-(s/2));
}
return 0;
}