题解
- 皮克定理:给定顶点座标均是整点的简单多边形,其面积和内部格点数目、边上格点数目满足关系:
- 边上点的个数为 gcd(abs(p[i-1].x-p[i].x),abs(p[i-1].y-p[i].y))(只包括一个端点的)。
- 这题不能pick定理求面积,而是先求出面积再用pick定理反推内部点的个数
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
double const eps = 1e-8;
int const N = 100 + 10;
int n,I,E;
double A;
int x,y;
typedef struct Point{ //点和向量
int x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point operator - (const Point& e)const{ //减
return Point(x - e.x,y - e.y);
}
double operator ^ (const Point& e)const{ //叉乘
return x * e.y - y * e.x;
}
}Vector;
Point p[N];
double getarea(){
int ans = 0;
for(int i=1;i<n-1;i++)
ans += ((p[i] - p[0]) ^ (p[i+1] - p[0]));
return (double)ans / 2;
}
int main(){
int T,caser = 0;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
p[0] = Point(0,0);
E = 0;
for(int i=1;i<=n;i++){
int dx,dy;
scanf("%d%d",&dx,&dy);
if(i != n){
p[i] = Point(p[i-1].x + dx,p[i-1].y + dy); //最后一点为第一个点,没必要添加,共有0--n-1的点
E += __gcd(abs(p[i-1].x-p[i].x),abs(p[i-1].y-p[i].y));
}else E += __gcd(abs(p[n-1].x-p[0].x),abs(p[n-1].y-p[0].y));
}
double A = getarea();
I = (A + 1 - E / 2);
printf("Scenario #%d:\n",++caser);
printf("%d %d %.1f\n",(int)I,(int)E,A);
cout<<endl;
}
return 0;
}