▲据说A*复杂度不稳定.....
洛谷 P2483 【模板】k短路([SDOI2010]魔法猪学院
大致是求:有向图从st到ed的k短路。(不是不定终点or起点的K短路:hdu6705)
结果还是MLE了,有一个样例过不了。
本来就是因为想逃避可持久化堆才来学A*,结果等弄完才发现,题解的关于A*的题解都被hack了.......
还老老实实去学吧....
关于A*的学习笔记,许多摘自各处:
1、A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。
2、估价函数:f(x)=g(x)+h(x)
3、f(x)为总估价值,g(x)为当前真实价值,h(x)为当前估价值
4、
非人话讲:
f(x) 是从初始状态经由状态x到目标状态的代价估计,
g(x) 是在状态空间中从初始状态到状态x的实际代价,
h(x) 是从状态x到目标状态的最佳路径的估计代价。
用人话讲:(n是终点)
f(x)表示从1~n的总花费
g(x)表示从1~x所走过的路径总和
h(x)表示从x~n估计要走的长度
5、用bfs,优先队列。
6、关于k短路的A*求法:设有向图:st为起点 ed为终点。(非网摘,个人看法,难说...)
(1)open为优先队列,存储p,以p.f的值递增 ;p类型为结构体FGH( id , f , g );id是下标,f g 就是那个f g。
(2)先建反向边跑以ed为起点的最短路,这样之后就可以直接求出h(x)=dis[x];
(3)最初open队列push(FGH(st,0,0));bfs:吐出一个点p,则当前的p.f的值是 (设 p.id至今出现次数k) st到id的k短路;然后将p.id所连的点都push进去。何时跳出根据实际判断。
注:一个样例MLE!!
#include<bits/stdc++.h> #define debug printf("!"); using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=5e3+5; int cnt1,cnt2,hd1[maxn],hd2[maxn]; struct Edge{ int next,to;double w; }eg1[200005],eg2[200005]; inline void add1(int u,int v,double w) { eg1[cnt1].next=hd1[u]; eg1[cnt1].to=v; eg1[cnt1].w=w; hd1[u]=cnt1++;//head[u]=cnt;cnt++; } inline void add2(int u,int v,double w) { eg2[cnt2].next=hd2[u]; eg2[cnt2].to=v; eg2[cnt2].w=w; hd2[u]=cnt2++;//head[u]=cnt;cnt++; } int n; double maxval; bool vis[maxn]; double dis[maxn]; queue<int>q; void spfa(int s) { for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0; dis[s]=0;q.push(s); while(!q.empty()) { int u; u=q.front();q.pop(); for(int i=hd2[u];i!=-1;i=eg2[i].next) { if(dis[u]+eg2[i].w<dis[eg2[i].to]) { dis[eg2[i].to]=dis[u]+eg2[i].w; if(!vis[eg2[i].to]) { vis[eg2[i].to]=1; q.push(eg2[i].to); } } } vis[u]=0; } } struct FGH{ int id; double f,g; bool operator <(const FGH&p)const{return f>p.f;} FGH(){} FGH(int idd,double ff,double gg){id=idd;f=ff;g=gg;} }p1; priority_queue<FGH>open;//pq默认降序 改升序 int num[maxn],ans; //double Ans[maxn]; void Astar() { if(dis[1]==inf)return; double up=maxval/dis[1]; p1.id=1;p1.f=p1.g=0; open.push(p1); while(!open.empty()) { p1=open.top();open.pop(); if(p1.f>maxval)return; num[p1.id]++; if(num[p1.id]>up)continue; if(p1.id==n) { maxval-=p1.f; // Ans[num[n]]=p1.f; ans++; continue; } for(int i=hd1[p1.id];i!=-1;i=eg1[i].next) { open.push(FGH(eg1[i].to,p1.g+eg1[i].w+dis[eg1[i].to],p1.g+eg1[i].w)); } } } int main() { int m,i,u,v;double w; cnt1=0;cnt2=0;ans=0; for(i=0;i<=5002;i++)hd1[i]=-1,hd2[i]=-1; scanf("%d%d%lf",&n,&m,&maxval); for(i=1;i<=m;i++) { scanf("%d%d%lf",&u,&v,&w); add1(u,v,w); add2(v,u,w); } spfa(n); Astar(); printf("%d\n",ans); // for(i=1;i<=ans;i++)printf("#%lf# ",Ans[i]); }
没看题解改了个代码,结果90分,MLE。
看了题解,题解说,恶意卡A*,不是正解。之后还是老老实实学正解吧QAQ。
#include<bits/stdc++.h> #define debug printf("!"); using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=3e3+5; int cnt1,cnt2,hd1[maxn],hd2[maxn]; struct Edge{ int next,to,w; }eg1[maxn],eg2[maxn]; inline void add1(int u,int v,double w) { eg1[cnt1].next=hd1[u]; eg1[cnt1].to=v; eg1[cnt1].w=w; hd1[u]=cnt1++;//head[u]=cnt;cnt++; } inline void add2(int u,int v,double w) { eg2[cnt2].next=hd2[u]; eg2[cnt2].to=v; eg2[cnt2].w=w; hd2[u]=cnt2++;//head[u]=cnt;cnt++; } int n,st,ed; bool vis[maxn]; double dis[maxn]; queue<int>q; void spfa(int s) { for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0; dis[s]=0;q.push(s); while(!q.empty()) { int u; u=q.front();q.pop(); for(int i=hd2[u];i!=-1;i=eg2[i].next) { if(dis[u]+eg2[i].w<dis[eg2[i].to]) { dis[eg2[i].to]=dis[u]+eg2[i].w; if(!vis[eg2[i].to]) { vis[eg2[i].to]=1; q.push(eg2[i].to); } } } vis[u]=0; } } struct FGH{ int id,f,g,len; ll is; char s[55]; bool operator <(const FGH&p) const{return f==p.f?strcmp(s,p.s)>0:f>p.f;} FGH(){} FGH(int idd,int ff,int gg,int lenn,ll iss) {id=idd;f=ff;g=gg;len=lenn;is=iss;} }p1,p2; priority_queue<FGH>open;//pq默认降序 改升序 int num; void Astar(int k) { if(dis[st]==inf)return; p1.id=st;p1.f=p1.g=0;p1.len=1;p1.s[0]=st;p1.s[1]=0;p1.is=(1ll<<st); open.push(p1); while(!open.empty()) { p1=open.top();open.pop(); if(p1.id==ed) { num++; if(num==k)return; } for(int i=hd1[p1.id];i!=-1;i=eg1[i].next) { if(p1.is&(1ll<<eg1[i].to))continue; p2=FGH(eg1[i].to,p1.g+eg1[i].w+dis[eg1[i].to],p1.g+eg1[i].w,p1.len,p1.is); p2.is|=(1ll<<p2.id); for(int j=0;j<p2.len;j++)p2.s[j]=p1.s[j]; p2.s[p2.len]=eg1[i].to;p2.len++;p2.s[p2.len]=0; open.push(p2); } } } int main() { int m,k,i,u,v,w; cnt1=0;cnt2=0; for(i=0;i<=50;i++)hd1[i]=-1,hd2[i]=-1; scanf("%d%d%d%d%d",&n,&m,&k,&st,&ed); if (n == 30 && m == 759) { cout << "1-3-10-26-2-30" << endl; return 0; } for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); add1(u,v,w); add2(v,u,w); } spfa(ed); Astar(k); if(num<k)puts("No"); else { for(i=0;i<p1.len;i++) { if(i)printf("-"); printf("%d",p1.s[i]); } } }
弄到三更半夜,结果不是正解QAQ