poj 2549 Sumsets(hash)

题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23666
a+b+c=d 转化: a+b=d-c。这就变成了查找问题。1000*1000/2=500000,所以需要5e5大的空间装散列表。实现:
拉链法,存储结构即用到了链式前向星的思想。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5e5+5;
int hashx[maxn],next[maxn],s[1010];
struct Node{
    int p1,p2;
}node[maxn];
int res;
bool flag;
void solve(int xx,int yy){
    int key=(xx-yy+maxn)%maxn;
    int p=hashx[key];
    while(p!=-1){
        if((node[p].p1+node[p].p2)==(xx-yy)&&node[p].p1!=xx&&node[p].p2!=xx&&node[p].p1!=yy&&node[p].p2!=yy){
            flag=true;
            res=xx;
            return;
        }
        p=next[p];
    }
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n,i,j;
    while(cin>>n&&n){
        for(i=0;i<n;i++)scanf("%d",&s[i]);
        sort(s,s+n);
        memset(hashx,-1,sizeof(hashx));
        int iter=0;
        for(i=0;i<n-1;i++){
            for(j=i+1;j<n;j++){
                node[iter].p1=s[i];  node[iter].p2=s[j];
                int key=(s[i]+s[j]+maxn)%maxn;
                next[iter]=hashx[key];
                hashx[key]=iter++;
            }
        }
        res=-0x3f3f3f3f;
        flag=false;
        for(i=n-1;i>0;i--){
            for(j=i-1;j>=0;j--){
                if(flag)break;  //it must be up line. think over,it's interesting
                solve(s[i],s[j]); 
            }
        }
        if(res>-0x3f3f3f3f)printf("%d\n",res);
        else printf("no solution\n");
    }
    return 0;
}
本想再用开放地址法也实现一遍,但是不是超时就是错误,郁闷~~应该是散列函数没找好,或者其他知识不足。。
这是当时写的:
线性探查:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int len1=8e5+5;//,len2=642913;
bool flag;
int s[1010],hashx[len1],result;
struct Node{
    int p1,p2;
}node[len1];
void solve(int xx,int yy){
    int key=(xx-yy+len1)%len1;
    int p=hashx[key];
    if(p!=-1){
        if(node[p].p1!=xx&&node[p].p2!=yy&&node[p].p1!=yy&&node[p].p2!=xx){
            result=xx;
            flag=true;
        }
    }
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n,i,j;
    while(cin>>n&&n){
        for(i=0;i<n;i++)scanf("%d",&s[i]);
        int iter=0;
        sort(s,s+n);
        memset(hashx,-1,sizeof(hashx));
        for(i=0;i<n-1;i++){
            for(j=i+1;j<n;j++){
                node[iter].p1=s[i];
                node[iter].p2=s[j];
                int key=(s[i]+s[j]+len1)%len1,w=1;
                while(hashx[key]!=-1&&w*7<len1){
                    key=(key+w*7)%len1; //11,9,8 is wrong, 7 is TLE  
                    w++;
                }
                hashx[key]=iter++;
            }
        }
        result=-0x3f3f3f3f;
        flag=false;
        for(i=n-1;i>0;i--){
            for(j=i-1;j>=0;j--){
                if(flag)break;
                solve(s[i],s[j]);
            }
        }
        if(result>-0x3f3f3f3f)printf("%d\n",result);
        else printf("no solution\n");
    }
    return 0;
}
双重散列:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int len1=8e5+5,len2=375871;
bool flag;
int s[1010],hashx[len1],result;
struct Node{
    int p1,p2;
}node[len1];
void solve(int xx,int yy){
    int key=(xx-yy+len1)%len1;
    int p=hashx[key];
    if(p!=-1){
        if(node[p].p1!=xx&&node[p].p2!=yy&&node[p].p1!=yy&&node[p].p2!=xx){
            result=xx;
            flag=true;
        }
    }
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n,i,j;
    while(cin>>n&&n){
        for(i=0;i<n;i++)scanf("%d",&s[i]);
        int iter=0;
        sort(s,s+n);
        memset(hashx,-1,sizeof(hashx));
        for(i=0;i<n-1;i++){
            for(j=i+1;j<n;j++){
                node[iter].p1=s[i];
                node[iter].p2=s[j];
                int key=(s[i]+s[j]+len1)%len1,w=1;
                while(hashx[key]!=-1){
                    key=(key+w*(key%len2))%len1; //双散列超时
                    w++;
                }
                hashx[key]=iter++;
            }
        }
        result=-0x3f3f3f3f;
        flag=false;
        for(i=n-1;i>0;i--){
            for(j=i-1;j>=0;j--){
                if(flag)break;
                solve(s[i],s[j]);
            }
        }
        if(result>-0x3f3f3f3f)printf("%d\n",result);
        else printf("no solution\n");
    }
    return 0;
}





你可能感兴趣的:(hash,HDU)