题目:
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 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;
}
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;
}