lrjlrjlrj老师给我们三种解决办法,对于一个节点的查重。
这里拿八数码问题中的状态查重来介绍:
数组表示了当前状态。
编码和解码
将排列变成整数:设计一套排列的编码和解码,把0−80-80−8的全排列和0−3628790-3628790−362879的整数一一对应。
然而具体实现的对应并没有看懂。
int vis[362880],fact[9];
void init_lookup_table(){
fact[0]=1;
for(int i=1;i<9;i++)fact[i]=fact[i-1]*i;
}
int try_to_insert(int s){
int code=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++)if(st[s][j]<st[s][i])cnt++;
code+=face[8-i]*cnt;
}
if(vis[code])return 0;
return vis[code]=1;
}
哈希表
哈希技术:将结点变成整数,并映射到一个区间内,如果哈希相同的就插入一个链表中。
查询的时候在哈希值对应的链表中查询。(这个方法最佳/不过链表可能很长,要求哈希函数足够优秀,区间长度也最好是大素数)
const int hashsize = 1000003;
int head[hashsize],next[maxstate];
void init_lookup_table(){memset(head,0,sizeof(head));}
int hash(State& s){
int v=0;
for(int i=0;i<9;i++)v=v*10+s[i];
return v%hashsize;
}
int try_to_insert(int s){
int h=hash(st[s]);
int u=head[h];
while(u){
if(memcmp(st[u],st[s],sizeof(st[s]))==0)return 0;
u=next[u];
}
next[s]=head[h];
head[h]=s;
return 1;
}
STL
可以使用map,setmap,setmap,set直接记录状态,或者将状态暴力转换成数(可以存longlonglong longlonglong)
最后查询判断即可。