常用的广搜状态保存和哈希法

 

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.

posted @ 2010-05-14 13:55  jesonpeng  阅读(251)  评论(0)    收藏  举报