1 题意
顺序、逆序、从任意一个位置开始6个数,只要长度和位置一一对应相同的两朵雪花,都认为是相同的。
2 分析
散列表,链接法处理冲突。
学习:处理任意一个位置开始6个数的情况。是将6个数在数组里再复制一遍,然后从前面6个数开始分别往后连续数6个数即是不同的组合。
3
挺慢的,2800ms+(4000ms)
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=1200010;
const int mod=1200007;
struct Node{
int num[6];
int next;//相同Key值的后续指针
}node[maxn];//存储雪花的链表
int cur;//雪花链表存储用的当前指针
int hash_table[maxn];//[Key]=对应的首指针
unsigned gethash(int *num){///传进了部分num
unsigned sum=0;
for(int i=0;i<6;i++){
sum+=num[i];///传进的num并非从0开始,用的时候直接从传进的位置开始递加
}
return sum%mod;
}
bool cmp(int* n1,int* n2){
for(int i=0;i<6;i++){
if(n1[i]!=n2[i]) return false;
}
return true;
}
void Insert_hash(int* n,int key){
for(int i=0;i<6;i++)
node[cur].num[i]=n[i];
node[cur].next=hash_table[key];
hash_table[key]=cur++;
}
bool Search_hash(int* num){
unsigned sum=gethash(num);
int next=hash_table[sum];
while(next!=-1){
if(cmp(num,node[next].num)) return true;
next=node[next].next;
}
Insert_hash(num,sum);
return false;
}
void Ini_hash(){
cur=0;
for(int i=0;i<maxn;i++) hash_table[i]=-1;
}
int main()
{
int n;int num[2][12];
scanf("%d",&n);
bool flag=false;
Ini_hash();
//unsigned long long sum=0;
for(int kk=1;kk<=n;kk++){
//插入正序和逆序,以及同构预处理
for(int i=0;i<6;i++){
scanf("%d",&num[0][i]);
num[0][i+6]=num[0][i];
}
if(flag) continue;
for(int i=0;i<6;i++){
num[1][i]=num[0][6-i-1];
num[1][i+6]=num[1][i];
}
//Judge,顺序枚举
for(int i=0;i<6;i++){
if(Search_hash(num[0]+i)||Search_hash(num[1]+i)){
flag=true;
}
}
}
if(flag) cout<<"Twin snowflakes found."<<endl;
else cout<<"No two snowflakes are alike."<<endl;
}