路径规划题解

路径规划题解
恶心题,加油站怎么都想不到如何处理
所以它先处理加油站之间的不超过k个红绿灯的距离,
再用小于limit的距离见加油站之间的图(转化为到加油站,必加油)

#include<bits/stdc++.h>
using namespace std;
const int N=10002,M=20004,K=12;
const double eps=1e-7;
int n,m,k,s,t,t1,t2,t3,top=0,cnt=0,g[N],head[N*K],head2[N*K];
double a,b,ans=2e18+7,limit,cost,w[N*K],dis[N*K]; 
struct edge{int nxt,to; double w;}e[(M<<1)*K],f[(M<<1)*K];
struct xd{
   double z; int i;
   bool operator < (const xd ww) const {return z>ww.z;} 
}tmp,nw;
inline void add(int u,int v,double w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
inline void add2(int u,int v,double w){f[++cnt].nxt=head2[u],f[cnt].to=v,f[cnt].w=w,head2[u]=cnt;}
inline void add_edge(int u,int v,double www){
   if(fabs(w[v])>eps) for(int i=0;i<k;++i) add(i*n+u,i*n+n+v,www+w[v]);
   else for(int i=0;i<=k;++i) add(i*n+u,i*n+v,www);
}
map<string,int>name;
string ss,st,sw;
priority_queue<xd> q;
void dijkstra(int x,int hd[],edge o[]){
    memset(dis,0x6f,sizeof(dis));
    dis[x]=0,tmp.z=0,tmp.i=x,q.push(tmp);
    while(!q.empty()){
       tmp=q.top(),q.pop();
       if(dis[tmp.i]<tmp.z) continue;
       for(int i=hd[tmp.i];i;i=o[i].nxt){
           nw.i=o[i].to,nw.z=tmp.z+o[i].w;
           if(dis[nw.i]>nw.z) dis[nw.i]=nw.z,q.push(nw);
       }
    }
}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
int main(){
   n=read(),m=read(),k=read(),limit=read(),cost=read();
   for(int i=1;i<=n;++i){
       cin>>ss,a=read(),b=read(),name[ss]=i;
       if(ss=="start") s=i;
       if(ss=="end") t=i;
       if(ss.find("gas")!=string::npos) ++top,g[top]=i;
       if(a) w[i]=a*a/(2.000*(a+b));
   }
   for(int i=1;i<=m;++i) cin>>ss>>sw>>st,t1=name[ss],t2=name[sw],t3=read(),add_edge(t1,t2,t3),add_edge(t2,t1,t3); 
   cnt=0,g[++top]=s,g[++top]=t;
   for(int i=1;i<=top;++i){
       dijkstra(g[i],head,e);
       for(int j=1;j<=top;++j){
           if(i==j) continue;
           a=(g[j]!=s&&g[j]!=t)?cost:0;
           for(int p=0;p<=k;++p) if(dis[p*n+g[j]]<=limit) for(int v=0;v+p<=k;++v) add2(v*n+g[i],(p+v)*n+g[j],dis[p*n+g[j]]+a);
       }
   }
   dijkstra(s,head2,f);
   for(int i=0;i<=k;++i) ans=min(ans,dis[i*n+t]);
   printf("%.3lf",ans); 
   return 0;
}

猜你喜欢

转载自www.cnblogs.com/ljk123-de-bo-ke/p/11837838.html