PAT-Apat甲级题1003(python和c++实现)下

本文介绍了如何使用C++语言实现深度优先搜索(DFS)算法解决一个关于救援队在无向带权图中的路径问题,包括输入处理、距离矩阵初始化、剪枝策略和DFS函数的详细设计。
摘要由CSDN通过智能技术生成

PTA | 1003 Emergency

书接上回,上次我们使用了python实现无向带权图与DFS算法的设计,本次我们将使用C++对本题进行解答,思路和题目分析同上一节内容,本次我们将在上一节的基础上继续实现。

okok现在又是激动人心的手搓代码时间:(代码思路来自哔哩哔哩)

 首先,定义以下全局变量:

        1, int N, M, C1, C2; 输入变量:城市数量,道路数量,起始城市, 终点城市
        2,  int path, teams; path表示路径数量,teams表示经过每个城市的最多的队伍数量
        3, int num_of_team[500] = {0};表示每个城市的队伍数
        4, int distence[500][500];距离矩阵
        5, int mindis[500];最短路径数量
        6, vector<int> v[500];用于构建无向带权图网络

此后,根据题意对输入数据进行处理:

    int i,j,k,l; // j,k,l分别表示输入的两个城市j、k和这两者之间的距离l
    cin >> N >> M >> C1 >> C2;
    for(int i = 0; i < N; i ++){
        cin >> num_of_team[i];
    }
    for(int i = 0; i < M; i++){
        cin >> j >> k >> l;
        // 无向带权图,则j—>k与k->j应当看作同一条路径,即二者作为端点均需要相互连接
        v[j].push_back(k);
        v[k].push_back(j);
        // 距离矩阵中,二者之间的距离是一致的
        distence[j][k] = distence[k][j] = l;
    }

此后,我们定义最短距离矩阵,为每个元素初始化为一个很大的数,表示两两之间并不相通:

    for(int i=0; i<N; i++)mindis[i] = 100000000;

重点来了,现在我们设计dfs函数:选择当前城市,当前走过的路径长度,当前积累的救援队数量作为传入参数,

void dfs(int curcity, int curlen, int curnums)

第一步:剪枝

        根据传入参数,我们可以意识到,当当前走过的路径长度curlen大于mindis[curcity],即并非第一次到达curcity且走过的路径长度比之前到达curcity所花费的距离大,直接return,

此后,由于我们的传入参数中并没有目标城市,因此对于当前城市,我们需要先对其进行判断:

                if 是目标城市:

                        当前所走过的路径curlen是否小于该城市之前的所记录的最短距离mindis[city]:

                                if 距离相等:

                                        说明是满足要求的最短路径之一,path自增1

                                        同时比较当前积累的救援队数量curnums和最大救援队数量teams是否需要交换

                      

                                elif 当前走过的路径curlen小于该城市之前的所记录的最短距离mindis[city]:

                                        表示之前所有的路径均非最短路径,此时将重新对最短路径数组mindis[C2],路径数path,最大救援队数量teams重新赋值,

                elif 非目标城市:

                        此时运用一点贪心的思想,比较当前走过的路程curlen与当前城市记录到的最短路径值,

                                if  curlen < mindis[curcity]:  

                                        表示以前走过的到达本城市的路径均非最短路径,直接对其重新赋值为当前路径长度

                               for  对于所有与当前城市接壤的所有城市v[curcity]进行遍历,         

                                        将其中的所有城市与当前城市相结合,即在当前城市的基础上, 继续DFS,直到路径到达终点或者遍历结束

本部分较为繁琐, DFS的代码思路如上, 接下来是本部分的代码:

   if(curcity == C2){  // if 是目标城市:

        // 当前所走过的路径curlen是否小于该城市之前的所记录的最短距离mindis[city]:

        // if 距离相等:
        if(curlen == mindis[curcity]){
            path ++;
            if(curnums > teams){
                teams = curnums;
            }
        }

        // elif 当前所走过的路径curlen小于该城市之前的所记录的最短距离mindis[city]:
        else{
            mindis[C2] = curlen;
            path = 1;
            teams = curnums;
        }
    }

    // elif 非目标城市:
    else{
        if(curlen < mindis[curcity])mindis[curcity] = curlen;
        for(int i = 0;i < v[curcity].size(); i++){
            // 在当前城市的基础上, 继续DFS,直到路径到达终点或者遍历结束
            int j = v[curcity][i];
            dfs(j, curlen+distence[curcity][j], curnums+num_of_team[j]);
        }
    }

完整的代码如下:

#include<bits/stdc++.h>
using namespace std;
int N, M, C1, C2;
int path, teams;
int num_of_team[500] = {0};
int distence[500][500];
int mindis[500];
vector<int> v[500];

void dfs(int curcity, int curlen, int curnums){
    if(curlen > mindis[curcity])return;
    if(curcity == C2){
        if(curlen == mindis[curcity]){
            path ++;
            if(curnums > teams){
                teams = curnums;
            }
        }
        else{
            mindis[C2] = curlen;
            path = 1;
            teams = curnums;
        }
    }
    else{
        if(curlen < mindis[curcity])mindis[curcity] = curlen;
        for(int i = 0;i < v[curcity].size(); i++){
            int j = v[curcity][i];
            dfs(j, curlen+distence[curcity][j], curnums+num_of_team[j]);
        }
    }
}


int main(){
    int i,j,k,l;
    cin >> N >> M >> C1 >> C2;
    for(int i = 0; i < N; i ++){
        cin >> num_of_team[i];
    }
    for(int i = 0; i < M; i++){
        cin >> j >> k >> l;
        v[j].push_back(k);
        v[k].push_back(j);
        distence[j][k] = distence[k][j] = l;
    }
    for(int i=0; i<N; i++)mindis[i] = 100000000;
    dfs(C1, 0, num_of_team[C1]);
    cout << path<< " " << teams;
}

   以上就是使用C++解决本题的全部内容,最后附上AK截图:

        本题难度较大,思路尚未清晰的童鞋也不要气馁, 可以针对这部分内容多看看讲解或者是找一些简单题来练手, DFS题目重难点都在于DFS内容的设计,这部分没有固定的公式可以套用,但是只要思路清晰,虽然不能拿到全部的用例分,我相信大部分的分数还是可以拿到手的.

        针对本题,C++部分的做法较为简单直接和常规,如果您有疑惑或者是更好的见解,请在评论区留言交流!

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值