POJ1265:pick定理

POJ1265

题解

  • 皮克定理:给定顶点座标均是整点的简单多边形,其面积A和内部格点数目i、边上格点数目b满足关系:{\displaystyle A=i+{\frac {b}{2}}-1}
  • 边上点的个数为 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/89022653