康复训练向,连暴力都不会,打个?ACM
言归正传,知识点只是简要讲讲,运用在题目里才最重要,能独立写对的话一定是已经理解了。
图遍历算法:(默认用邻接矩阵存图)
DFS(深度优先搜索)
Depth First Search,简单概括就是“有一堆路和路口,一直向下走,走不通就回到上一个路口,换个方向继续走,直到所有路都已走过”。关注点在“深度”,就是选定一条道后就会一直沿着它走,直到走到底才会返回,换方向。
常用于枚举所有方案,时间复杂度为O(n*n),n为邻接矩阵的规模
(其实我个人感觉DFS比BFS容易爆时间复杂度…视具体问题及选用的方法而定)
由于存在递归回溯,所以(隐式地)调用了栈
DFS的具体算法描述为选择一个起始点v作为当前结点,执行如下操作:
a. 访问当前结点,并且标记该结点已被访问,然后跳转到b
b. 如果存在一个和当前结点相邻并且尚未被访问的结点u,则将u设为当前结点,继续执行a
c. 如果不存在这样的u,则进行回溯,回溯的过程就是回退当前结点
图中描述了DFS的遍历方向,以1为出发节点,红色箭头代表遍历方向,蓝色箭头代表回溯方向
个人认为DFS关键之处在于写对dfs()的状态转移参数以及回溯处理。
DFS深究的话还有很多技巧,如合理剪枝以降低时间复杂度等等,以后做到了相关题目再单独在题解里写出来
模板如下
//Matsuri
int move[2][4]={1,-1,0,0,0,0,1,-1}; //上下左右走,具体要根据题意
void dfs(int x)
{
if (...) //满足一定条件
{
... // 相关处理
return; // 回溯
}
... // 相关处理,如给当前节点打上标记代表已经搜索过
for (int i=0;i<=3;i++)
{
if (...) // 如果没超界限&没搜索过&其他等等
{
... // 相关处理,打标记等等
dfs(***) // *关键,填入状态转移方式
... // 别忘了回溯,把标记“解放”等等
}
}
}
int main()
{
...(输入)
dfs(0); // 参数一般填初始状态
return 0;
}
BFS(广度优先搜索)
Breadth First Search,简要概括其实就是DFS里关注的“深度”换成了“广度”,就是搜索到一个节点的时候,接下来总是先搜索离它近的其他节点,也就是说是按照开始所在节点→转移1次即可达到的所有节点→转移2次即可达到的所有节点→…这样的顺序进行搜索,直到所有节点都已被访问过。时间复杂度为O(m*n),m为状态数量,n为状态转移方式
需要显式地用到队列
BFS的具体算法描述为选择一个起始点v放入一个先进先出的队列中,执行如下操作:
a. 如果队列不为空,弹出一个队列首元素,记为当前结点,执行b;否则算法结束
b. 将与当前结点相邻并且尚未被访问的结点的信息进行更新,并且全部放入队列中,继续执行a
模板如下
//Matsuri
typedef struct
{
//点的属性,如x,y坐标
int x; //行坐标
int y; //列坐标
int cost; //到该点时已有的花费(如时间)
}node;
queue<node>q;
int move[2][4]={1,-1,0,0,0,0,1,-1}; //上下左右走,具体要根据题意
void bfs()
{
node cur,next;//cur当前节点,next与cur有关的待入队节点
q.push(startpoint);//首先要让第一个节点入队,然后打上标记(如vis[startpoint]=1)
...
while(!q.empty())
{
cur=q.front();q.pop;
if (...)//结束条件,找到满足答案要求的情况了
{
......//相关处理
break;
}
else
{
for (int i=0;i<=3;i++)
{
next.x=cur.x+move[0][i];
next.y=cur.y+move[1][i];
next.cost=cur.cost+1;
if (!vis[next.x][next.y]&&...) //检验不越界等等
{
q.push(next);
vis[next.x][next.y]=1;
}
}
}
}
}
个人认为BFS在原理上比DFS要好理解一些
简单总结:
深搜适合找出所有方案
广搜适合找出最优方案
当图是连通图的时候,只要调用一次BFS/DFS即可遍历图中所有节点;但当图有多个连通分支的时候(即不是所有节点之间都是互通的),要想遍历图中所有点,就必须对每个连通分支调用一次BFS/DFS。这点在题目中很经常体现,要灵活处理。
相关题目及解答
【codevs1294】全排列
【POJ1321】棋盘问题
【POJ2386】Lake Counting
【codevs2801】盖伦的蹲草计划
【POJ2251】Dungeon Master
【POJ3278】Catch That Cow
================================================================
参考资料:
博客 https://blog.csdn.net/WhereIsHeroFrom/article/details/78921973
书籍《挑战程序设计竞赛(第二版)》巫泽俊主译