poj3349-hash

45 篇文章 0 订阅

题目连接

分析:

对于一个六边形,长度个不一个样,而物体可以旋转,这是一个很头痛的问题,该如何辨别这些相同的六边形,链表?这显然不好,用map行不通,想想看,

比如:1 2 3 4 5 6和1 2 2 3 4 5,他们的和是不同的,所以我们直接就可以否定他们相同,但对于 1 2 3 4 5 6和 1 3 2 4 6 5,他们的和是相同的,但属于不同的

六边形,这些数据有些好辨别,有些不好辨别,我们应该让他们离散化,尽可能的让他们离散,由于sum和可能很大,我们就mod一个数就是让他们离散化,

对于余数相同的,我们就hash吧!。

hash思想:对于很多数据,存在个体差别和个体相同,要查找一个数据,很不容易,我们就先把它们离散化,离散化并不能消除个体相同的,但在很大程度上

降低了查找数据的难度,对于转化后的数据,还是相同,我们就把它放在一起(即放在同一行)。这样我就根据该行,一次找下去,就可以了。说白了,hash思想的

精粹就是:类比思想。一大批数据,我们只要对这些数在一个特定的M(方式),在M的处理下,每个数据有个映射,沿着这条路径,可以彼此建立联系,把原问题转化成

另一个问题,大大降低难度了。

好好体会这种思想!

本题代码如下:

#include<stdio.h>
#include<string.h>
#define H 1000000
#define N 2000000

struct node{
       int date[6];
       int next;
}Node[N];

int hashtable[N],cnt=0;
int get_hash(int *num)
{
    int sum=0;
    for(int i=0;i<6;i++)
     sum=(sum+num[i])%H; 
    return sum;              
}
bool cmp(int *num1,int *num2){
     for(int i=0;i<6;i++){
         if(num1[i]!=num2[i])
              return false;
     }
     return true;
}
void insert (int *num,int x){
     for(int i=0;i<6;i++){
      Node[cnt].date[i]=num[i];
     }
     Node[cnt].next=hashtable[x];
     hashtable[x]=cnt++;
}
bool search(int *num){
      int r=get_hash(num);
      int m=hashtable[r];
      while(m!=-1){
       if(cmp(num,Node[m].date)) return true;
        m=Node[m].next;               
      }
     insert(num,r);
	 return false;
}
int main()
{
    int num[2][12],t,i,flag=0;
    memset(hashtable,-1,sizeof(hashtable));
    scanf("%d",&t);
    while(t--){
       for(i=0;i<6;i++){
          scanf("%d",&num[0][i]);
          num[0][6+i]=num[0][i];   //构造循环 
       }  
       for(i=0;i<6;i++){
         num[1][i+6]=num[1][i]=num[0][5-i];   //构造反循环 ,巧妙之处。 
       }  
       for(i=0;i<6;i++){
        if(search(num[0]+i)||search(num[1]+i))
        {
          flag=1;
          break;
        }
       }
	  }
       if(flag) printf("Twin snowflakes found.\n");
       else printf("No two snowflakes are alike.\n");       
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值