搜索入门
搜索算法的原理就是枚举。利用 计算机的高性能,给出人类制定好的规则,枚举出所有可行的情况,找到可行解或者最优解。
搜索算法:
- 深度优先搜索
一般用来求可行解,利用剪枝(通过某种判断,避免一些不必要的搜索过程)进行优化,在树形结构的图上用处较多。
- 广度优先搜索
一般用来求最优解,配合哈希表进行状态空间的标记,从而避免重复状态的计算。
深度优先搜索
一直往下走,走不通回头,还条路再走,直到无路可走;
具体算法:
选择一个起始点u作为当前节点,执行如下操作:
- 访问当前节点,并且标记当前节点已被访问,然后跳转到2;
- 如果存在一个和当前节点相邻并且未被访问的节点v,则将v设为当前节点,执行1;
- 如果不存在这样的节点v,则进行回溯,回溯过程就是回退当前节点。
算法实现:
可以用栈来存储当前节点,也可以用递归的方式来实现,以下是递归的方式;
const int MAXN = 7;
void dfs(int u) {
if(visit[u]) { //标记当前节点是否已被访问,被访问则返回,不被访问则访问,需自己实现的函数
return ;
}
visit[u] = true;
dfs_add(u); //存储当前节点 需自己实现的函数
for(int i = 0; i < MAXN; ++i) {
int v = i;
if(adj[u][v]) { //adj[u][v]为图的邻接矩阵,非0表示连通,0表示不连通
dfs(v);
}
}
}
广度优先搜索
Breadth Fisrt Search,我会分身我怕谁?!
算法步骤:
- 选择一个起始点u放入一个先进先出的队列中,执行如下操作:
- 如果队列不为空,弹出一个队列首元素,记为当前接待您,执行3,否则算法结束;
- 将与当前节点相邻并且尚未被访问的节点的信息进行更新,并且全部放入队列中,继续执行2。
维护广搜的数据结构是队列和哈希表(标记状态),即open-close表。
广搜的最基础应用是用来求图的最短路。
算法实现:
const int inf = -1;
void bfs(int u) {
queue <int> q;
memset(dis, inf, sizeof(dis)); // 初始化路径数组,-1表示无限远
dis[u] = 0;
q.push(u);
while(!q.empty()) {
u = q.front(); // 每次弹出一个元素
q.pop();
for(int v = 1; v <= n; ++v) {
if(!adj[u][v]) continue; // 不连通,跳过
if(dis[v] != inf) continue; // 节点已被访问过,跳过
dis[v] = dis[u] + 1;
q.push(v); //扩展下一个节点
}
}
}
相关题目
题目描述:
给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 a 和 b 的一条无向边,且该边遍历成功的概率为 succProb[i] 。
指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。
如果不存在从 start 到 end 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。
思路:
无向图的最长路问题,边权是概率,所以每次经过都是相乘的关系,由于概率是0-1的小数,所以会越乘越小,所以不存在环的情况;
直接用SPFA求解即可;
class Solution {
#define maxn 10010
//碰到这种问题,首先要建边;
struct Edge {
int to;
double val;
Edge() {}
Edge(int t, double v):to(t), val(v) {}
};
vector<Edge> edge[maxn];
double bfs(int start, int end) {
double dis[maxn];
memset(dis, 0, sizeof(dis));
queue<int> q;
dis[start] = 1;
q.push(start);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < edge[u].size(); ++i) {
int v = edge[u][i].to;
double d = dis[u] * edge[u][i].val;
if (d > dis[v]) { //利用概率为0-1之间的小数,越乘越小的特点
dis[v] = d;
q.push(v);
}
}
}
return dis[end];
}
public:
double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
for (int i = 0; i < succProb.size(); ++ i) {
int u = edges[i][0];
int v = edges[i][1];
double w = succProb[i];
edge[u].push_back(Edge(v, w)); //有向图的处理
edge[v].push_back(Edge(u, w));
}
return bfs(start, end);
}
};