图的介绍
图是节点集合的一个拓扑结构,节点之间通过边相连。图分为有向图和无向图。有向图的边具有指向性,即A-B仅表示由A到B的路径,但并不意味着B可以连到A。与之对应地,无向图的每条边都表示一条双向路径。
可称为:DAG Directed acyclic graph
图的表达方式
宽度优先搜索——BFS(Breadth First Search)
BFS(G, s)
For each vertex u exept s
Do Color[u] = WHITE
Distance[u] = MAX
Parent[u] = NIL
Color[s] = GRAY
Distance[s] = 0
Parent[s] = NIL
Enqueue(Q, s)
While Q not empty
Do u = Dequeue(Q)
For each v is the neighbor of u
Do if Color[v] == WHITE
Color[v] = GRAY
Distance[v] = Distance[u] + 1
Parent[v] = u
Enqueue(Q, v)
Color[u] = BLACK
BFS特点
搜索所有可以到达的状态,转移顺序为『初始状态->只需一次转移就可到达的所有状态->只需两次转移就可到达的所有状态->…』,所以对于同一个状态,BFS 只搜索一次
BFS 通常配合队列一起使用,搜索时先将状态加入到队列中,然后从队列顶端不断取出状态,再把从该状态可转移到的状态中尚未访问过的部分加入队列,知道队列为空或已找到解。因此 BFS 适合用于『由近及远』的搜索,比较适合用于求解最短路径、最少操作之类的问题。
深度优先
DFS(G)
For each vertex v in G
Do Color[v] = WHITE
Parent[v] = NIL
For each vertex v in G
DFS_Visit(v)
DFS_Visit(u)
Color[u] = GRAY
For each v is the neighbor of u
If Color[v] == WHITE
Parent[v] = u
DFS_Visit(v)
Color[u] = BLACK
回溯
DFS 通常从某个状态开始,根据特定的规则转移状态,直至无法转移(节点为空),然后回退到之前一步状态,继续按照指定规则转移状态,直⾄至遍历完所有状态
回溯法包含了多类问题,模板类似。
排列组合模板->搜索问题(是否要排序,哪些情况要跳过)
使用回溯法的一般步骤:
确定所给问题的解空间:⾸首先应明确定义问题的解空间,解空间中至少包含问题的一个解。
确定结点的扩展搜索规则以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
模式识别
⽤用Backtracking( Top-Down )解决发散结构问题
对于发散性问题(例如“所有组合”,“全部解”),可以选取其问题空间“收敛”的一端作为起点,沿着节点发散的方向(或者说,当前节点的多种选择)进行递归,直到a.当前节点“不合法” 或 b.当前节点发散方向搜索完毕,才会return。
如果需要记录决策的路径,可以用vector<int> &path
沿着搜索的方向记录,在满足胜利条件时记录当前path(通常是将path存入vector<vector<int>> &paths)
。
Backtracking的典型模板c
void backtracking( P node, vector<P> &path, vector<vector<P> >&paths ){
if(!node ) // invalid node
return;
path.push_back(node);
bool success = ; // condition for success
if( success )
paths.push_back( vector<P>(path.begin(),path.end()) ); // don't return here
for( P next: all directions )
backtracking