A*
简介:
- A∗ A ∗ (Astar),是一种启发式搜索,也是 bfs b f s 的特例。准确说, bfs b f s 是盲目的搜索。
- 那么 A∗ A ∗ 就是让决策优化,
- 实际上,就是预处理终点到起点的最短路,再在起点到终点时判断第 K K 短路。
- 这是一个非常实用的解决第短路问题的算法。
常规操作:
- 先预处理出终点到起点(反图)的最短路(SPFA,Dijs)
- 再通过优先队列来对起点到终点的路径判断第
K
K
短路
Code(模板):
int S,T,K;
struct edge{
int to,cost;
};
vector<edge>E[N],G[N];
int dis[N];
bool vis[N];
queue<int>Q;
void SPFA(){//反图 T->S
while(!Q.empty())Q.pop();
memset(vis,0,sizeof(vis));
memset(dis,0x3f3f3f3f,sizeof(dis));
Q.push(T);
vis[T]=1;
dis[T]=0;
while(!Q.empty()){
int x=Q.front();Q.pop();
vis[x]=0;
for(int i=0;i<(int)G[x].size();++i){
int y=G[x][i].to;
if(dis[y]>dis[x]+G[x][i].cost){
dis[y]=dis[x]+G[x][i].cost;
if(!vis[y]){
vis[y]=1;
Q.push(y);
}
}
}
}
}
struct Anode{
int to,d,all;
bool operator<(const Anode &_)const{
return all==_.all?d>_.d:all>_.all;
}
};
priority_queue<Anode>Star;
int Astar(){//S->T
if(dis[S]==0x3f3f3f3f)return -1;
if(S==T)K++;
int cnt=0;
while(!Star.empty())Star.pop();
Star.push((Anode){S,0,dis[S]});
while(!Star.empty()){
Anode now=Star.top();Star.pop();
int x=now.to;
if(x==T){
cnt++;
if(cnt==K)return now.d;
}
for(int i=0;i<(int)E[x].size();i++){
int y=E[x][i].to;
Star.push((Anode){y,now.d+E[x][i].cost,now.d+E[x][i].cost+dis[y]});
}
}
return-1;
}
Summary:
- 算法针对于第
K
K
短路非常实用,但其本身还是有缺陷,可以被卡成。
- 对于较大的数据,还是左偏树可并堆解决的了… 但写法还是非常方便的。
例题:POJ2449 Remmarguts’ Date
Description:
n个点,m条边的有向图,求s到t的第k短路。
Solution:
- A*算法解决第k短路裸题。
Code:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<cstdlib> using namespace std; #define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;i++) #define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;i++) #define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;i--) #define db double #define LL long long #define INF 0x3f3f3f3f #define MINF 0xc0c0c0c0 #define inf 0x3f3f3f3f3f3f3f #define Sz(a)sizeof(a) #define mcl(a,b)memset(a,b,Sz(a)) #define mcp(a,b)memcpy(a,b,Sz(b)) #define pb push_back #define fi first #define se second template<class T>inline bool chkmin(T&x,T y){return y<x?x=y,1:0;} template<class T>inline bool chkmax(T&x,T y){return x<y?x=y,1:0;} inline LL Max(LL x,LL y){return x>y?x:y;} inline LL Min(LL x,LL y){return x<y?x:y;} typedef pair<int,int>PII; #define N 1002 #define M 500002 int n,m; int S,T,K; int qwq1,qwq2,head1[N],head2[N]; struct edge{ int to,next,cost; }E[M],G[M]; void addedge(int x,int y,int z){ E[qwq1]=(edge){y,head1[x],z};head1[x]=qwq1++; G[qwq2]=(edge){x,head2[y],z};head2[y]=qwq2++; } int dis[N]; bool vis[N]; queue<int>Q; struct Anode{ int to,d,all; bool operator<(const Anode &_)const{ return all==_.all?d>_.d:all>_.all; } }; priority_queue<Anode>Star; void SPFA(){ while(!Q.empty())Q.pop(); mcl(dis,INF); mcl(vis,0); Q.push(T); dis[T]=0; vis[T]=1; while(!Q.empty()){ int x=Q.front();Q.pop(); vis[x]=0; for(int i=head2[x];~i;i=G[i].next){ int y=G[i].to; if(chkmin(dis[y],dis[x]+G[i].cost)){ if(!vis[y]){ vis[y]=1; Q.push(y); } } } } } int Astar(){ int cnt=0; if(S==T)K++; if(dis[S]==INF)return-1; while(!Star.empty())Star.pop(); Star.push((Anode){S,0,dis[S]}); while(!Star.empty()){ Anode now=Star.top();Star.pop(); int x=now.to; if(x==T){ cnt++; if(cnt==K)return now.d; } for(int i=head1[x];~i;i=E[i].next){ int y=E[i].to; Star.push((Anode){y,now.d+E[i].cost,now.d+E[i].cost+dis[y]}); } } return-1; } void Clear(){ qwq1=qwq2=0; mcl(head1,-1); mcl(head2,-1); } int main(){ // printf("sz=%d\n",(Sz(E)*2+Sz(dis)*2+Sz(Star)+Sz(Star))/1024/1024); while(~scanf("%d%d",&n,&m)){ Clear(); REP(i,1,m){ int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); } scanf("%d%d%d",&S,&T,&K); SPFA(); printf("%d\n",Astar()); } return 0; }