zoukankan      html  css  js  c++  java
  • 【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)

    题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0。问有多少种选法。(N≤4000,D≤2^28)

    解法:首先我们从最直接最暴力的方法开始思考:四重循环O(n^4)枚举;三重循环枚举,把剩下的一个集合排序后二分查找,O(n^3 log n)。在进一步想,运用“中途相遇法”:从两个不同的方向来解决问题,最后“汇集”到一起的方法。(有类似于“双向广度优先搜索”的思想)通过两重循环枚举出A,B两个集合中的元素可组成的和,一般想到开个以和为值的数组记录个数。但是由于D值有2^28这么大,所以不行。于是——解决技巧很厉害!(。ì _ í  。)

    实现1:既然不能将相同的数一个个竖向累积在一个数组位,那就可以把这些相同的数横向拉伸,排成一排。使用STL库头文件algorithm里的upper_bound和lower_bound函数直接查找到>d和>=d的数的位置,相减就是d值的数的个数。这样的时间复杂度是O(n^2 log n)。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<iostream>
     6 using namespace std;
     7 
     8 const int N=4010;
     9 int a[N],b[N],c[N],d[N],sum[N*N];
    10 
    11 int main()
    12 {
    13     int T;
    14     scanf("%d",&T);
    15     while (T--)
    16     {
    17       int n;
    18       scanf("%d",&n);
    19       for (int i=1;i<=n;i++)
    20         scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    21       int m=0;
    22       for (int i=1;i<=n;i++)
    23         for (int j=1;j<=n;j++)
    24           sum[++m]=a[i]+b[j];
    25       sort(sum+1,sum+1+m);
    26       long long cnt=0;//long long
    27       for (int i=1;i<=n;i++)
    28         for (int j=1;j<=n;j++)
    29           cnt+=upper_bound(sum+1,sum+1+m,-c[i]-d[j])-lower_bound(sum+1,sum+1+m,-c[i]-d[j]);
    30       printf("%lld
    ",cnt);
    31       if (T) printf("
    ");
    32     }
    33     return 0;
    34 }
    STL库实现

    实现2:当然检索的高效算法 Hash也是可以的。我这里用的是闭散列表储存,即%一个大整数(一般是质数)之后放在相应的位置。若该位置已存储了其他数,则将这个数一直往后推直到一个空的位置。由于和的个数最多为n^2,小于列表的长度足够存储,那么就算和的值很大也不影响了。
       关于具体代码我再解释一些:1.常量的0x7fffff表示16进制的7fffff,f是15,即2^23;2.结构体哈希表重载了运算符[],这样就可以直接得到每个数的个数了;3.用&运算而不是%,可能是因为运算速度或存储空间,改成%就RE,但其实它们的意思是一样的,目的都是使数较集中的放在一起。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 const int N=4010;
     8 int a[N],b[N],c[N],d[N];
     9 
    10 struct ha_map
    11 {
    12     static const int mod=0x7fffff;
    13     int s[mod+1],d[mod+1];
    14     void clear() {memset(s,0,sizeof(s));}
    15     int& operator [] (int x)
    16     {
    17       int i;
    18       for (i=x&mod;s[i]&&d[i]!=x;i=(i+1)&mod);
    19       d[i]=x;
    20       return s[i];
    21     }
    22 }ha;
    23 
    24 int main()
    25 {
    26     int T;
    27     scanf("%d",&T);
    28     while (T--)
    29     {
    30       int n;
    31       scanf("%d",&n);
    32       for (int i=1;i<=n;i++)
    33         scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    34       ha.clear();
    35       for (int i=1;i<=n;i++)
    36         for (int j=1;j<=n;j++)
    37           ha[a[i]+b[j]]++;
    38       long long cnt=0;//long long
    39       for (int i=1;i<=n;i++)
    40         for (int j=1;j<=n;j++)
    41           cnt+=ha[-c[i]-d[j]];
    42       printf("%lld
    ",cnt);
    43       if (T) printf("
    ");
    44     }
    45     return 0;
    46 }
    Hash实现

    Hash的速度是STL库的4倍多~~ (-ω-*)

  • 相关阅读:
    eclipse启动时发生的Initializing Java Tooling错误
    2017最新xcode打包APP详细图文
    系统安全:安装系统时要做的优化
    逻辑卷扩容
    记一次装13行为
    网络边界安全:防火墙双机热备之上下行接交换机
    解决故障的终极绝招:重装重启之dell R620装系统
    态势感知
    怪力乱神
    远程给客户配置防火墙的反思
  • 原文地址:https://www.cnblogs.com/konjak/p/6043638.html
Copyright © 2011-2022 走看看