哈希表好像遠比我想象的要復雜得多啊 @_@~ loading。。。。
又過了很久,大概看懂了一點這個哈希表是個什么意思:
對于這道題,我要做的就是,根據每個雪花的六個數(把他們映射到一個整數),把這些雪花分類,盡量多的分類,每一類里的雪花數量盡量少(在內存大小允許的前提下)。而且對于一個已知六條邊長度的雪花,都是可以瞬間(以O(1)的時間復雜度)找到這個雪花應該在的類。然后就是如果有多個雪花的六個數都有相同的映射,一個很巧妙很巧妙的方法,現在想想之前的鄰接表代碼實現看不懂應該也是用了這個方法,就是用next數組表示同一類里面,第i個雪花的下一雪花的標號next[i];
關于這個映射方法:
去網上看了幾個映射方法,然后因為第一次做哈希表的題,所有都沒用過?,F在暫時只討論本題,因為我要考慮的是這六個數的圍成的圈是否有重復的,所有這個映射方法至少應該滿足的條件是:有可能圍城相同的環的兩組數一定要分到一個類里面。換句話說,就是不同組里面的兩組數一定不可能圍成相同的環。但是如何在滿足這個的條件下使得每一類里面的數盡可能的少呢?也就是映射的盡量均勻。
#include<iostream>#include<string.h>#include<stdio.h>#define N 1000000using namespace std;int hash[N+500]={0};int next[N+500]={0};int snow[100500][6]={0};int n;void input(){ for(int i=1;i<=n;i++) { for(int j=0;j<6;j++) { scanf("%d",&snow[i][j]); } }}bool compare(int *a,int *b)//判斷a數組和b數組是否可以圍成相同的圈 { for(int i=0;i<6;i++) { bool flag=1; for(int j=0;j<6;j++) { if(a[j]!=b[(j+i)%6]) { flag=0;break; } } if(flag==1)return 1; } for(int i=0;i<6;i++) { bool flag=1; for(int j=0;j<6;j++) { if(a[j]!=b[(i-j+5)%6]) { flag=0;break; } } if(flag==1)return 1; } return 0;}/*bool compare(int a,int b)//網友的compare函數 { int i,j,k; for(i=0;i<6;i++) { for(j=i,k=0;k<6;k++,j=(j+1)%6)//???,??????? if(snow[a][k]!=snow[b][j])break; if(k==6)return true; for(j=i,k=0;k<6;k++,j=(j+5)%6)//??? if(snow[a][k]!=snow[b][j])break; if(k==6)return true; } return false;}*/int main(){ while(cin>>n) { input(); bool flag=0; memset(hash,0,sizeof(hash)); memset(next,0,sizeof(next)); for(int i=1;i<=n;i++) { int x=0; for(int j=0;j<6;j++)//求出i對應的x { x=(int)((x+(long long int)snow[i][j]*(long long int)snow[i][j])%N); } int l=hash[x]; //cout<<x<<endl; while(l)//判斷是否有與第i個相同的雪花 { if(compare(snow[i],snow[l])) { flag=1; break; } l=next[l]; } if(flag==1)break; //把第i個加入類中 next[i]=hash[x]; hash[x]=i; } if(flag==1)cout<<"Twin snowflakes found."<<endl; else cout<<"No two snowflakes are alike."<<endl; }}另外x=(x+snow[i][j]*snow[i][j])%N會runtime error。一定要強制類型轉換成long long int。
新聞熱點
疑難解答