搜索-BFS之A Star算法学习笔记
\(A*算法:bfs + 估价函数\)
总代价=当前代价+未来估价
1. 估价函数
1.1 \(f(x) \le g(x)\)
-
\(f(x) 从状态x到目标状态的\ 估价\)
-
\(g(x) 从状态x到目标状态的\ 实际代价\)
1.2 Kth路
常规思路:\(BFS\),使用优先队列代替传统队列,每次选择距离最近的。但是,这是贪心,策略显然错误。
正解:仍然\(BFS\),使用优先队列代替传统队列,每次选择距离最近的。而在插入优先队列的时候,将实际代价替换为总代价。
#include<bits/stdc++.h>
#include<cctype>
#pragma GCC optimize(2)
#define in(a) a = read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n')
#define ll long long
#define rg register
#define New int
using namespace std;
namespace IO_Optimization{
inline New read()
{
New X = 0,w = 0;
char ch = 0;
while(!isdigit(ch))
{
w |= ch == '-';
ch=getchar();
}
while(isdigit(ch))
{
X = (X << 3) + (X << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -X : X;
}
char F[200] ;
inline void write(New x) //快速输出 空间
{
if(x == 0)
{
putchar('0');
return;
}
New tmp = x > 0 ? x : -x;
int cnt = 0;
if(x < 0)
putchar( '-' );
while(tmp > 0)
{
F[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while(cnt > 0)
putchar(F[--cnt]) ;
}
#undef New
}
using namespace IO_Optimization;
const int N = 100000 + 2;
int n, m, s, t, k, x, y, z, len, p;
int dis[N], nxt, val, tot[N];
struct Node
{
int num, dist;
inline bool operator <(const Node &nxt)const{
return dist > nxt.dist;
}
};
vector<Node> nei[N];
vector<Node> e[N];
bool vis[N];
inline void Dijkstra(int start)
{
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(vis,false,sizeof(vis));
priority_queue<Node>q;
Node cur = {start,0};
q.push(cur);
dis[start] = 0;
vis[start] = true;
while(!q.empty())
{
cur = q.top();
q.pop();
p = cur.num;
vis[p] = false;
len = nei[p].size();
for(rg int i = 0;i < len; ++i)
{
nxt = nei[p][i].num;
val = nei[p][i].dist;
if(dis[nxt] > dis[p] + val)
{
dis[nxt] = dis[p] + val;
if(!vis[nxt])
{
Node tmp = {nxt,dis[nxt]};
q.push(tmp);
vis[nxt] = true;
}
}
}
}
return;
}
inline void A_star(int s)
{
priority_queue<Node>q;
Node now = {s, 0 + dis[s]};
if(s == t)
++k;
q.push(now);
while(!q.empty())
{
int x = q.top().num;
int dist = q.top().dist - dis[x];
q.pop();
++tot[x];
if(tot[t] == k)
{
outn(dist);
return ;
}
int len = e[x].size();
for(rg int i = 0; i < len; ++i)
{
int nxt = e[x][i].num;
int val = e[x][i].dist;
if(tot[nxt] < k)
{
Node tmp = {nxt, dist + val + dis[nxt]};
q.push(tmp);
}
}
}
puts("-1");
return ;
}
int main()
{
in(n), in(m);
for(rg int i = 1;i <= m; ++i)
{
in(x), in(y), in(z);
Node u1 = {x, z};
nei[y].push_back(u1);
Node u2 = {y, z};
e[x].push_back(u2);
}
in(s), in(t), in(k);
Dijkstra(t);
A_star(s);
return 0;
}
iddfs
适用的题目:
- 答案层次可以直接或间接地知道(较浅)
- 新增节点随着层次快速增加
劣势:每一次都要从根节点重新搜索
伪代码:
inline bool dfs(int cen)
{
if(cen == dep)
{
if(存在合法答案)
return true;
return false;
}
for(cen->next)
if(dfs(next) == true)
return true;
}
while(dfs(toor) == false)
++dep;
cout<<dep;