POJ3349 哈希表

题目大意:就是在给出的雪花当中判断有没有至少一样的一对雪花。

思路:在10W片雪花中直接比较雪花明显不可,但是经过哈希之后可以边插入边比较。

//Memory Time
//16696K 3766MS

#include<iostream>
using namespace std;

const __int64 prime=999983; // 10n内最大的素数(本题n=10W)

class
{
public:
__int64 len[6]; //6瓣叶子的长度
}leaf[100001];

typedef class HashTable
{
public:
__int64 len[6]; //记录6瓣叶子的长度信息
HashTable* next; //用于冲突时开放寻址

HashTable() //Initial
{
next=0;
}
}Hashtable;

Hashtable* hash[prime+1];//模拟链表的头指针的作用

/*计算第k个雪花的关键字key*/

__int64 compute_key(int k)
{
__int64 key=0;
for(int i=0;i<6;i++)
{
key+=(leaf[k].len[i]) % prime;
key%=prime; //利用同余模定理计算key,避免出现大数
}

return ++key; //键值后移1位,把key的范围从0~999982变为 1~999983
}

/*从顺时针方向判断两片雪花是否相同*/

bool clockwise(Hashtable* p,int k)
{
for(int j=0;j<6;j++) //顺时针转动j格
{
bool flag=true;
for(int i=0;i<6;i++)
if(leaf[k].len[i] != p->len[(i+j)%6])
{
flag=false;
break;
}
if(flag)
return true;
}
return false;
}

/*从逆时针方向判断两片雪花是否相同*/

bool counterclockwise(Hashtable* p,int k)
{
for(int j=0;j<6;j++) //逆时针转动j格
{
bool flag=true;
for(int i=0;i<6;i++)
if(leaf[k].len[i] != p->len[(5-i-j+6)%6])
{
flag=false;
break;
}
if(flag)
return true;
}
return false;
}

/*把第k个雪花信息插入HashTable*/
/*当插入的位置已存在其他雪花信息时,顺便比较*/

bool insert(int k)
{
__int64 key=compute_key(k);

if(!hash[key])
{
Hashtable* temp=new Hashtable;

for(int i=0;i<6;i++)
temp->len[i]=leaf[k].len[i];

hash[key]=temp; //保存key对应的地址
}
else //地址冲突,开放寻址,顺便比较
{
Hashtable* temp=hash[key];

if(clockwise(temp,k) || counterclockwise(temp,k)) //检查雪花是否相同
return true;

while(temp->next) //寻址
{
temp=temp->next;

if(clockwise(temp,k) || counterclockwise(temp,k)) //检查雪花是否相同
return true;
}

temp->next=new Hashtable; //申请空间,保存新雪花信息
for(int i=0;i<6;i++)
temp->next->len[i]=leaf[k].len[i];
}
return false;
}

int main(int i,int j)
{
int n; //雪花数
while(cin>>n)
{
/*Initial*/

memset(hash,0,sizeof(hash)); // 0 <-> NULL

/*Input*/

bool flag=false; //记录输入过程中是否出现了相同的雪花
for(i=1;i<=n;i++)
{
for(j=0;j<6;j++)
scanf("%I64d",&leaf[i].len[j]);

/*Hash*/

if(!flag) //当前还没有出现相同的雪花
flag=insert(i);
//若出现相同的雪花,则还需后续输入,但不再处理
}

/*Output*/

if(flag)
cout<<"Twin snowflakes found."<<endl;
else
cout<<"No two snowflakes are alike."<<endl;

}
return 0;
}

另转:http://axorb.diandian.com/post/2011-07-14/40029160561


#include<iostream>

#define M 99991

using namespace std;

struct Snow

{

long leg[7];

Snow * next;

}snow[M+5];

void shushi(void)

{

for(int i=0;i<M;i++)

{

memset(snow[i].leg,0,sizeof(snow[i].leg));

snow[i].next=NULL;

}

}

int Hash(long a[])

{

long long x=0;

x=a[0]+a[1]+a[2]+a[3]+a[4]+a[5];

return x%M;

}

int to_insert(long a[])

{

int k=Hash(a);

Snow * p = &snow[k];

while(p->next!=NULL)p=p->next;

p->next=new Snow;

for(int i=0;i<6;i++)

p->next->leg[i]=a[i];

p->next->next=NULL;

return 0;

}

int judge(long a[],long b[])

{

long c[7];

for(int i=0;i<6;i++)

c[i]=a[6-i-1];

for(int i=0;i<6;i++)

{

int n=0;

for(int j=0;j<=5;j++)

if(a[(j+i)%6]==b[j])

n++;

if(n==6)return 1;

}

for(int i=0;i<6;i++)

{

int n=0;

for(int j=0;j<=5;j++)

if(c[(j+i)%6]==b[j])

n++;

if(n==6)return 1;

}

return 0;

}

int main(){

long n,arm[7];

cin >> n;

int mark=0;

shushi();

while(n--)

{

for(int i=0;i<6;i++)

scanf("%ld",&arm[i]);

if(mark)continue;

int k=Hash(arm);

Snow * p=snow[k].next;

while(p!=NULL)

{

if(judge(p->leg,arm))

mark=1;

p=p->next;

}

to_insert(arm);

}

if(mark) printf("Twin snowflakes found.\n");

else printf("No two snowflakes are alike.\n");

system("pause");

}

#include<iostream>

#define M 99991

using namespace std;

struct Snow

{

long leg[7];

Snow * next;

}snow[M+5];

void shushi(void)

{

for(int i=0;i<M;i++)

{

memset(snow[i].leg,0,sizeof(snow[i].leg));

snow[i].next=NULL;

}

}

int Hash(long a[])

{

long long x=0;

x=a[0]+a[1]+a[2]+a[3]+a[4]+a[5];

return x%M;

}

int to_insert(long a[])

{

int k=Hash(a);

Snow * p = &snow[k];

while(p->next!=NULL)p=p->next;

p->next=new Snow;

for(int i=0;i<6;i++)

p->next->leg[i]=a[i];

p->next->next=NULL;

return 0;

}

int judge(long a[],long b[])

{

long c[7];

for(int i=0;i<6;i++)

c[i]=a[6-i-1];

for(int i=0;i<6;i++)

{

int n=0;

for(int j=0;j<=5;j++)

if(a[(j+i)%6]==b[j])

n++;

if(n==6)return 1;

}

for(int i=0;i<6;i++)

{

int n=0;

for(int j=0;j<=5;j++)

if(c[(j+i)%6]==b[j])

n++;

if(n==6)return 1;

}

return 0;

}

int main(){

long n,arm[7];

cin >> n;

int mark=0;

shushi();

while(n--)

{

for(int i=0;i<6;i++)

scanf("%ld",&arm[i]);

if(mark)continue;

int k=Hash(arm);

Snow * p=snow[k].next;

while(p!=NULL)

{

if(judge(p->leg,arm))

mark=1;

p=p->next;

}

to_insert(arm);

}

if(mark) printf("Twin snowflakes found.\n");

else printf("No two snowflakes are alike.\n");

system("pause");

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值