😎皮克定理:
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; }