NKOJ 挖隧道【最短路】

在这里插入图片描述


唯有极上与极下挖隧道:

#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=1e4+5;
const ll Inf=1e18;

ll n,vis[N];db vw,vc,x[N],y[N],dis[N];
ll cnt,to[N<<1],nxt[N<<1],head[N];db edge[N<<1];

void ins(ll x,ll y,db z) {
	to[++cnt]=y;edge[cnt]=z;nxt[cnt]=head[x];head[x]=cnt;
}

void spfa(ll s) {
	queue<ll>q;
	rep(i,1,n) dis[i]=1.0*Inf;
	q.push(s);vis[s]=1;dis[s]=0.0;
	while(q.size()) {
		int x=q.front();q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=nxt[i]) {
			ll y=to[i];db z=edge[i];
			if(dis[x]+z<dis[y]) {
				dis[y]=dis[x]+z;
				if(!vis[y]) {
					vis[y]=1;q.push(y);
				}
			}
		}
	}
}

int main() {
	scanf("%lld%lf%lf",&n,&vw,&vc);
	
	rep(i,1,n) scanf("%lf%lf",&x[i],&y[i]);
	
	rep(i,1,n-1) {
		db time=(sqrt(pow((x[i]-x[i+1]),2)+pow((y[i]-y[i+1]),2)))/vw;ins(i,i+1,time);
		
		if(y[i+1]>y[i]) { 
        	ll j=i+1;
        	
            while(j<=n&&y[j]>y[i])j++;if(j>n)continue; 
            db k=(y[j-1]-y[j])/(x[j-1]-x[j]),b=y[j]-k*x[j],xx=(y[i]-b)/k,yy=y[i]; 
            
            time=((xx-x[i])/vc+sqrt((x[j]-xx)*(x[j]-xx)+(y[j]-yy)*(y[j]-yy))/vw); 
            
            ins(i,j,time);
        } 
	}
	
	repd(i,n,2) {
		if(y[i-1]>y[i]) { 
            ll j=i-1; 
            
            while(j>=1&&y[j]>y[i])j--;if(j<1)continue; 
            db k=(y[j+1]-y[j])/(x[j+1]-x[j]),b=y[j]-k*x[j],xx=(y[i]-b)/k,yy=y[i]; 
            
            db time=((x[i]-xx)/vc+sqrt((x[j]-xx)*(x[j]-xx)+(y[j]-yy)*(y[j]-yy))/vw); 
            
            ins(j,i,time);
        } 
	}
	
	spfa(1);
	
	printf("%.6lf",dis[n]);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/82776636