zoukankan      html  css  js  c++  java
  • 湖南省第6届程序大赛 Repairing a Road

    Problem G

    Repairing a Road

    You live in a small town with R bidirectional roads connecting C crossings and you want to go from crossing 1 to crossing C as soon as possible. You can visit other crossings before arriving at crossing C, but it’s not mandatory.

    You have exactly one chance to ask your friend to repair exactly one existing road, from the time you leave crossing 1. If he repairs the i-th road for t units of time, the crossing time after that would be viai-t. It's not difficult to see that it takes vi units of time to cross that road if your friend doesn’t repair it.

    You cannot start to cross the road when your friend is repairing it.

    Input

    There will be at most 25 test cases. Each test case begins with two integers C and R (2<=C<=100, 1<=R<=500). Each of the next R lines contains two integers xi, yi (1<=xi, yi<=C) and two positive floating-point numbers vi and ai (1<=vi<=20,1<=ai<=5), indicating that there is a bidirectional road connecting crossing xi and yi, with parameters vi and ai (see above). Each pair of crossings can be connected by at most one road. The input is terminated by a test case with C=R=0, you should not process it.

    Output

    For each test case, print the smallest time it takes to reach crossing C from crossing 1, rounded to 3 digits after decimal point. It’s always possible to reach crossing C from crossing 1.

    Sample Input

    Output for the Sample Input

    3 2

    1 2 1.5 1.8

    2 3 2.0 1.5

    2 1

    1 2 2.0 1.8

    0 0

    2.589

    1.976

    题意:给C个顶点(从1开始编号), R条边, 的无向图. 其中每条边上有起点, 终点, 时间权值vi, 和另一参数ai。如果这道路总共修了t时间,那么这条路的花费就会变成 vi * ai ^ (-t)。我们要从1走到C,求最小花费(花费就是时间)。

    思路: 先用floyd把每两点间的最短距离算出, 判断出这俩点是否相通,如果相通的话,暴力枚举每条可以用于节省时间的边。

      1 #include <iostream>
      2 #include <cmath>
      3 #include <cstdio>
      4 #define LL long long
      5 #include <cstring>
      6 #define INF 100000000000
      7 #include <queue>
      8 #define eps (1e-6)
      9 
     10 using namespace std;
     11 typedef struct edge
     12 {
     13     LL from,to;
     14     double v,a;
     15 }edge;
     16 double cost[110][110];//floyd,cost 用于存储两点间的最短路
     17 queue<edge> que;//用于暴力枚举每一条两点间的最短边
     18 LL N,R;//N,R分别是顶点和边的数目
     19 double sum;
     20 void init()
     21 {
     22     while (!que.empty())
     23         que.pop();
     24     for (int i=1;i<=N;i++)
     25     {
     26         for(int j=1;j<=N;j++)
     27         {
     28             if (i==j)
     29                 cost[i][j]=0;
     30             else
     31                 cost[i][j]=INF;
     32         }
     33     }
     34 }
     35 void input()
     36 {
     37     edge e;
     38     LL temp;
     39     for (int i=1;i<=R;i++)
     40     {
     41         scanf("%I64d %I64d %lf %lf",&e.from,&e.to,&e.v,&e.a);
     42         if (e.v<cost[e.from][e.to])
     43             cost[e.from][e.to]=e.v;//无向图,双向边
     44         if (e.v<cost[e.to][e.from])
     45             cost[e.to][e.from]=e.v;//不考虑修路效果情况下,最短路由e.v构成
     46         que.push(e);
     47         temp=e.from;
     48         e.from=e.to;
     49         e.to=temp;
     50         que.push(e);
     51     }
     52 }
     53 void floyd()
     54 {
     55     for (int k=1;k<=N;k++)
     56     {
     57         for (int i=1;i<=N;i++)
     58         {
     59             for (int j=1;j<=N;j++)
     60             {
     61                 cost[i][j]=min(cost[i][k]+cost[k][j],cost[i][j]);
     62             }
     63         }
     64     }
     65 }
     66 void solve()
     67 {
     68     edge e;
     69     double limit;//记录对于每条边递增函数的起点
     70     while (!que.empty())
     71     {
     72         e=que.front();que.pop();
     73         if (abs(e.a-1)>eps)//防止出现除零错误
     74             limit=log(e.v*log(e.a))/log(e.a);  
     75         else   //数学计算:y = t + v*a^(-t); => y'=1+(-v*a^(-t)ln(a))=0; => a^t=v*ln(a); => t=log(a,v*ln(a))=log(e,v*ln(a))/log(e,a);                                  
     76             limit=0;
     77         if (cost[1][e.from]<limit)
     78         { //sum = min( min(1->e.from) + f(e.from,e.to) + min(e.to->N) )  e:所有可能的边,考虑方向,所以e入队时做了处理                         
     79             if (limit+e.v*pow(e.a,-limit)+cost[e.to][N] < sum)
     80                 sum=limit+e.v*pow(e.a,-limit)+cost[e.to][N];
     81         }
     82         else
     83         {
     84             limit=cost[1][e.from];
     85             if (limit+e.v*pow(e.a,-limit)+cost[e.to][N] < sum)
     86                 sum=limit+e.v*pow(e.a,-limit)+cost[e.to][N];
     87         }
     88     }
     89 }
     90 int main()
     91 {
     92     while (scanf("%I64d%I64d",&N,&R)==2&&(R||N))
     93     {
     94         init();
     95         input();
     96         floyd();
     97         sum=cost[1][N];
     98         solve();
     99         printf("%.3lf
    ",sum);
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    刷题-力扣-剑指 Offer 22. 链表中倒数第k个节点
    刷题-力扣-617. 合并二叉树
    刷题-力扣-1109. 航班预订统计
    刷题-力扣-606. 根据二叉树创建字符串
    刷题-力扣-563. 二叉树的坡度
    扛把子组20191017-8 alpha week 2/2 Scrum立会报告+燃尽图 07
    20191017-7 alpha week 2/2 Scrum立会报告+燃尽图 06
    20191017-6alpha week 2/2 Scrum立会报告+燃尽图 05
    扛把子组20191017-5 alpha week 2/2 Scrum立会报告+燃尽图 04
    记第一次 团建
  • 原文地址:https://www.cnblogs.com/52why/p/5840998.html
Copyright © 2011-2022 走看看