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 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;
}
0 0
- poj 2549 Sumsets(hash)
- POJ 2549 Sumsets hash
- UVA 10125 - Sumsets(POJ 2549) hash
- poj 2549 Sumsets
- poj 2549 Sumsets
- POJ 2549 Sumsets
- POJ-2549-Sumsets
- poj 2549 Sumsets
- poj 2549 Sumsets
- POJ 2549 Sumsets
- POJ 2549:Sumsets
- poj 2549 Sumsets
- poj 2549 Sumsets
- poj 2549 Sumsets
- POJ-----2549---Sumsets---二分
- Poj 2549/Hoj 1879 Sumsets
- UVa 10125 & POJ 2549 - Sumsets
- POJ 2549 Sumsets(折半枚举)
- codevs1012
- 移动端Web上传图片实践
- [c++学习笔记]反汇编角度看变量名和引用作为函数参数
- 树懒_移动开学笔记_day01_web_html
- 反汇编uimage和查看符号表的方法
- poj 2549 Sumsets(hash)
- 用户管理系统调用
- iOS 读取图片的各种方法
- day03--面向对象--interface接口
- codevs1013
- 利用QTP TextUtil对象获取图片验证码
- JavaScript引擎的工作原理
- 悼念舟曲受难人民!
- 点滴积累,水滴石穿,非一日之功!