poj 1265 Area

/*

题意: 求逆时针顺序的顶点为整点的简单多边形边面积A, 其边上的格点数, 内部的格点数。 

Pick定理:A = I + E/ 2 - 1(前提为顶点为整数)

一开一闭区间(x1, y1)-> (x2, y2)的上的格子点数为 gcd(|x1 - x2|, |y1 - y2|);

然后就可以水了, G++输出“%.1f”   C++输出 “%.1lf” 不然就会WA

*/


#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#define MAX 1005
#include <complex>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <string>
#define INF 1e8
#define MAX (int)1e6+ 5
using namespace std;
inline int gcd(int a, int b){ return !b? a : gcd(b, a % b);}
struct Point
{
  int x, y;
  Point(){}
  Point(int xx , int yy):x(xx), y(yy){}
  Point operator - ( const Point &a)const {
    return Point(x - a.x, y - a.y);
  }
  friend int det(const Point &a, const Point &b){
    return a.x * b.y - a.y * b.x;
  }
  void in(){ scanf("%d %d", &x, &y);}
  void out(){cout<<x<<" "<<y<<endl;}
};
struct Polygon{
    vector<Point>p;//anti-clockwis
    int E, I;
    double A;
    Polygon(){}
    Polygon(const vector<Point> &a):p(a){ }
    void caAEI(){
        int n = p.size();
        A = 0;
        E = 0;
        #define next(i) ( (i + 1) % n)
        for(int i = 0; i < n; i++){
            int ni = next(i);
            A += det(p[i], p[ni]);
            E += gcd(abs(p[i].x - p[ni].x), abs(p[i].y - p[ni].y) );
        }
         A /= 2.0;//pick定理, A = I + E/2 - 1;
         I = (int)(A + 1 - E/ 2.0);
    }
    void out(){
        printf("%d %d %.1f\n", I, E, A);
    }
};
int T, n;
int main()
{
    cin>>T;
    int ca = 0;
    while(T--){
        cin>>n;
        vector<Point>temp;
        Point now(0, 0), dir;
        for(int i = 0; i < n; i++){
            dir.in(); dir = Point(0, 0) - dir;
            now = now - dir;
            temp.push_back(now);
        }
        Polygon pg(temp);
        pg.caAEI();
        printf("Scenario #%d:\n", ++ca);
        pg.out();
        cout<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值