poj 1265 Area【计算几何:叉积计算多边形面积+pick定理计算多边形内点数+计算多边形边上点数】

题目:http://poj.org/problem?id=1265

Sample Input

2
4
1 0
0 1
-1 0
0 -1
7
5 0
1 3
-2 2
-1 0
0 -3
-3 1
0 -3

Sample Output

Scenario #1:
0 4 1.0

Scenario #2:
12 16 19.0

注意:题目给出的成对的数可不是坐标,是在x和y方向走的数量。


边界上的格点数:一条左开右闭的线段(x1, x2)->(x2, y2)上的格点数为:gcd( abs(x2-x1), abs(y2-y1) );
Pick公式:对于给定的坐标都是整点的简单多边形,有如下等式:
多边形面积=多边形内部格点数+边上的格点数/2 - 1; 由此可以推出如何计算多边形内部的格点数量!
当然这需要知道多边形的面积,计算多边形的面积:顺时针或逆时针相邻两点分别与原点构成的向量的叉积累加和,再取绝对值,再除2
(因为顺逆方向的问题,可能会导致叉积累加和为负,又因为叉积计算的是向量围成的四边行的面积所以还要除2)

代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

struct node
{
    int x;
    int y;
}q[110];

int cal_area(node a, node b)
{
    return a.x*b.y-a.y*b.x;
} //叉积计算两个向量的面积

int gcd(int a, int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int tg; scanf("%d", &tg);
    int n;
    int i, j;
    for(int cnt=1; cnt<=tg; cnt++){
        scanf("%d", &n);
        q[0].x=0; q[0].y=0; //这是坐标原点

        int p_on_l=0; //point on line

        for(i=1; i<=n; i++){
           scanf("%d %d", &q[i].x, &q[i].y );
           //先计算线段上的点数
           int dx=abs(q[i].x);
           int dy=abs(q[i].y);
           p_on_l+=gcd(dx, dy);

           q[i].x+=q[i-1].x;
           q[i].y+=q[i-1].y; //题目中给出的是前一个点在x y方向上行走的数量
        }                    //只要累加就可以计算出i节点的坐标
        //所有点的坐标计算完毕
        int area=0;
        for(i=2; i<=n; i++){
            area+=cal_area(q[i], q[i-1]);
        }
        area=abs(area); //多边行的面积一定大于等于0 如果求出的结果为负值
                        //说明叉积计算的方向是和正值计算相比是反的
        double ans=area/2.0;//叉积计算的是平行四边行的面积 不是三角形 面积要减半

        printf("Scenario #%d:\n", cnt);
        printf("%d %d %.1lf\n", (area/2+1-p_on_l/2), p_on_l, ans);
        printf("\n");
    }
    return 0;
}

 


posted @ 2015-08-10 10:39  我喜欢旅行  阅读(304)  评论(0编辑  收藏  举报