hiho一下 第125周 GeoHash一·编码解码

题目1 : GeoHash一·编码解码

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

小Hi:上一次我们讲到了在一个城市里,利用四叉树来查找一个坐标附近的点。假如我们把范围扩大到整个地球呢?

小Ho:扩大到整个地球,那坐标怎么办?

小Hi:坐标的话,我们就用经纬度好了。纬度从-90°到90°,经度从-180°到180°。

小Ho:四叉树里面我们用的都是整数坐标,如果变成实数坐标感觉就不那么容易了。

小Hi:没错,而且在扩展到全球的情况下,可以预见点数也会变得非常巨大。因此用四叉树来存储这么多点显然不太现实。

小Ho:那有什么好一点的方法么?

小Hi:当然有了,这一次我们采用编码的方式来解决。

提示:geohash

输入

第1行:2个整数N,M。1≤N,M≤100。

第2..N+1行:每行2个实数x,y,第i+1行表示第i个点的纬度和经度。-90≤x≤90,-180≤y≤180

第N+2..N+M+1行:每行1个字符串,表示需要解码的geohash代码

输出

第1..N行:每行1个字符串,第i行表示以第i个点的geohash编码,长度为10。

第N+1..N+M行:每行2个实数x,y,第N+i行表示以第i个geohash编码所表示的区域中心点坐标,保留6位小数。

样例输入
3 2
36.255833 117.103367
27.293056 112.688922
34.477861 110.082600
wx0csn0ng82y
ww0k7k0et784
样例输出
ww7q2b0jd1
wsb5k299d4
wqnk0ux8n7
39.672792 113.730620
34.519663 112.995297
#include<bits/stdc++.h>
using namespace std;


char Base32[]=
{
    '0','1','2','3','4','5','6','7','8','9','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z'
};

string encode(double latt,double lonn,int precision)
{
    double lat[]= {-90,90};
    double lon[]= {-180,180};
    int len =precision*5;
    string geohash;
    int bits=0;
    for(int i=1; i<=len; i++)
    {
        if (i&1)
        {
            double mid=(lon[0]+lon[1])/2;
            if (lonn>mid)
                bits=bits<<1|1,lon[0]=mid;
            else
                bits<<=1,lon[1]=mid;
        }
        else
        {
            double mid=(lat[0]+lat[1])/2;
            if (latt>mid)
                bits=bits<<1|1,lat[0]=mid;
            else
                bits<<=1,lat[1]=mid;
        }
        if (i%5==0)
            geohash+=Base32[bits],bits=0;
    }
    return geohash;

}
int indexofBase32(char s)
{
    return lower_bound(Base32,Base32+32,s)-Base32;
}
void decode(char  s[],double &x,double&y)
{
    bool odd=1;
    double lat[]= {-90,90};
    double lon[]= {-180,180};
    double mid;
    int len=strlen(s);
    for(int i=0; i<len; i++)
    {

        int bits=indexofBase32(s[i]);
        for(int j=4; j>=0; j--)
        {
                int bit=(bits>>j)&1;
            if (odd&1)
            {
                mid=(lon[0]+lon[1])/2;
                lon[1-bit]=mid;
            }
            else
            {
                mid=(lat[0]+lat[1])/2;
                lat[1-bit]=mid;
            }
            odd^=1;
        }
    }
    x=(lat[0]+lat[1] )/2;
    y=(lon[0]+lon[1] )/2;
}
int main()
{
    double x,y;
    int n,m;
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        scanf("%lf%lf",&x,&y);
        string ret=encode(x,y,10);
        printf("%s\n",ret.c_str());
    }
    char ss[15];
    for(int i=1; i<=n; i++)
    {
        scanf("%s",ss);
        decode(ss,x,y);
        printf("%.6lf %.6lf\n",x,y);
    }


}


 

geohash简介: geohash是一种地址编码,它能把二维的经纬度编码成一维的字符串。geohash有以下几个特点: 首先,geohash用一个字符串表示经度和纬度两个坐标。某些情况下无法在两列上同时应用索引 (例如MySQL 4之前的版本,Google App Engine的数据层等),利用geohash,只需在一列上应用索引即可。 其次,geohash表示的并不是一个点,而是一个矩形区域。比如编码wx4g0ec19,它表示的是一个矩形区域。 使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。 第三,编码的前缀可以表示更大的区域。例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。 这个特性可以用于附近地点搜索。首先根据用户当前坐标计算geohash(例如wx4g0ec1)然后取其前缀进行查询 (SELECT * FROM place WHERE geohash LIKE 'wx4g0e%'),即可查询附近的所有地点。Geohash比直接用经纬度的高效很多。用途: 移动互联网,lbs可以说是一个基础应用,geohash对于解决附近地点搜索提供了一个有效的解决方案。扩展: 这个php扩展,提供了三个函数:/**     *  $latitude    //纬度     *  $longitude   //经度     *  $precision   //精密度, 默认是12     *  返回 $precision 长度的 string     */    geohash_encode($latitude, $longitude, $precision=12);      /**     *  $hash    //geohash_encode后的值     *  返回 array // Array     *                    (     *                        [latitude] => 39.416916975752     *                        [longitude] => 100.92223992571     *                        [north] => 39.416917059571     *                        [east] => 100.92224009335     *                        [south] => 100.92223992571     *                        [west] => 100.92223975807     *                    )     */    geohash_decode($hash);    /**     *  $hash    //geohash_encode后的值     *  返回 在$hash 8个 (东南西北各二个)附近的hash值     */    geohash_neighbors($hash); 标签:geohash
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值