常用的广搜状态保存和哈希法
http://hi.baidu.com/mfs666/blog/item/34e388b1fac640530823027c.html
广搜的时候,保存状态和进行哈希很重要,我们来回忆一下常见的状态保存和哈希法
1.直接的数组定位:
hash:array[0..20,0..20,0..20] of record end;
将组成状态的各个元素直接作为数,或者编号,然后就可以利用数组的下标直接定位,适用于各元素不是很大,而且维数不是太多
2.编号法,对状态事先进行存储,然后编号。或者是对于几个有序的元素的全排列,可以利用康托展开对全排列进行编号和生成。
对十进制数的全排列进行康托展开:
var
k:array[0..10] of longint;//保存阶乘
s:string;
i:longint;
function kt(x:string):longint;
var
hash:array[0..10] of boolean;//判断数是否出现过
i,t,j,c:longint;
begin
fillchar(hash,sizeof(hash),false);//初始化
kt:=0;
for i:=1 to length(s)-1 do begin//从第一位到倒数第二位进行处理
val(s[i],t);//转换为数字
hash[t]:=true;//将这一位数字设置为出现过
c:=0;//计数器置0
for j:=1 to t-1 do//对于比这一位小的的数字,如果没有在之前出现过,则计数
if not hash[j] then
inc(c);
inc(kt,c*k[length(s)-i]);将符合要求的数量乘以从倒数第二位开始数的数的阶乘
end;
inc(kt);
end;
begin
readln(s);
k[1]:=1;
for i:=2 to length(s) do
k[i]:=i*k[i-1];//计算阶乘数组
writeln(kt(s));
end.
3.进制数法,常用的就是状态有多个0,1状态,组成一个二进制串,然后转变成一个十进制数。也可以是其他进制的状态组成数,转变成十进制数保存。见进制转换(数学部分)
4.字符串法,若状态可以表示为一个没什么规律的串,所以用字符串哈希,见以下,函数值是dword范围内的。
program bkdrhash;
var
s:string;
a:qword;
function bkdrhash(x:string):dword;
var
i:longint;
t,seed:qword;
begin
t:=0;
seed:=131;//质数种子
for i:=1 to length(s) do
t:=(t*seed+ord(s[i])) and $FFFFFFFF;//对于每一位,将当前函数值乘以种子,加上ascii码,最后and最大的32位数
bkdrhash:=t and $7FFFFFFF;//最后and这个数
end;
begin
readln(s);
a:=bkdrhash(s);
writeln(a);
end.

浙公网安备 33010602011771号