poj2002 排序+哈希

来源:互联网 发布:北京赛车pk10微信源码 编辑:程序博客网 时间:2024/06/17 01:24
/** * poj 2002 排序+哈希 * 首先要有一个正确的大方向,就是取两个点,利用公式给出另外两个点,并搜索这另外的两个点是否存在 * 大方向有了,首先是确定另外两个点的方法,随意取点,可能组出多个正方形,判断的时候会取多次,这就浪费了很多运算量 * 吸取了别人代码的经验,首先将点先x后y升序排列,然后对于i<j,只考虑yi>=yj的点。有所改进的是,我们这里不需要对xi==xj的情况多做判断,这是因为排序之后,不可能有xi==xj,yi>=yj的情况出现 * 这样,得到两点取另两点的方向就可以放在第一象限方向(正方向)了 * 下面是哈希,其实是就是哈希的原理,只是我是第一次手写哈希的构造和搜索,所以写出来很蹩脚。而且因为最开始,多轮运算之间忘了重新初始化HASH表,WA了好多次 * 既然是第一次写哈希,就把哈希的原理也说一下吧.简单地说,我们用数组索引指向数据,而搜索的时候是用数据查找索引,哈希就是另外构建了一张表,将数据通过函数计算出一个下标,将原数组的索引作为值,以链表的形式存起来 * 对于不可能出现哈希值重复的情况,就不需要使用链表,而像题目中这种情况,肯定会有重复的,就需要用链表来在重复的情况下进行查找。如何将整个数据范围尽量平摊到哈希表长度上,就是哈希函数选取的关键了 * 我这里是随便取的,找了一个素数7993,取((abs(x)+1)*(abs(y)+1))%7993作为哈希函数,还好,344ms就过了 * 这道题好像还有一种二分搜索的做法,我这里就不尝试了 */#include <cstdio>#include <iostream>#include <cstdlib>using namespace std;const int MAX_NUM = 1001;const int PRIME = 7993;struct point{    int x;    int y;} p[MAX_NUM];struct node{    int index;    node* next;    node(){        index = -1;        next = NULL;    }    node(int i){        index = i;        next = NULL;    }};int abs(int i){    return (i>=0) ? i : -1*i;}int cmp(const void* a,const void* b){    point *p1=(point*)a,*p2=(point*)b;    if(p1->x != p2->x){        return p1->x - p2->x;    }    else{        return p1->y - p2->y;    }}bool find(node* hash,int x,int y){    int key = ((abs(x)+1) * (abs(y)+1)) % PRIME;    node *pn;    if(hash[key].index < 0){        return false;    }    else{        pn = &hash[key];        while(pn != NULL){            if(p[pn->index].x == x && p[pn->index].y == y){                return true;            }            else{                pn = pn->next;            }        }        return false;    }}int main(){    int n,res;    scanf("%d",&n);    while(n!=0){        node hash[PRIME];        int key;        node *pp;        for(int i=0;i<n;++i){            scanf("%d%d",&p[i].x,&p[i].y);        }        qsort(p,n,sizeof(point),cmp);        for(int i=0;i<n;++i){            //construct hash table            key = ((abs(p[i].x)+1) * (abs(p[i].y)+1)) % PRIME;            if(hash[key].index == -1){                hash[key].index = i;            }            else{                pp = &hash[key];                while(pp->next != NULL){                    pp = pp->next;                }                pp->next = new node(i);            }        }        res = 0;        int x1,x2,y1,y2,x3,x4,y3,y4,ydiff,xdiff;        for(int i=0;i<n;++i){            x1 = p[i].x;            y1 = p[i].y;            for(int j=i+1;j<n;++j){                if(p[j].y <= p[i].y){                    x2 = p[j].x;                    y2 = p[j].y;                    ydiff = abs(y1-y2);                    xdiff = abs(x1-x2);                    x3 = x1 + ydiff;                    x4 = x2 + ydiff;                    y3 = y1 + xdiff;                    y4 = y2 + xdiff;                    if(find(hash,x3,y3) && find(hash,x4,y4)){                        ++res;                    }                }            }        }        printf("%d\n",res);        scanf("%d",&n);    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机卡里还有话费怎么办 多余的话费要怎么办 联通流量欠费500怎么办 手机卡没了怎么办呢 联通显示无服务怎么办 大王卡停用了怎么办 手机卡中 剩余话费怎么办 小米被流量限制怎么办 支付宝禁止联网怎么办 手机号登录不上怎么办 电信手机号无法打电话怎么办 新手机号无法注册怎么办 电信手机怎么办流量包 qq华夏到监牢怎么办 炫舞被骗2900怎么办 qq好友申诉后怎么办 无好友辅助申请怎么办 辅助申诉成功后怎么办 qq绑不了手机号怎么办 新办号码有微信怎么办 两手机互换号后微信怎么办 手机申请不了qq怎么办 快手账号保护了怎么办 qq号过期登不上怎么办 xp 登陆界面不见了怎么办 手机号qq 别人登录怎么办 qq号申请频繁怎么办 qq号实名验证怎么办 陌陌没法注册怎么办 腾讯q币充值错误怎么办 手机号码注册微信号怎么办 q币充错了号怎么办 微信超额度提现都不可以怎么办 微信发红包转账限额怎么办 银行卡没设密码怎么办 宜人贷逾期一天怎么办 快手实名已认证怎么办 爱奇艺充会员没有银行卡怎么办 手机qq内存太大怎么办 借呗逾期半年怎么办 支付宝支付错误怎么办