DFS核心代码:
关于dfs参数问题,什么在变化,就把什么设置成参数。
- 如果要求输出所有可能的解,往往都是要用深度优先搜索。
- 如果是要求找出最优的解,或者解的数量,往往可以使用动态规划。
void dfs()//参数用来表示状态
if(到达终点状态)
{
...//根据题意添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改全局变量;//根据题意来添加
visit标记;
dfs();
恢复全局变量//回溯部分
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
}
}
全排列问题
先给一个正整数 ( 1 < = n < = 10 )
例如n=3,所有组合,并且按字典序输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#include<iostream>
#include<cmath>
using namespace std;
void combineDfs(int dep, vector<int> &cur, vector<vector<int>> &res, int len, int vis[]){
if(dep == len + 1)//到达终点状态
{
res.push_back(cur);
return ;
}
for(int i = 1; i <= len; ++i){
if(vis[i] == false)//扩展方式所达到状态合法(结点可访问
//if(vis[i]==false&& i>cur[dep])剪枝后一个进入的要比当前的大
{
vis[i] = true;
cur.push_back(i);//当前层数用某个,若层数返回记得退回
combineDfs(dep+1, cur, res, len, vis);
//一趟深搜结束,还原标记下次还可用来深搜
cur.pop_back();
vis[i] = false;//结点是否可重复使用
}
}
}
int main(){
int vis[10] = {0};
int n;
n = 3;
vector<int> cur;
vector<vector<int>> res1;
combineDfs(1, cur, res1, n, vis);
return 0;
}
回文字符串问题
类似全排列,亦是for 1:len展开所有
bool isPalindrome(string s){
return s == string(s.rbegin(), s.rend());
}
void palindromeDfs(string s, vector<string> &cur, vector<vector<string>> &res){
if(s == ""){
res.push_back(cur);
return ;
}
//展开方式,每次从0开始取i个单位当子串
for (int i = 1; i <= s.size(); ++i) {
string sub = s.substr(0, i);
if (isPalindrome(sub)) {
cur.push_back(sub);
//当前是回文,从i开始再取len-i个子串
palindromeDfs(s.substr(i, s.size() - i), cur, res);
cur.pop_back();
}
}
}
vector<vector<string>> partition(string s){
vector<vector<string>> res;
vector<string> cur;
palindromeDfs(s, cur, res);
return res;
}
BFS:
最典型的模版就是树的层序遍历:
void levelOrder(TreeNode* root){
if(root == NULL) return;
queue<TreeNode*> que;//初始化队列Q
TreeNode* cur = NULL;
que.push(root);//Q=起点
while (!que.empty()) {
cur = que.front();//取队首元素出队
que.pop();
cout << cur->val << " ";
if(cur->left) que.push(cur->left);//满足目标状态
if(cur->right) que.push(cur->right);
}
return;
}
矩阵中的路径问题:
int h[606][606];
const int mm = pow(10,9);
class point {
public:
int x, y;
point(int a, int b) :x(a), y(b){}
};
int maina()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> h[i][j];
}
}
int x, y, z, w;
cin >> x >> y >> z >> w;
queue<point> q;
q.push(point(x, y));
int count = 0;
while (!q.empty()) {
point cur = q.front();
q.pop();
if (cur.x == z && cur.y == w) {
++count;
count %= mm;
}
if (cur.x - 1 >= 0 && h[cur.x - 1][cur.y] > h[cur.x][cur.y])
q.push(point(cur.x - 1, cur.y));
if (cur.x + 1 < n && h[cur.x + 1][cur.y] > h[cur.x][cur.y])
q.push(point(cur.x + 1, cur.y));
if (cur.y - 1 >= 0 && h[cur.x][cur.y - 1] > h[cur.x][cur.y])
q.push(point(cur.x, cur.y - 1));
if (cur.y + 1 < m && h[cur.x][cur.y + 1] > h[cur.x][cur.y])
q.push(point(cur.x, cur.y + 1));
}
cout << count << endl;
return 0;
}
BFS和DFS对比
- DFS多用于连通性问题因为其运行思想与人脑的思维很相似,故解决连通性问题更自然。
- BFS多用于解决最短路问题,其运行过程中需要储存每一层的信息,所以其运行时需要储存的信息量较大,如果人脑也可储存大量信息的话,理论上人脑也可运行BFS。
多数情况运行BFS所需的内存会大于DFS需要的内存(DFS一次访问一条路,BFS一次访问多条路)。