l
r
j
lrj
lrj老师给我们三种解决办法,对于一个节点的查重。
这里拿八数码问题中的状态查重来介绍:
数组表示了当前状态。
编码和解码
将排列变成整数:设计一套排列的编码和解码,把
0
−
8
0-8
0−8的全排列和
0
−
362879
0-362879
0−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
可以使用
m
a
p
,
s
e
t
map,set
map,set直接记录状态,或者将状态暴力转换成数(可以存
l
o
n
g
l
o
n
g
long long
longlong)
最后查询判断即可。