zoukankan      html  css  js  c++  java
  • poj1265&&2954 [皮克定理 格点多边形]【学习笔记】

    Q:皮克定理这种一句话的东西为什么还要写学习笔记啊?

    A:多好玩啊...

    PS:除了蓝色字体之外都是废话啊...


     Part I

    1.顶点全在格点上的多边形叫做格点多边形(坐标全是整数)

    2.维基百科

    Given a simple polygon constructed on a grid of equal-distanced points (i.e., points with integer coordinates) such that all the polygon's vertices are grid points, Pick's theorem provides a simple formula for calculating the area A of this polygon in terms of the number i of lattice points in the interior located in the polygon and the number b of lattice points on the boundary placed on the polygon's perimeter:[1]

     

    A=i+{frac {b}{2}}-1.

    3.看不懂英文?

    S=a+b/2-1,其中a表示多边形内部的点数,b表示多边形边界上的点数,s表示多边形的面积。

    证明:

    1.先证明直角三角形和矩形 在逆用证明任意三角形,归纳法证明任意多边形

    2.

    From:http://www.matrix67.com/blog/archives/768

    最酷的证明:Pick定理另类证法

        难以想像,一段小小的证明竟然能比一个瘦小的留着长头发穿黑色短袖T恤紧身牛仔裤边跳边弹吉他的MM还要酷。原来一直以为这个证明已经很酷了,现在显然我已经找到了一个更酷的证明。
        Pick定理是说,假设平面上有一个顶点全在格点上的多边形P,那么其面积S(P)应该等于i+b/2-1,其中i为多边形内部所含的格点数,b是多边形边界上的格点数。绝大多数证明都是用割补的办法重新拼拆多边形。这里,我们来看一个另类的证明。
        假设整个平面是一个无穷大的铁板;在0时间,每个格点上都有一个单位的热量。经过无穷长时间的传导后,最终这些热量将以单位密度均匀地分布在整个铁板上。下面我们试着求多边形P内的热量。考虑多边形的每一条线段e:它的两个端点均在格点上,因此线段e的中点是整个平面格点的对称中心,因而流经该线段的热量收支平衡(这半边进来了多少那半边就出去了多少),即出入该线段的热量总和实际为0。我们立即看到,P的热量其实完全来自于它自身内部的i个格点(的全部热量),以及边界上的b个格点(各自在某一角度范围内传出的热量)。边界上的b个点形成了一个内角和为(b-2)*180的b边形,从这b个点流入P的热量为(b-2)*180/360 = (b-2)/2 = b/2-1。再加上i个内部格点,于是S(P)=i+b/2-1。

    Part II

    一条端点在格点上的线段覆盖的点数:

    gcd(dx,dy) dxdy分别为线段横向占的点数和纵向占的点数

    证明:自己随便想想就知道了,和这道题的思想有点像:http://www.cnblogs.com/candy99/p/6074673.html


     

    于是就可以做裸题了....

    POJ 2954 三角形内部格点数

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N=105;
    const double eps=1e-8;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    inline int sgn(double x){
        if(abs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    struct Vector{
        int x,y;
        Vector(int a=0,int b=0):x(a),y(b){}
    };
    typedef Vector Point;
    Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
    int Cross(Vector a,Vector b){
        return a.x*b.y-a.y*b.x;
    }
    
    int n,x,y,x2,y2,x3,y3,b,s;
    int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
    int main(int argc, const char * argv[]){
        while(scanf("%d",&x)!=EOF){
            y=read();x2=read();y2=read();x3=read();y3=read();
            if(!x&&!y&&!x2&&!y2&&!x3&&!y3) break;
            b=s=0;
            b=gcd(abs(x2-x),abs(y2-y))+gcd(abs(x3-x2),abs(y3-y2))+gcd(abs(x3-x),abs(y3-y));
            s=abs(Cross(Vector(x2-x,y2-y),Vector(x3-x,y3-y)));
            printf("%d
    ",(s-b+2)/2);
        }
        
        return 0;
    }

    POJ1265 给一个平面上的简单多边形,求边上的点,多边形内的点,多边形面积。

     

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N=105;
    const double eps=1e-8;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    inline int sgn(double x){
        if(abs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    struct Vector{
        int x,y;
        Vector(int a=0,int b=0):x(a),y(b){}
    };
    typedef Vector Point;
    Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
    int Cross(Vector a,Vector b){
        return a.x*b.y-a.y*b.x;
    }
    
    int n,x,y,b,s;
    Point poly[N];
    int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
    int main(int argc, const char * argv[]){
        int T=read(),cas=0;
        while(T--){
            b=s=0;
            n=read();
            for(int i=1;i<=n;i++){
                x=read();y=read();
                b+=gcd(abs(x),abs(y));
                poly[i]=poly[i-1]+Point(x,y);
                s+=Cross(poly[i],poly[i-1]);
            }
            s=abs(s);
            printf("Scenario #%d:
    ",++cas);
            printf("%d %d %.1f
    
    ",(s+2-b)/2,b,0.5*s);
        }
        
        return 0;
    }
  • 相关阅读:
    树莓派系统安装初始化
    CentOS7搭建配置SVN服务器
    搭建web定时任务管理平台
    Linux 内存清理
    使用kubeadm安装Kubernetes
    Web页面执行shell命令
    解决"libc.so.6: version `GLIBC_2.14' not found"问题
    crontab 任务带日期输出
    Linux 源码安装 Python3
    MongoDB 数据恢复与导出
  • 原文地址:https://www.cnblogs.com/candy99/p/pick.html
Copyright © 2011-2022 走看看