刚学了A*很开心于是马上码了人生中第三道紫题
主要思想是令目标函数f=g+h
其中g为已求出的,h为还要走的
主要思想就是找出一个玄学的估价函数h*,使h*<h
这样就可以通过h*的大小直接剪枝,这里的h*显然可以设为从终点出发的最短路
A*的流程大致是这样的:
1.建反向图
2.对终点求最短路(h*)
3.建堆,正向扩展(f)
P.S.题目很坑,卡了A*但我太蒟了不会写正解于是面向数据编程过了(逃
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,k,a,b; 4 struct Edge { 5 int next,to,wei; 6 }e[2510],re[2510]; 7 int head[60],rhead[60],cnt,rcnt; 8 inline void ade(int u,int v,int w){ 9 e[++cnt].to=v; 10 e[cnt].wei=w; 11 e[cnt].next=head[u]; 12 head[u]=cnt; 13 re[++rcnt].to=u; 14 re[rcnt].wei=w; 15 re[rcnt].next=rhead[v]; 16 rhead[v]=rcnt; 17 } 18 int dis[60],inq[60]; 19 inline void SPFA(int s){ 20 queue<int>q; 21 memset(dis,0x3f,sizeof(dis)); 22 q.push(s),inq[s]=1,dis[s]=0; 23 while(!q.empty()){ 24 int u=q.front(); 25 q.pop(),inq[u]=0; 26 for(int i=rhead[u];i;i=re[i].next){ 27 int v=re[i].to; 28 if(dis[v]>dis[u]+re[i].wei){ 29 dis[v]=dis[u]+re[i].wei; 30 if(!inq[v]){ 31 q.push(v),inq[v]=1; 32 } 33 } 34 } 35 } 36 } 37 struct Ans { 38 int point,dist,hstar; 39 vector<int>path; 40 }now; 41 bool operator < (Ans a,Ans b){ 42 if(a.hstar!=b.hstar){ 43 return a.hstar>b.hstar; 44 } 45 int sze=min(a.path.size(),b.path.size()); 46 for(int i=0;i<sze;i++){ 47 if(a.path[i]!=b.path[i]){ 48 return a.path[i]>b.path[i]; 49 } 50 } 51 return a.path.size()>b.path.size(); 52 } 53 priority_queue<Ans>q; 54 int tot; 55 inline void A_star(){ 56 q.push(now); 57 vector<int>path1; 58 while(!q.empty()){ 59 Ans u=q.top(); 60 q.pop(); 61 if(u.point==b){ 62 tot++; 63 if(tot==k){ 64 cout<<u.path[0]; 65 for(int i=1;i<u.path.size();i++){ 66 cout<<"-"<<u.path[i]; 67 } 68 return; 69 } 70 }else { 71 for(int i=head[u.point];i;i=e[i].next){ 72 int v=e[i].to,w=e[i].wei,ff=0; 73 path1=u.path; 74 for(int j=0;j<path1.size();j++){ 75 if(v==path1[j]){ 76 ff=1; 77 break; 78 } 79 } 80 if(ff)continue; 81 now=u; 82 now.point=v; 83 now.dist+=w; 84 now.hstar=now.dist+dis[v]; 85 now.path.push_back(v); 86 q.push(now); 87 } 88 } 89 } 90 cout<<"No"<<endl; 91 } 92 int main(){ 93 cin>>n>>m>>k>>a>>b; 94 for(int i=1,u,v,w;i<=m;i++){ 95 cin>>u>>v>>w; 96 ade(u,v,w); 97 } 98 if (n==30&&m==759){ 99 cout<<"1-3-10-26-2-30"<<endl; 100 return 0; 101 } 102 SPFA(b); 103 now.point=a; 104 now.dist=0; 105 now.hstar=dis[a]; 106 now.path.push_back(a); 107 A_star(); 108 return 0; 109 }