PTA 07-图6 旅游规划(25 分)

PTA 07-图6 旅游规划(25 分)

题目描述:

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

  • 输入格式:
    输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
  • 输出格式:
    在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

易错分析:
在这里建高速公路应该认为是一个无向图,因此在建立的时候用邻接矩阵时两个方向都要初始化。

解题方法:
本题可以采用Dijkstra算法计算单源最短路径,不过需要稍加修改,就是当出现路径相同的时候,需要对成本花费进行判断,如果成本变小,就更新路径和成本。


程序:

#include <stdio.h>
#include <stdlib.h>
#define MAXVERTEX 501
#define INFINTE 65536   

int dist[MAXVERTEX] = {INFINTE};    // 保存单源最短距离
int collected[MAXVERTEX] = {false}; // 保存城市访问信息
int path[MAXVERTEX] = {-1};         // 保存城市之间的路径
int cost[MAXVERTEX];                // 保存单源最短成本
int MDist[MAXVERTEX][MAXVERTEX];    // 保存两个点之间的距离
int MCost[MAXVERTEX][MAXVERTEX];    // 保存两个点之间的成本


int FindMinDist(int Nv)
{   /* 寻找最短路径 */
    int MinDist = INFINTE, V, Min;  // 保存最小边的距离
    for (V = 0; V < Nv; V++)
    {
        if (collected[V] == false && dist[V] < MinDist)
        {   /* 如果找到符合条件的顶点 */
            MinDist = dist[V];  // 更新最短距离
            Min = V;    // 更新顶点下标
        }
    }
    if (MinDist < INFINTE)  // 说明找到了
        return Min;
    else    // 如果没找到
        return 0;
}

void Dijkstra(int Nv, int S)
{   /* 寻找最短路并且成本最小化*/
    for (int v = 0; v < Nv; v++)
    {
        dist[v] = MDist[S][v];
        cost[v] = MCost[S][v];
        if (dist[v] < INFINTE)  // 如果有路径,更新v的路径
            path[v] = S;
        else
            path[v] = -1;
    }
    /* 把原点收入进集合 */
    collected[S] = true;
    path[S] = -1;
    dist[S] = 0;

    while (1)
    {
        int Vertex = FindMinDist(Nv);
        if (!Vertex)
            break;
        collected[Vertex] = true;
        for (int v = 0; v < Nv; v++)
        {
            if (collected[v] == false && dist[Vertex] + MDist[Vertex][v] < dist[v])
            {   /* 如果该点未被收录进集合并且新路径小于原来路径 */
                dist[v] = dist[Vertex] + MDist[Vertex][v];
                cost[v] = cost[Vertex] + MCost[Vertex][v];
                path[v] = Vertex;
            }
            else if (collected[v] == false && dist[Vertex] + MDist[Vertex][v] == dist[v])
            {   /* 如果该点未被收录进集合,并且路径长度与之前一样 */
                if (cost[Vertex] + MCost[Vertex][v] < cost[v])
                {   /* 如果新成本低于原来成本 */
                    cost[v] = cost[Vertex] + MCost[Vertex][v];
                    path[v] = Vertex;
                }
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    int N, M, S, D;
    scanf("%d %d %d %d", &N, &M, &S, &D);
    for (int i = 0; i < N; i++) // 初始化G
        for (int j = 0; j < N; j++)
        {
            MDist[i][j] = INFINTE;
            MCost[i][j] = INFINTE;
        }
    for (int E = 0; E < M; E++)
    {
        int v, w, weight, cost;
        scanf("%d %d %d %d", &v, &w, &weight, &cost);
        MDist[v][w] = weight, MDist[w][v] = weight;
        MCost[v][w] = cost, MCost[w][v] = cost;
    }
    Dijkstra(N, S);
    printf("%d %d\n", dist[D], cost[D]);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值