搜索模板

深度优先搜索,就是将可能的答案从头到尾进行递归枚举,在确定前一部分的情况下,根据规则往下扩展答案树,直到得到可行的答案

广搜,借助队列实现,扩展节点入队

双向广搜,双向扩展结点,在两个方向的扩展顺序上,可以轮流交替进行,但由于大部分的解答树并不是棵完全树 ,在扩展完一层后,下一层则选择结点个数较少的那个方向先扩展,可以克服两个方向结点生成速度不平衡的状态,明显提高搜索效率

剪枝

1.如果当前节点已经到达过,就可以直接剪掉,这个可以用哈希表来实现,也可以根据情况直接开一个Judge数组

2.使用估价函数判定,如果在最乐观的情况下,所需要的步数仍然不如已经找到的最优解,就直接剪掉

注意事项

1.在传递参数的过程中,如果把当前状态也传了过来,就一定要开一个备份,直接对备份进行操作,然后把备份作为参数传下去,这之后再把备份改回原来的状态

2.在搜索方案的过程中,如果在往下走之前把judge数组设了一,递归完一定要再改成零

3.在循环搜索填下一个空的时候,如果开了变量,要对状态进行一定处理,并有他进行judge数组记录,在需要回溯的时候一定要看好,这个变量还是不是从一开始穿上来的那个状态引出来的

4.一定要设置边界

5.在判重的时候,在队首元素入队前设标记,在扩展节点前判定标记,在入队新状态前设标记

框架:

1.深搜

void dfs(当前状态);
{
           if  当前状态为边界   {
              if 当前状态为最佳目标状态 
                     { 记下最优结果;exit;}
               }
           for i←算符最小值 to 算符最大值 do {//状态循环变量为局部变量
               算符i作用于当前状态,扩展出一个子状态;
               标记子状态路径;
               if (子状态满足约束条件) and (子状态满足最优性要求)
                  dfs(子状态);
                   恢复子状态路径;  //回溯
           }
}
View Code

2.广搜

 1 void bfs(v);
 2 {
 3 Int queue(q); 
 4 Visite(v); visted[v]=true; Insert_queue(q,w);
 5 While not empty(q) do {
 6 取出队首元素 v
 7 For 对所有v扩展出来的元素w
 8 if (not visited[w] )
 9     { visite(w);visited[w]=true; Insert_queue(q,w)}
10  delete_queue(q,v);
11 }
12 }
View Code

3.双向广搜

 1 //DOUBFS初始化,初始结点,和目标结点分别进入OPEN[1]和OPEN[2]表;
 2     head[1]=1; tail[1]=1; head[2]=1; tail[2]=1 3     do{
 4              if (tail[1]-head[1]<=tail[2]-head[2]) t=1;else t=2//优先扩展待讨论节点比较少那个方向
 5              for(i=head[t];i<=tail[t];i++)expand(t);//讨论队列中的结点
 6         }while(head[t]<=tail[t]);
 7    //函数expand(t)的结构如下:
 8   void expand(int t)
 9  {
10       int j;
11       for(j=1;j<=n;j++ ) //n为最多后继状态数
12       {
13           产生i点的第j个后继状态,将它加入到队尾(tail[t]+1);
14           if(新结点未与其上一层以上的所有点重复)
15           {
16                 if isans(t) {输出结果;return;}
17           }
18          else{将新点从队列中去掉(tail[t]-1);}
19       }
20   }
21   // 判断两个方向是否是相交点的函数isans(t)如下:
22   bool isans(int t)
23   {
24         int j,k;
25         if(t==1)k=2; else k=126         for(j=head[k] ;j<=tail[k];j++) 
27            if(tail[t]==j)return true;//新结点tail[t]是相交点
28         return false;
29  }
View Code

4.康托展开式编码判重

 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

 1 int gethash(status a)
 2 {
 3     int res = 0;
 4     int k = 1;
 5     int i, j;
 6     //此处的4为每个位能达到的最大数+1 
 7     for (i = 1; i <= 4; i++)
 8         for (j = 1; j <= 4; j++)
 9         {
10             res += a.map[i][j] * k;
11             k *= 3;
12         }
13     return res;
14 } 
View Code

5.位运算加速

  ·x&-x 返回最低一位1

  ·x ^ 1 等价于!x

  

 

posted @ 2015-09-19 23:36  ACforever  阅读(250)  评论(0编辑  收藏  举报