POJ 1265 Area (皮克公式)

版权声明:欢迎神犇指教 https://blog.csdn.net/sdxtcqs/article/details/87967260

http://poj.org/problem?id=1265
题意:一机器人从原点出发进行 n n 次移动,每次向右移动 d x i dx_i ,向上移动 d y i dy_i ,求其路线(不含原点)画成的多边形内部有多少格点,边界上有多少格点,及其面积多大。

Pick公式
对于顶点坐标均为整数的简单多边形:
= + / 2 1 面积=内部格点数目+边界格点数目/2-1
边界格点数目
把每条边当做左开右闭区间以避免重复,一条左开右闭的线段(x1,y1)->(x2,y2)上格点数为:
g c d ( x 2 x 1 , y 2 y 1 ) 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;
}

猜你喜欢

转载自blog.csdn.net/sdxtcqs/article/details/87967260