搜索
dfs
普通
模板一
int Search(int k)
{
for(i=1;i<=算符种数;i++)
if(满足条件)
{
保存结果
if(到目的地) 输出解;
else Search(k+1);
恢复:保存结果之前的状态{回溯一步}
}
}
模板二
int Search(int k)
{
if(到目的地) 输出解;
else
for(i=1;i<=算符种数;i++)//有哪些路
{
if(满足条件) //判断能不能走
{//怎么走
保存结果;
Search(k+1);
恢复:保存结果之前的状态{回溯一步}
}
}
}
记忆化搜索
较常见
记录有效信息,避免无用搜索
int g[MAXN];
int ans=最坏情况,now;
void dfs(传入数值)
{
//这一行很重要↓
if(g[规模]!=无效规模) return ;//或者记录解,视情况而定
if(到达目的地) ans=从当前解与已有解中选最优;//输出解,视情况而定
for(遍历所有可能性)
{
if(可行)
{
进行操作;
dfs(缩小规模);
撤回操作;
}
}
}
int main()
{
···
memset(g,无效数值,sizeof(g));//初始化记忆化数组
···
}
最优性剪枝
排除肯定不优的解
int ans=最坏情况,now;
void dfs(传入参数)
{
//这一行很重要↓
if(now比ans还要差) return ;
if(到达目的地) ans=;
for(遍历所有可能性)
{
if(可行)
{
进行操作;
dfs(缩小规模);
撤回操作;
}
}
}
可行性剪枝
较常见
排除明显不可行的解
int ans=最坏情况,now;
void dfs(传入参数)
{
//这一行很重要↓
if(当前解不可用) return ;//根据题目中的条件进行剪枝
if(到达目的地) ans=;
for(遍历所有可能性)
{
if(可行)
{
进行操作;
dfs(缩小规模);
撤回操作;
}
}
}
排除等效冗余
排除重复的结果
如果有两个解相同,就需要标记一下,避免重复搜索
优化搜索顺序
优先选择最可行/最优的方案
例题
-
优化搜索顺序:从大到小排序
-
排除等效冗余:
(1)因为x+y=y+x,所以我们可以限制每一根加进去的木棍长度是递减的
(2)如果木棍长度相同就不再重复尝试
(3)若一根原始木棍中尝试拼接的第一根木棍递归分支就已经失败,直接判定无解
迭代加深
DFS每次会选择一个分支,不断深入,直到递归边界才回溯,浪费了大量的时间
思想:我们可以从小到大限制搜索的深度,如果当前深度限制下搜不到答案,就把深度限制增加,重新搜索
bfs
普通
int bfs()
{
初始化,初始状态存入队列;
队列首指针head=0;
尾指针tail=1;
do
{
指针head后移一位,指向待扩展结点;
for (int i=1;i<=max;++i) //max为产生子结点的规则数
{
if (子结点符合条件)
{
tail指针增1,把新结点存入列尾;
if (新结点与原已产生结点重复) 删去该结点(取消入队,tail-1);
else
if (新结点是目标结点) 输出并退出;
}
}
}
while(head<tail); //队列为空
}

浙公网安备 33010602011771号