DFS实例注释:pat共享单车管理程序。

//链接:https://www.nowcoder.com/questionTerminal/4b20ed271e864f06ab77a984e71c090f
//来源:牛客网
//作者:I_hate_algorithm
//DFS递归算法,存储结构优化计算过程!思维量颇大~~~
//全局变量避免形式参数的传入。
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 500 + 5, INF = 1e9;
//cap-站内自行车容量;n-站的个数;sp-待修复车站;m-道路条数
int cap, n, sp, m, bike[maxn], cost[maxn][maxn];
//anspath结果路径  curpath当前路径
vector<int> G[maxn], anspath, curpath;
//minsend-最少带出 //minback最少带回 //mincost最短路径 //vis[]数组,存储是否访问过的标志0和1
int minsend = INF, minback = INF, mincost = INF, vis[maxn];
//递归的过程添加判断条件
//只关心本节点和下一节点应该怎样走
void dfs(int cur, int cursend, int curback, int curcost) {
    //本站点访问
    vis[cur] = 1; curpath.push_back(cur);
    //终止条件
    //1.路径长度优先判断
    if (curcost>mincost) return;
    //2.找到终点,亦结束循环
    if (cur == sp) {
        if (curcost<mincost) {
            mincost = curcost;
            minsend = cursend;
            minback = curback;
            anspath = curpath; 
            return;
        }if (curcost == mincost && cursend<minsend) {
            mincost = curcost;
            minsend = cursend; 
            minback = curback;
            anspath = curpath;
            return;
        }if (curcost == mincost && cursend == minsend && curback<minback) {
            mincost = curcost;
            minsend = cursend; 
            minback = curback;
            anspath = curpath;
            return;
        }
        return;
    }
    //
    //简化思维:下一点的选取从点集中选,选取没有访问的那个做下一步dfs。
    //数学归纳如果走到尽头,则获得正确结果;若没有走到尽头,则依次退栈,回到可以继续的分支。
    //
    for (int i = 0; i<G[cur].size(); ++i) {
        //尝试下一个站点,站标记为v
        int v = G[cur][i];
        //v没有被访问才会继续,否则G[cur]指针后移
        if (!vis[v]) {
            //如果传入的自行车数目和到上一点需要带回的数目之和小于标准,则需要添加自行车数目
            if (bike[v] + curback<cap / 2) 
                //添加传入自行车数目,传入形参的过程完成参数的迭代
                dfs(v, cursend + cap / 2 - bike[v] - curback, 0, curcost + cost[cur][v]);
            else
                //添加带回的自行车数目,传入形参的过程完成参数的迭代
                dfs(v, cursend, curback + bike[v] - cap / 2, curcost + cost[cur][v]);
            //如果以上2种情况无以为继(邻接点都被访问过了),即达到各自G[cur].size()最大值的时候,无法继续深度遍历,则curpath退栈,vis[v]回归0,直到回退到G[cur]指针未达到最大的地方继续遍历
            vis[v] = 0;
            curpath.pop_back();
            //退栈的过程mincost,minsend,minback,anspath等不需要重新赋值,它们也会回到正确的时间点。
        }
    }
    //    vis[cur]=0;curpath.pop_back();    
}
int main() {
    //cap-站内自行车容量;n-站的个数;sp-待修复车站;m-道路条数
    scanf("%d %d %d %d", &cap, &n, &sp, &m);
    //站内自行车数目
    for (int i = 1; i <= n; ++i) 
        scanf("%d", &bike[i]);
    //构建邻接矩阵cost[x][y];G[x][0]~G[x][n]、G[y][0]~G[y][n]代表去往x,y的上一跳所有可能性。
    for (int i = 1, x, y, z; i <= m; ++i) {
        scanf("%d %d %d", &x, &y, &z);
        G[x].push_back(y);
        G[y].push_back(x);
        cost[x][y] = z;
        cost[y][x] = z;
    }
    dfs(0, 0, 0, 0);
    //输出
    printf("%d ", minsend);
    for (int i = 0; i<anspath.size(); ++i)
        if (i == 0) 
            printf("%d", anspath[i]);
        else 
            printf("->%d", anspath[i]);
    printf(" %d\n", minback);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值