论搜索的剪枝

我觉得搜索是真的有趣(其实真的难

搜索的本质

其本质就是在一张图上找出一条从起点到终点,满足某些条件的路径——夏季提高营搜索EX

搜索的模板

1.dfs

void dfs(int step)//可以加入其它有关状态
{
 	if(check())//如果满足跳出条件
    {	
        ...//方案数加一或者输出答案
     	return ;   
    }
    ...//可行性剪枝和最优性剪枝的最佳插入地点
    for(...)
        if(...)//这算一个劣质的剪枝
        {
            oper();
            dfs(step+1);
            re();
        }
}

2.bfs

queue< > q;//可以改为优先队列进行优化
void bfs()
{
    q.push(...);
    while(q.empty()==0)
    {
        tmp=q.front();
        q.pop();
        if(...)
           continue;//可行性剪枝和最优性剪枝的最佳插入地点
        for(...)
            if(...)
                ...;
        		q.push(...);
    }
}

搜索的剪枝

想要优化搜索的复杂度,显然最直接的方法,就是尝试减少需要枚举的局面的数量,在一些特殊情况下,可能有一些特殊的优化的方法。

想要减少遍历枚举的局面数量,最简单的方法就是剪枝。——夏季提高营搜索EX

一般的剪枝有两种,即可行性剪枝和最优性剪枝。

可行性剪枝即是剪去那些不可能满足题设条件的状态,即在某种情况下不可能存在有效解,关键在于看得远,较多用于方案型搜索。

最优性剪枝即是剪去不可能成为最优解的状态,关键在于准确估计最值代价,较多用于最优性搜索。

预测越远,效果越佳。——夏季提高营搜索EX

搜索的剪枝确实是有套路的,(那又如何我反正不会用)

我们来看看常见的深搜套路

  • 改变搜索方向 秋令营搜索第一题
  • 改变状态减少搜索树子集 换个角度看问题
  • 数学方法优化 (多用于数学题) 秋令营搜索第三、四题
  • 玄学转换法 秋令营搜索第九题
  • 按升序搜索 非常常见的操作
  • 折半搜索 (我不会啊)

那么广搜呢

  • map判重减少空间和搜索次数 'search'(亲测不剪30)
  • 循环数组提高空间利用率

搜索剪枝前:7601ms 128000kb

搜索剪枝后:112ms 816kb

只加了三行代码,所以

剪枝真的很重要

But a man is not made for defeat.A man can be destroyed but not defeated.