EOJ 1046 4个数的和为0

poj 2785 http://poj.org/problem?id=2785

eoj 1046 http://acm.cs.ecnu.edu.cn/problem.php?problemid=1046

    思路: 散列(hash) + 拉链法去冲突;

    具体过程:
    
    把num[][1-4]按列划分为num[][1-2] 和 num[][3-4];
    
    对    MAXN + num[i][1] + num[j][2]    散列;O(n^2 * len)

    对    MAXN - num[i][3] - num[j][4]    查找;O(n^2 * len)
    
    须使得被散列值为正,故用一大数 MAXN 保护;len为链表平均长度;

    注意:
    
    1.散列时,sum的地址由 hash(sum) = sum % MOD; 给出

    2.MOD取一个大素数的动机是:使得平均查找效率更优;

    也即散列得更均匀;

    3.解决冲突的链表,这里用数组模拟,貌似比malloc快。

    困惑:
        按题意,节点总数最多为 4000*4000,
        
        而我这里只开了NE个节点,觉得不够, 开大了又MLE。。。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define MAXN (1<<29)
 4 #define N 4005
 5 #define MOD 3999971
 6 #define NE 3999999
 7 typedef struct
 8 {
 9     int n;
10     int cnt;
11     int next;
12 }E;
13 int ie;
14 E edge[NE];    //待分配的节点
15 
16 int num[N][5];
17 int hash[MOD+5];
18 
19  
20 void init()
21 {
22     for(int i=0; i<=MOD; i++)
23         hash[i] = 0;        
24     ie = 1;
25 }
26 int search(int n)
27 {
28     int a = n%MOD;
29     int p = hash[a];
30     while(p)
31     {
32         if(edge[p].n == n)
33             return p;
34         p = edge[p].next;
35     }
36     return 0;    //未找到
37 }
38  
39 void add(int n)
40 {
41     int a = n%MOD;
42     int p;
43     if(p = search(n))    //找到,则仅将次数++
44         edge[p].cnt ++;
45             
46     else        //未找到,则申请新节点,并插在头部。
47     {
48         edge[ie].n = n;
49         edge[ie].cnt = 1;
50         
51         edge[ie].next = hash[a];
52         hash[a] = ie++;
53     }
54  
55 }
56  
57 int main()
58 {
59     int n;
60     while(scanf("%d", &n) != EOF)
61     {
62         int i, j, cnt = 0;
63         for(i=1; i<=n; i++)
64             for(j=1; j<=4; j++)
65                 scanf("%d", &num[i][j]);
66         
67         init();
68         
69         for(i=1; i<=n; i++)
70             for(j=1; j<=n; j++)        
71                add(MAXN + num[i][1] + num[j][2]);
72         
73         for(i=1; i<=n; i++)
74             for(j=1; j<=n; j++)
75             {
76                 int p = search(MAXN - num[i][3] - num[j][4]);
77                 if(p)
78                     cnt += edge[p].cnt;
79             }                    
80         
81         printf("%d\n", cnt);
82     }
83     
84 }
View Code

posted on 2013-06-09 13:38  KimKyeYu  阅读(205)  评论(0编辑  收藏  举报

导航