10088:Trees on My Island
問題文
http://uva.onlinejudge.org/external/100/10088.html
単純多角形が与えらる。その中の格子点の数を求めよ。
x,y座標の範囲は絶対値1000000。
ピックの定理を使った。
http://en.wikipedia.org/wiki/Pick%27s_theorem
↑ピックの定理
( 格子点の数 ) = ( 面積 ) - ( 辺上の格子点の数 ) / 2 + 1
辺上の格子点の数は辺の端点をa,bとすると
gcd( abs( a.x - b.x ), abs( a.y - b.y ) ) - 1
で辺ab上の格子点の数を求めることができる。
多角形の面積を求めるのは↓を参考にした。
http://www004.upp.so-net.ne.jp/s_honma/urawaza/area2.htm
#include<cmath> #include<algorithm> #include<iostream> #include<vector> #include<climits> #include<cfloat> #include<cstdio> #define curr(P, i) P[(i) % P.size()] #define next(P, i) P[(i+1) % P.size()] using namespace std; typedef long long ll; double EPS = 1e-10; using namespace std; double add(double a, double b){ if(abs(a+b) < EPS * (abs(a)+abs(b)))return 0; return a+b; } struct point{ double x, y; point(){} point(double x,double y) : x(x) , y(y){} point operator + (point p){return point(add(x,p.x), add(y,p.y));} point operator - (point p){return point(add(x,-p.x), add(y,-p.y));} point operator * (double d){return point(x*d,y*d);} }; double areaPol(vector<point> t){ double area=0; for(int i=0;i<t.size();i++) area+=(curr(t,i).x-next(t,i).x)*(curr(t,i).y+next(t,i).y); return abs(area)/2.0; } int gcd(int a,int b){ if(b==0)return a; return gcd(b,a%b); } ll is_lattice_points_on_line(point a,point b){ return gcd(abs(a.x-b.x),abs(a.y-b.y))-1; } ll pick(vector<point>pol){ double S=areaPol(pol); int b=pol.size(); for(int j=0;j<pol.size();j++) b+=is_lattice_points_on_line(curr(pol,j),next(pol,j)); return S-b/2+1; } int main(void){ int n; while(cin >> n,n){ vector<point>p(n); for(int i=0;i<n;i++)cin >> p[i].x >> p[i].y; cout << pick(p) << endl; } return 0; }