搜索

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(缩小规模);
			撤回操作; 
		}
	}
}

排除等效冗余

排除重复的结果

如果有两个解相同,就需要标记一下,避免重复搜索

优化搜索顺序

优先选择最可行/最优的方案

例题

P1120 小木棍 [数据加强版]

  1. 优化搜索顺序:从大到小排序

  2. 排除等效冗余:

    (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);                       //队列为空
}

posted @ 2021-08-15 20:50  晨曦时雨  阅读(73)  评论(0)    收藏  举报
-->