😎皮克定理:
S:多边形面积 ——累加叉积/2
I:多边形内部点数
E:多边形边上的点数——每次求出端点的最大公约数,其他约数构成最小子增加,最大公约数就是可以放大多少次,就是新增的点数,
每次起点不计,终点计入,因为是封闭多边形,所以最开始的起点是最后的终点
#include <iostream>
#include <math.h>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Point{
int x,y;
Point(int x=0,int y=0):x(x),y(y){
};
Point operator-(Point b){return Point(x-b.x,y-b.y);
}
double operator^(Point b){return x*b.y-y*b.x;
}
Point operator+(Point b){return Point(x+b.x,y+b.y);
}
};
const int N=105;
Point point[N];
int t,m,xx,yy;
int I,e;
double s;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
double calArea(){
double area=0;
for(int i=0;i<m;i++){
area+=(point[i]^point[(i+1)%m])/2;//用公式叉积/2求出面积
}
return fabs(area);//逆时针为正,顺时针为负,为防止负求绝对值
}
int main() {
scanf("%d",&t);
for(int i=1;i<=t;i++){
s=I=e=0;
scanf("%d",&m);//输入运动数
for(int j=0;j<m;j++){
scanf("%d%d",&xx,&yy);//输入运动方案
point[j].x=xx;point[j].y=yy;//如果为第一次,直接记录xx,yy位置
if(j) point[j]=point[j-1]+Point(xx,yy);//不是第一次在前一次基础上运动
e+=gcd(abs(xx),abs(yy));//记住abs ,此处为一次运动新增点数
}
s=calArea();//计算面积
I=(int)s+1-e/2;//计算内部点数,皮克定理
printf("Scenario #%d:\n%d %d %.1f\n\n",i,I,e,s);
}
return 0;
} 
京公网安备 11010502036488号