【PAT甲级】1030 Travel Plan 旅行计划

PAT原题网址PTA | 程序设计类实验辅助教学平台 (pintia.cn)

ACwing原题网址1507. 旅行计划 - AcWing题库

分析

0.易错点

c++

1. 准备

int n, m, Start, End; // 点数 边数 起点编号 终点编号
int g[N][N], c[N][N]; // g存储两点间距离  c存储两点间的花费
int dist[N], cost[N], pre[N];// dist 最终距离 cost最终花费 pre[t]存的是t的前一个点的
bool st[N];

2. 核心

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    memset(cost, 0x3f, sizeof cost);
        
    // 起点到起点的距离dist为0,还未从起点出发cost = 0
    dist[Start] = 0, cost[Start] = 0;
    for(int i = 0; i < n; i ++ )
    {
        int t = -1;
        for(int j = 0; j < n; j ++ )
        {
            if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
                t = j;
        }
        
        st[t] = true;
    
        for(int j = 0; j < n; j ++ )
        {
                if(dist[j] > dist[t] + g[t][j])
                {
                    dist[j] = dist[t] + g[t][j];
                    cost[j] = cost[t] + c[t][j]; // 改变花费
                    pre[j] = t; // 存j点的前一个点
                }
                else if(dist[j] == dist[t] + g[t][j] ) // 若距离相等
                {
                    if(cost[j] > cost[t] + c[t][j]) 
                    {
                        cost[j] = cost[t] + c[t][j]; // 更新花费为最小
                        pre[j] = t; // 存j点的前一个点
                    }
                }
            
        }
        
    }
    
}

3.main函数

int main()
{
    memset(g, 0x3f, sizeof g);//距离
    memset(c, 0x3f, sizeof c);//花费 都初始化为0x3f
    
    cin >> n >> m >> Start >> End;// 读入 
    
    while(m -- ) // m条边 m次输入
    {
        int a, b, x, y;
        cin >> a >> b >> x >> y;
        g[a][b] = g[b][a] = min(g[a][b], x); //存距离
        c[a][b] = c[b][a] = min(c[a][b], y); //存花费
    }
    
    dijkstra();
    
    for(int i = 0; i < 7; i ++ )
        cout << pre[i];//  pre下标 0 1 2 3  
    cout << endl;      //  具体值  0 0 0 2  3的前一个点是2  2的前一个点是0
    
    vector<int> path;
    for(int i = End; i != Start; i = pre[i] ) 
        path.push_back(i); //path下标  0 1 2 3 
                           //  具体值  3 2 0  
    cout << path.size();
    cout << endl; //  0 - 2 三个点  
    
    cout << Start; // 输出起点 0 
    for(int i = path.size() - 1; i >= 0; i --)  
        cout << ' ' << path[i]; // 先输出2  再输出3
    
    cout << ' ' << dist[End] << ' ' << cost[End] << endl;
    
    return 0;
}

4. AC代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 600;

int n, m, Start, End; // 点数 边数 起点编号 终点编号
int g[N][N], c[N][N]; // g存储两点间距离  c存储两点间的花费
int dist[N], cost[N], pre[N];// dist 最终距离 cost最终花费 pre[t]存的是t的前一个点的
bool st[N];

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    memset(cost, 0x3f, sizeof cost);
        
    // 起点到起点的距离dist为0,还未从起点出发cost = 0
    dist[Start] = 0, cost[Start] = 0;
    for(int i = 0; i < n; i ++ )
    {
        int t = -1;
        for(int j = 0; j < n; j ++ )
        {
            if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
                t = j;
        }
        
        st[t] = true;
    
        for(int j = 0; j < n; j ++ )
        {
                if(dist[j] > dist[t] + g[t][j])
                {
                    dist[j] = dist[t] + g[t][j];
                    cost[j] = cost[t] + c[t][j]; // 改变花费
                    pre[j] = t; // 存j点的前一个点
                }
                else if(dist[j] == dist[t] + g[t][j] ) // 若距离相等
                {
                    if(cost[j] > cost[t] + c[t][j]) 
                    {
                        cost[j] = cost[t] + c[t][j]; // 更新花费为最小
                        pre[j] = t; // 存j点的前一个点
                    }
                }
            
        }
        
    }
    
}

int main()
{
    memset(g, 0x3f, sizeof g);//距离
    memset(c, 0x3f, sizeof c);//花费 都初始化为0x3f
    
    cin >> n >> m >> Start >> End;// 读入 
    
    while(m -- ) // m条边 m次输入
    {
        int a, b, x, y;
        cin >> a >> b >> x >> y;
        g[a][b] = g[b][a] = min(g[a][b], x); //存距离
        c[a][b] = c[b][a] = min(c[a][b], y); //存花费
    }
    
    dijkstra();
    
    for(int i = 0; i < 7; i ++ )
        cout << pre[i];//  pre下标 0 1 2 3  
    cout << endl;      //  具体值  0 0 0 2  3的前一个点是2  2的前一个点是0
    
    vector<int> path;
    for(int i = End; i != Start; i = pre[i] ) 
        path.push_back(i); //path下标  0 1 2 3 
                           //  具体值  3 2 0  
    cout << path.size();
    cout << endl; //  0 - 2 三个点  
    
    cout << Start; // 输出起点 0 
    for(int i = path.size() - 1; i >= 0; i --)  
        cout << ' ' << path[i]; // 先输出2  再输出3
    
    cout << ' ' << dist[End] << ' ' << cost[End] << endl;
    
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值