Repairing a Road NBUT

来源:互联网 发布:积分系统数据库设计 编辑:程序博客网 时间:2024/06/10 01:24

枚举每条边,那么耗费时间就是dis(1, x) + (t - dis(1, x)) + vi * ai ^ (-t) + dis(y, C) ,dis代表u到v的最短路,可知因为是最短路,1到u和v到c肯定不会经过(u,v)这条边,所以求出t-vi*ai^(-t)的最小值就可以了,t的范围(dis(1,x),dis(1,c)) 

求导求零点就行了,f'(t) = 1 - ln(ai) * vi * ai ^ (-t)

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <vector>#include <map>#include <cmath>#include <set>#include <queue>using namespace std;const int INF=1e9+10;const double EPS = 1e-10;  typedef long long ll;double mp[105][105];struct t{int x,y;double v,a;t(){};t(int xx,int yy,double vv,double aa){x=xx;y=yy;v=vv;a=aa;};}edge[105];double erfen(double l,double r,double a,double v){for(int i=0;i<10;i++){double mid=(l+r)/2.0;if(1.0-1.0*log(a)*v*pow(a,-mid)<0) l=mid;else r=mid;}return l+v*pow(a,-l);}int main(){    //freopen("out.txt","w",stdout);int c,r;while(scanf("%d %d",&c,&r)&&c&&r){for(int i=0;i<=c;i++)for(int j=0;j<=c;j++)if(i!=j)mp[i][j]=INF;else mp[i][j]=0.0;for(int i=0;i<r;i++){int x,y;double v,a;scanf("%d %d %lf %lf",&x,&y,&v,&a);mp[x][y]=mp[y][x]=v;edge[i]=t(x,y,v,a);}for(int k=1;k<=c;k++)for(int i=1;i<=c;i++)for(int j=1;j<=c;j++)mp[i][j]=min(mp[i][j],mp[i][k]+mp[j][k]);//f'(t) = 1 - ln(ai) * vi * ai ^ (-t)double ans=mp[1][c];for(int i=0;i<r;i++){ans=min(ans,mp[edge[i].x][c]+erfen(mp[1][edge[i].y],ans,edge[i].a,edge[i].v));ans=min(ans,mp[edge[i].y][c]+erfen(mp[1][edge[i].x],ans,edge[i].a,edge[i].v));}printf("%.3f\n",ans );}    return 0;  }


原创粉丝点击