zoukankan      html  css  js  c++  java
  • (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU

    这个讲的好:

    https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95/

    分治法

    先空着


    看一下这个第三个方法(随机增量哈希,O(n))

    1.千万不要用unordered_map/hash_map!T飞是肯定的;要手写哈希表,所以码量就很大;手写哈希表方法记一下

    2.事实上以d为边长画格子,每次遍历相邻的9个格子,常数要比以d/2边长画格子,每次遍历相邻25个格子要好(当然此时每个格子里面不一定只有一个数了);不知道为什么

    3.注意,用此方法时,如果距离已经为0了,那么就马上跳出循环(不然可能由于除以0或很接近0的数产生非常大的格子编号,产生不好的事情)

    4.常数似乎较大,比一些分治法要慢

    别人的代码!跑的飞快(交洛谷)

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <time.h>
     4 #include <string.h>
     5 #include <math.h>
     6 #define MAXN 201000
     7 #define DUBF 999999999.9
     8 #define INF 201007
     9 struct NODE
    10 {
    11     int to;
    12     int next;
    13 };
    14 struct NODE1
    15 {
    16     double x, y;
    17 };
    18 int direction[9][2] = {0, 0, -1, -1, -1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1};
    19 NODE1 point[MAXN];
    20 NODE edges[MAXN];
    21 int ad;
    22 int map[INF];
    23 int HASH(int x, int y)
    24 {
    25     return ((x * MAXN + y) % INF + INF) % INF;
    26 }
    27 double len(int i, int j)
    28 {
    29     return sqrt((point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y));
    30 }
    31 void Into_Hash(int i, double r)
    32 {
    33     edges[ad].to = i;
    34     edges[ad].next = map[HASH( (int)(point[i].x/r), (int)(point[i].y/r) )];
    35     map[HASH( (int)(point[i].x/r), (int)(point[i].y/r) )] = ad ++;
    36 }
    37 void Renew_Hash(int n, double r)
    38 {
    39     ad = 0;
    40     memset(map, -1, sizeof(map));
    41     for(int i = 0; i <= n; i ++)
    42         Into_Hash(i, r);
    43 }
    44 double Get_len_around(int p, double r)
    45 {
    46     int x = (int) (point[p].x / r), y = (int) (point[p].y / r), i, j;
    47     double s = DUBF;
    48     for(int k = 0; k < 9; k ++)
    49     {
    50         i = x + direction[k][0], j = y + direction[k][1];
    51         for(int q = map[HASH(i, j)]; ~q; q = edges[q].next)
    52             s = s < len(edges[q].to, p) ? s : len(edges[q].to, p);
    53     }
    54     return s;
    55 }
    56 double Get_R(int n)
    57 {
    58     double r = len(0, 1), s;
    59     int i;
    60     if(r - 0 < 1e-6 || n < 2)
    61         return 0;
    62     Renew_Hash(1, r);
    63     for(i = 2; i < n; i ++)
    64         if((s = Get_len_around(i, r)) < r)
    65         {
    66             r = s;
    67             if(r - 0 < 1e-6)
    68                 return 0;
    69             Renew_Hash(i, r);
    70         }
    71         else
    72             Into_Hash(i, r);
    73     return r;
    74 }
    75 void swap(int i, int j)
    76 {
    77     NODE1 t = point[i];
    78     point[i] = point[j];
    79     point[j] = t;
    80 }
    81 int main()
    82 {
    83     int n, i;
    84     while(scanf("%d", &n)==1)
    85     {
    86         for(i = 0; i < n; i ++)
    87             scanf("%lf %lf", &point[i].x, &point[i].y);
    88         srand((unsigned)time(NULL));
    89         for(i = 0; i < n; i ++)
    90             swap(i, rand() % n);
    91         printf("%.4lf
    ", Get_R(n));
    92     }
    93     return 0;
    94 
    95 }
    View Code

    自己的代码(跑的慢不少,找不出来原因)(交洛谷)

     1 #pragma GCC optimize("Ofast")
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<vector>
     6 #include<ctime>
     7 using namespace std;
     8 #define fi first
     9 #define se second
    10 #define mp make_pair
    11 #define pb push_back
    12 typedef long long ll;
    13 typedef unsigned long long ull;
    14 typedef pair<int,int> pii;
    15 typedef unsigned ul;
    16 typedef pair<ul,ul> puu;
    17 struct P
    18 {
    19     double x,y;
    20     P():x(0),y(0){}
    21     P(double a,double b):x(a),y(b){}
    22 }p[200100];
    23 double sqr(double x){return x*x;}
    24 double dis(const P &a,const P &b)
    25 {
    26     return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
    27 }
    28 //int dx[]={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,};
    29 //int dy[]={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,};
    30 int dx[]={-1,-1,-1,0,0,0,1,1,1};
    31 int dy[]={-1,0,1,-1,0,1,-1,0,1};
    32 
    33 const ul N=200000;
    34 const ul md=999983;
    35 ul calc_hash(const puu &x)    {return (ull(x.fi)*N%md+x.se)%md;}
    36 template<typename T1,typename T2>
    37 struct hmap
    38 {
    39 struct Node{T1 k;T2 v;int nxt;}e[N+100];
    40 int f1[md+1],ne;
    41 void ins(const T1 &x,const T2 &y)
    42 {
    43     ul t=calc_hash(x);
    44     e[++ne].k=x;e[ne].v=y;e[ne].nxt=f1[t];f1[t]=ne;
    45 }
    46 };
    47 
    48 hmap<puu,P> ma;
    49 int n;
    50 double d;
    51 const double MINX=-1e10,MINY=-1e10;
    52 puu gblock(const P &x)
    53 {
    54     return puu((x.x-MINX)/d,(x.y-MINY)/d);
    55 }
    56 void clr(int n)
    57 {
    58     for(int i=1;i<=n;i++)    ma.f1[calc_hash(gblock(p[i]))]=0;
    59     ma.ne=0;
    60 }
    61 void rebuild(int n)
    62 {
    63     for(int i=1;i<=n;i++)    ma.ins(gblock(p[i]),p[i]);
    64 }
    65 int main()
    66 {
    67     int i,j,k;puu lst,now;double td;
    68     srand(time(0));
    69     scanf("%d",&n);
    70     for(i=1;i<=n;i++)    scanf("%lf%lf",&p[i].x,&p[i].y);
    71     random_shuffle(p+1,p+n+1);
    72     d=dis(p[1],p[2]);rebuild(2);
    73     for(i=3;i<=n;i++)
    74     {
    75         if(d<1e-6)    {d=0;break;}
    76         lst=gblock(p[i]);td=1e18;
    77         for(j=0;j<9;j++)
    78         {
    79             now=mp(lst.fi+dx[j],lst.se+dy[j]);
    80             for(k=ma.f1[calc_hash(now)];k;k=ma.e[k].nxt)
    81                 if(ma.e[k].k==now)
    82                     td=min(td,dis(ma.e[k].v,p[i]));
    83         }
    84         if(td<d)    {clr(i-1);d=td;rebuild(i-1);}
    85         ma.ins(gblock(p[i]),p[i]);
    86     }
    87     printf("%.4f",d);
    88     return 0;
    89 }
    View Code

    (相关:

    http://blog.sina.com.cn/s/blog_6fa65cf90100ol2p.html

    http://blog.sina.com.cn/s/blog_aa74c5380101gv0v.html

    https://rjlipton.wordpress.com/2009/03/01/rabin-flips-a-coin/


    Raid POJ - 3714

    求两个点集间点距离最小值

    开两个哈希表,每次在一个哈希表中查询,然后插入另一个哈希表即可

    常数挺大,没有分治快

    注意要用%f输出double

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 #include<ctime>
      6 #include<cmath>
      7 using namespace std;
      8 #define fi first
      9 #define se second
     10 #define mp make_pair
     11 #define pb push_back
     12 typedef long long ll;
     13 typedef unsigned long long ull;
     14 typedef pair<int,int> pii;
     15 typedef unsigned ul;
     16 typedef pair<ul,ul> puu;
     17 struct P
     18 {
     19     double x,y;bool type;
     20     P():x(0),y(0){}
     21     P(double a,double b):x(a),y(b){}
     22 }p[200100];
     23 double sqr(double x){return x*x;}
     24 double dis(const P &a,const P &b)
     25 {
     26     return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
     27 }
     28 //int dx[]={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,};
     29 //int dy[]={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,};
     30 int dx[]={-1,-1,-1,0,0,0,1,1,1};
     31 int dy[]={-1,0,1,-1,0,1,-1,0,1};
     32 
     33 const ul N=200000;
     34 const ul md=999983;
     35 ul calc_hash(const puu &x)    {return (ull(x.fi)*N%md+x.se)%md;}
     36 template<typename T1,typename T2>
     37 struct hmap
     38 {
     39 struct Node{T1 k;T2 v;int nxt;}e[N+100];
     40 int f1[md+1],ne;
     41 void ins(const T1 &x,const T2 &y)
     42 {
     43     ul t=calc_hash(x);
     44     e[++ne].k=x;e[ne].v=y;e[ne].nxt=f1[t];f1[t]=ne;
     45 }
     46 };
     47 
     48 hmap<puu,P> ma1,ma2;
     49 int n;
     50 double d;
     51 const double MINX=-1e10,MINY=-1e10;
     52 puu gblock(const P &x)
     53 {
     54     return puu((x.x-MINX)/d,(x.y-MINY)/d);
     55 }
     56 void clr(int n)
     57 {
     58     for(int i=1;i<=n;i++)
     59         if(p[i].type)
     60             ma2.f1[calc_hash(gblock(p[i]))]=0;
     61         else
     62             ma1.f1[calc_hash(gblock(p[i]))]=0;
     63     ma1.ne=ma2.ne=0;
     64 }
     65 void rebuild(int n)
     66 {
     67     for(int i=1;i<=n;i++)
     68         if(p[i].type)
     69             ma2.ins(gblock(p[i]),p[i]);
     70         else
     71             ma1.ins(gblock(p[i]),p[i]);
     72 }
     73 int main()
     74 {
     75     int i,j,k,T;puu lst,now;double td;
     76     hmap<puu,P> *nm1,*nm2;
     77     srand(616);
     78     scanf("%d",&T);
     79     while(T--)
     80     {
     81     scanf("%d",&n);
     82     for(i=1;i<=2*n;i++)    scanf("%lf%lf",&p[i].x,&p[i].y),p[i].type=(i<=n);
     83     if(n==1)
     84     {
     85         printf("%.3f
    ",dis(p[1],p[2]));
     86         goto xxx;
     87     }
     88     swap(p[n+1],p[2]);
     89     random_shuffle(p+3,p+2*n+1);
     90     d=dis(p[1],p[2]);rebuild(2);
     91     for(i=3;i<=2*n;i++)
     92     {
     93         if(d<1e-6)    {d=0;break;}
     94         nm1=p[i].type?&ma1:&ma2;nm2=p[i].type?&ma2:&ma1;
     95         lst=gblock(p[i]);td=1e18;
     96         for(j=0;j<9;j++)
     97         {
     98             now=mp(lst.fi+dx[j],lst.se+dy[j]);
     99             for(k=nm1->f1[calc_hash(now)];k;k=nm1->e[k].nxt)
    100                 if(nm1->e[k].k==now)
    101                     td=min(td,dis(nm1->e[k].v,p[i]));
    102         }
    103         if(td<d)    {clr(i-1);d=td;rebuild(i-1);}
    104         nm2->ins(gblock(p[i]),p[i]);
    105     }
    106     printf("%.3f
    ",d);
    107     clr(2*n);
    108     xxx:;
    109     }
    110     return 0;
    111 }
    View Code

    upd:这个基于哈希表的随机增量好像不是很对?哈希表的空间开不到O(n^2)啊,冲突概率怕是会很高?(然而实测还行啊?)

  • 相关阅读:
    第四章、Vue组件
    第三章、Vue实例
    第二章、Vue指令
    Python练习实例012
    Python练习实例011
    Python练习实例010
    Python练习实例009
    Python练习实例008
    Python练习实例007
    Python练习实例006
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9418806.html
Copyright © 2011-2022 走看看