[毁灭世界的01]城市交通

【描述】

某城市有N1<=N<=50)个街区,某些街区由公共汽车线路相连,如在图1中,街区12有一条公共汽车线路相连,且由街区1至街区2的时间为34分钟。由于街区与街区之间的距离较近,与等车时间相比可忽略不记,所以这个时间为两趟公共汽车的间隔时间,即平均的等车时间。

由街区1至街区5的最快走法为1-3-5,总时间为44分钟。

现在市政府为了提高城市交通质量,决定加开M(1<=M<=10)条公共汽车线路。若在某两个街区A,B之间加开线路(前提是AB之间必须已有线路),则从AB的旅行时间缩小为原来的一半(距离未变,只是等车的时间缩短了一半)。例如,若在12之间加开一条线路,则时间变为17分钟,加开两条线路,时间变为8.5分钟,以此类推。所有的线路都是环路,即如果由12的时间变为17分钟,则由21的时间也变为17分钟。

求加开某些线路,能使由城市1至城市N的时间最少。例如,在图1中,如果M=2,则改变1-3,3-5的线路,总的时间可以减少为22分钟。

[毁灭世界的01]城市交通

【输入格式】

输入文件名为City.Inp

第一行为城市数N与加开线路数M

第二行至第N+1行,每行为N个实数,第I+1行第J列表示由城市I到城市J的时间。

如果时间为0,则城市I不可能到城市J

注意:输入数据中,从城市1到城市N至少有一条路线。

【输出格式】

输出文件名为City.Out.

第一行为由城市1到城市N的最小时间X(保留小数点后两位)。

第二行至第M+1行为更改的线路。每行由两个整数(x,y)构成。表示将城市x与城市y之间增加一条线路。

【样例输入】

52

034 24 0 0

340 10 12 0

2410 0 16 20

012 16 0 30

00 20 30 0

【样例输出】

22.00

13

35

【分析】

乍一看…………没感觉。完全不知道怎么解决。

开始想图结构的经典算法。当想到floyd的时候,突然发现,可以将floyd变化一下,然后就有点资源分配的感觉。于是一个算法出来了。第一次提交,50分。小看了下题解,和自己想的一样。但是就是不知道哪里错了。然后,想了一节课。发现动归过程的g应该从0开始,因为不加汽车也是可以有点之间距离的更新的。动归数组f[i][j][k]表示从i到j共加k条所能达到的最短路。方程很好理解。输出顺序题目没说,我就用最简单的方法输出了。恩,AC。

#include <stdio.h>

#define maxn 60

#define maxm 20

#define maxint 1000000000



double f[maxn][maxn][maxm];

int from[maxn][maxn][maxm][2];

int n,m;



void print(int a,int b,int c)

{

    if (!from[a][b][c][0])

        for (int i=1;i<=c;++i) printf("%d %d",a,b);

    else

    {

        print(a,from[a][b][c][0],from[a][b][c][1]);

        print(from[a][b][c][0],b,c-from[a][b][c][1]);

    }

}



int main()

{

    freopen("city.in","r",stdin);

    freopen("city.out","w",stdout);

    

    scanf("%d%d",&n,&m);

    for (int i=1;i<=n;++i)

        for (int j=1;j<=n;++j)

        {

            scanf("%lf",&f[i][j][0]);

            if (!f[i][j][0]) f[i][j][0]=maxint;

        }

    for (int g=1;g<=m;++g)

        for (int i=1;i<=n;++i)

            for (int j=1;j<=n;++j)

                if (f[i][j][0]<maxint)

                    f[i][j][g]=f[i][j][g-1]/2;

                else f[i][j][g]=maxint;

    for (int g=0;g<=m;++g)

        for (int k=1;k<=n;++k)

            for (int i=1;i<=n;++i)

                if (i!=k)

                    for (int j=1;j<=n;++j)

                        if ((i!=j)&&(j!=k))

                            for (int t=0;t<=g;++t)

                                if (f[i][k][t]+f[k][j][g-t]<f[i][j][g])

                                {

                                    from[i][j][g][0]=k;

                                    from[i][j][g][1]=t;

                                    f[i][j][g]=f[i][k][t]+f[k][j][g-t];

                                }

    printf("%.2lf\n",f[1][n][m]);

    print(1,n,m);

    return 0;

}



 

 





你可能感兴趣的:(交通)