http://poj.org/problem?id=1265
题意:一机器人从原点出发进行
n
n
n次移动,每次向右移动
d
x
i
dx_i
dxi,向上移动
d
y
i
dy_i
dyi,求其路线(不含原点)画成的多边形内部有多少格点,边界上有多少格点,及其面积多大。
Pick公式
对于顶点坐标均为整数的简单多边形:
面
积
=
内
部
格
点
数
目
+
边
界
格
点
数
目
/
2
−
1
面积=内部格点数目+边界格点数目/2-1
面积=内部格点数目+边界格点数目/2−1
边界格点数目
把每条边当做左开右闭区间以避免重复,一条左开右闭的线段(x1,y1)->(x2,y2)上格点数为:
g
c
d
(
x
2
−
x
1
,
y
2
−
y
1
)
gcd(x2-x1,y2-y1)
gcd(x2−x1,y2−y1)
然后面积用叉积求得即可。
这里要注意的是POJ的鬼畜评测机,交G++的话面积需要%f才能过,%lf一直WA,交C++的话就随便过。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x=_x;y=_y;
}
Point operator -(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
Point operator +(const Point &b)const
{
return Point(x+b.x,y+b.y);
}
double operator ^(const Point &b)const
{
return x*b.y-y*b.x;
}
};
Point p[110];
int T,n;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main()
{
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
int ans1=0,ans2=0;
double res=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for(int i=1;i<n;i++)
p[i]=p[i-1]+p[i];
for(int i=0;i<n;i++)
ans1+=gcd(abs((int)(p[(i+1)%n].x-p[i].x)),abs((int)(p[(i+1)%n].y-p[i].y)));
for(int i=0;i<n;i++)
res+=(p[i]^p[(i+1)%n])/2;
res=fabs(res);
ans2=int(res)+1-ans1/2;
printf("Scenario #%d:\n%d %d %.1lf\n\n",cas,ans2,ans1,res);
}
return 0;
}