zoukankan      html  css  js  c++  java
  • 6.12友谊赛T4城市交通费题解

    与普通的最短路径不同的是,题目中新引入了一个计入总体的费用——城市建设费。由于城市建设费由整体的某最大值决定,导致解没有最优子结构的性质,给思维带来难度。

    既然最棘手的是城市建设费,我们就对它分类讨论。为了分类有效,我们先把城市繁华度从小到大排个序,这样分类讨论时当前路径的城市的最大繁华度即为不严格递增的。这样,我们便可以考虑当前路径只可能经过前k个最不繁华的城市(可以不经过,但只要经过,经过的城市就一定在那前k个最不繁华的城市中),让k从小到大递增(每次+1)至n,对于每个k值,更新一下最短路径,再看一下第k个最不繁华的城市是否可以更新答案。由此我们想到了FLOYD算法。

    见AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cctype>
     5 #include<cstring>
     6 
     7 using namespace std;
     8 
     9 int ans,n,m,q,a[251][251],f[251][251],p[251],t[251];
    10 
    11 char ch;
    12 
    13 int read()
    14 {
    15     ans=0;
    16     ch=getchar();
    17     while(!isdigit(ch)) ch=getchar();
    18     while(isdigit(ch)) ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    19     return ans;
    20 }
    21 
    22 int cmp(int x,int y)//排序最终效果:把t数组排序,使t数组满足编号为ti的城市是第i个最不繁华的城市 
    23 {
    24     return p[x]<p[y];    
    25 }
    26 
    27 int main()
    28 {
    29 //    freopen("road.in","r",stdin);
    30 //    freopen("road.out","w",stdout);
    31     memset(a,63,sizeof a);//把a数组(存两点间最短路径)初始化为一个足以解题的无穷大 
    32     n=read(),m=read(),q=read();
    33     for(int i=1;i<=n;i++) p[i]=read();
    34     for(int i=1;i<=n;i++) t[i]=i;//一开始t数组应有所有城市的编号,所以不能忘了初始化
    35     int u,v,w;
    36     for(int i=1;i<=m;i++)
    37     {
    38         u=read(),v=read(),w=read();
    39         a[u][v]=min(a[u][v],w);//用邻接矩阵存边不要忘了防重边
    40         a[v][u]=min(a[v][u],w);
    41     }
    42     for(int i=1;i<=n;i++) a[i][i]=0;
    43     for(int i=1;i<=n;i++) //初始化两城市直接连通(路径不经过其他任何城市)的情况 
    44         for(int j=1;j<=n;j++)
    45         f[i][j]=a[i][j]+max(p[i],p[j]);
    46     sort(t+1,t+1+n,cmp);
    47     for(int k=1;k<=n;k++)//当FLOYD的最外层循环枚举到k是,路径经过的中间城市只可能是前k个最不繁华的城市(因为目前只用他们进行了松弛操作) 
    48         for(int i=1;i<=n;i++)
    49             for(int j=1;j<=n;j++)
    50             {
    51                 a[i][j]=min(a[i][j],a[i][t[k]]+a[t[k]][j]);
    52                 f[i][j]=min(f[i][j],a[i][j]+max(p[i],max(p[j],p[t[k]])));
    53             }
    54     for(int i=1;i<=q;i++)
    55     {
    56         u=read();v=read();
    57         printf("%d
    ",f[u][v]);
    58     }
    59     return 0;
    60 }

    总结:算法中有很多细节。初始时的边界条件要记得考虑。如果一开始对某个变量的有要求,就不能忘了初始化。用邻接矩阵存边的话不要忘了去重边。

  • 相关阅读:
    点滴线程(笔记)
    解决问题的思维方式之Problem->Desgin->Solution(笔记)
    阿朱分享:中国互联网十五年的22个创新模式(转)
    .NET JSON对象序列化和反序列化
    Centos防火墙设置
    跨平台的 NodeJS 组件解决 .NetCore 不支持 System.Drawing图形功能的若干问题
    Mysql 多行转一行
    redis中的缓存穿透 缓存击穿 缓存雪崩
    redis持久化
    redis事物
  • 原文地址:https://www.cnblogs.com/InductiveSorting-QYF/p/11014095.html
Copyright © 2011-2022 走看看