Astar 搜索算法
Astar A* 算法路径搜索应用
在求解路径问题时,往往会搜索许多不必要的路径,计算机无法简单地实现人的宏观思维
所以,可以给当前需要搜索的路径增设一个估价函数,令计算机判断当前的最优解,这样可以节省许多不必要的时间开支
估价函数预处理出每个状态到目标状态的所需代价的估计值 \(f(x)\),实际值为 \(g(x)\),应当满足估计值不大于实际值 \(f(x)\le g(x)\) (越接近越准确),这样的带有估价函数的优先队列 BFS 叫做 Astar 算法
在 BFS 过程中,维护一个堆,每次取出堆中 当前代价+未来估价 的最小状态进行扩展
例如求解第 \(K\) 短路问题:给定 \(n\) 个节点与 \(m\) 条边的有向图,求从 \(s\) 到 \(t\) 的第 \(K\) 短路
未来估价函数的计算
设 \(f_i\) 表示第 \(i\) 个节点到 \(t\) 的距离,这里可以通过 Dijkstra 算法,以 \(t\) 为起点 \(s\) 为终点跑一遍,最后可以计算出精确的 \(f_i=g_i\)
注意需要额外存一张反向图,这里以 rhe
表示
struct edge{ long long v,w; }; vector<edge> rhe[5010]; void dijkstra(void){ priority_queue<pair<long long,long long>> q; memset(f,0x3f,sizeof f); f[t]=0; q.push({0,t}); while (q.size()){ auto t=q.top(); q.pop(); if (vis[t.second]) continue; vis[t.second]=1; for (auto iter:rhe[t.second]){ if (f[iter.v]>f[t.second]+iter.w){ f[iter.v]=f[t.second]+iter.w; q.push({-f[iter.v],iter.v}); } } } }
Astar的实现
正向跑一边优先队列的 BFS,堆中维护三元组 \(\{dis_{s,i}+f_i,i,d\}\),按照 \(dis_{s,i}+f_i\) 从小到大排序
分别表示: \(s\) 到 \(i\) 的距离 + \(i\) 到 \(t\) 的未来估价函数,\(i\) 点编号,\(d\) 记录的总路径长度
在过程中,我们只允许每个点最多入队 \(K\) 次,当 \(t\) 节点第 \(K\) 次出队时,对应三元组中的 \(d\) 就为所求的第 \(K\) 短路
long long astar(void){ priority_queue<node> q; q.push({f[S],S,0}); while (q.size()){ auto t=q.top(); q.pop(); cnt[t.v]++; if (cnt[T]==K)//终点出队k次 return t.d; for (auto iter:he[t.v]) if (cnt[iter.v]<K) q.push({t.d+iter.w+f[iter.v],iter.v,t.d+iter.w}); } return -1; }
如果需要求严格的第 \(K\) 短路,即当路径长度不同时才算为不同的第 \(K\) 短路,需要增设一个变量记录上一次的答案
如果这一次得到路径长度与上一次相同,那么就需要令 \(K+1\)(当前的路径无效)
struct node{ long long s,v,d; bool operator<(const node&x)const{ return s>x.s; }//重载运算符,使优先队列按照s从小到大排列 }; long long mem=-1; long long astar(void){ priority_queue<node> q; q.push({f[s],s,0}); while (q.size()){ auto t=q.top(); q.pop(); if (t.v==K){ if (mem==t.d) K++; else mem=t.d; } cnt[t.v]++; if (cnt[T]==K) return t.d for (auto iter:he[t.v])//he表示正向图 if (cnt[iter.v]<K) q.push({t.d+iter.w+f[iter.v],iter.v,t.d+iter.w}); } return -1; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通