poj 2549 Sumsets(hash)

来源:互联网 发布:lol画面卡顿网络 编辑:程序博客网 时间:2024/06/07 01:43
题目: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;
}





0 0
原创粉丝点击