1018 Public Bike Management (30分)[DFS][单源最短路径]

By Jalan

吐槽

实际上这个题过于复杂了,又用了dijstra又用了dfs,后面PTA的30分一般不会这么复杂,如果出到,一般会涉及其中之一再加一点点别的

知识工具需求

数学

  • 一点点图的知识,一般混着最短路算法也就一起学了.

数据结构和算法

  • 单源最短路算法比如dijstra算法
  • DFS

语言

题干

一个共享单车管理,一个点存了一半是perfect,空的或者满的时候管理局会移车让这个点到达perfect.路上的站点也会被调整.一个问题站点出现的时候,管理局会选最短的路径去,若果同,选需要少的从管理局送出车的站点

输入条件

Cmax<=100是每个节点的最大能力,perfect是50,N<=500节点数,Sp问题节点号,管理局PBMC用0号表示,剩下站点是1-N,M边数.
下来N个非负数,是每个站点的当前车数,
接下来是M行,每行3个数,代表了从Si-Sj耗时.

输出条件

输出结果,送出的车数量 0 −>S​1​​ −>⋯−>S​p 回收的车数量
若不唯一,带回的需要尽量少.

例子

例1

输入
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
输出
3 0->2->3 0

题解

第一次

思路

  1. 输入,用二维数组matrix储存
  2. 用dijstra找最短路径.这里需要用到三个数组known标记结束点,cost标记花费和path标记上一个节点.
  3. dfs遍历最短路,在遍历出的每条路径再进行遍历,得到从初始点带出的和末尾剩余的,按要求筛选到result数组里.
  4. 输出数组.

预期时间复杂度

不知道

编写用时

120分钟

代码

CPP
#include <bits/stdc++.h>
#include <stdio.h>
#include <vector>
using namespace std;
int cmax, n, sp, m;
vector<int> nowBike;
vector<int> cost;
vector<vector<int>> matrix;
vector<bool> known;
vector<vector<int>> path;
int minTakeBike = INT_MAX;
int minRestBike = INT_MAX;
vector<int> result;
vector<int> sake;
int finalBike;
void dfs(int index)
{
    if (index == 0)
    {
        //这时sake是一条完整的序列,还需要检测一下这个序列才知道带回和带出.
        int vertexBike = 0; //原点
        int takeBike = 0;
        for (int i = (int)sake.size() - 1; i >= 0; i--)
        {
            if (vertexBike + nowBike[sake[i]] - cmax / 2 >= 0) //带来的车和当前节点的车够变成perfect
            {
                vertexBike = vertexBike + nowBike[sake[i]] - cmax / 2;
            }
            else //不够,需要从头再借
            {
                int deficit=vertexBike + nowBike[sake[i]] - cmax / 2;
                takeBike += -deficit;
                vertexBike = 0;
            }
        }
        if (takeBike < minTakeBike)
        {
            minTakeBike = takeBike;
            minRestBike = vertexBike;
            result = sake;
            return;
        }
        if (takeBike == minTakeBike)
        {
            if (vertexBike < minRestBike)
            {
                minRestBike = vertexBike;
                result = sake;
                return;
            }
        }

        return;
    }
    for (int i = 0; i < path[index].size(); i++)
    {
        int nextIndex = path[index][i];
        sake.push_back(nextIndex);
        dfs(nextIndex);
        sake.pop_back();
    }
}
int main(int argc, char const *argv[])
{
    //1
    scanf("%d%d%d%d", &cmax, &n, &sp, &m);
    nowBike.resize(n + 1);
    nowBike[0] = cmax / 2; //吧PM设成perfect因为pm不用调整.
    for (int i = 1; i < n + 1; i++)
    {
        scanf("%d", &nowBike[i]);
    }
    matrix.resize(n + 1);
    for (int i = 0; i < n + 1; i++)
    {
        matrix[i].resize(n + 1);
    }
    //initialize matrix
    for (int i = 0; i < n + 1; i++)
    {
        for (int j = 0; j < n + 1; j++)
        {
            matrix[i][j] = -1;
        }
    }
    for (int i = 0, j, k, l; i < m; i++)
    {
        scanf("%d%d%d", &j, &k, &l);
        matrix[j][k] = l;
        matrix[k][j] = l;
    }
    known.resize(n + 1);
    cost.resize(n + 1);
    path.resize(n + 1);
    //2
    for (int i = 1; i < n + 1; i++)
    {
        cost[i] = INT_MAX;
    }
    for (int i = 0; i < n + 1; i++)
    {
        path[i].resize(0);
    }
    for (int i = 0; i < n + 1; i++) //这个其实不用.
    {
        known[i] = false;
    }
    cost[0] = 0;
    while (1)
    {

        //找到cost最小的且known是false的
        int minIndex = -1;
        int minCost = 0x7fffffff;
        for (int i = 0; i < n + 1; i++)
        {
            if (cost[i] < minCost && known[i] == false)
            {
                minIndex = i;
                minCost = cost[i];
            }
        }
        if (minIndex == -1) //结束.
        {
            break;
        }
        //标记这个的known是true
        known[minIndex] = true;
        //known标记之后的cost是不再修改的,
        if (minIndex == sp)
        {
            break;
        }

        //修改它的邻接的known是false的节点的cost
        for (int i = 0; i < n + 1; i++)
        {
            if (matrix[minIndex][i] >= 0 && known[i] == false)
            {
                if (cost[minIndex] + matrix[minIndex][i] < cost[i])
                {
                    cost[i] = cost[minIndex] + matrix[minIndex][i];
                    //改变cost时改变path
                    //cost更小时全删了
                    path[i].clear();
                    path[i].push_back(minIndex);
                    continue;
                }
                if (cost[minIndex] + matrix[minIndex][i] == cost[i])
                {
                    //cost一致时,加进去
                    path[i].push_back(minIndex);
                    continue;
                }
            }
        }
    }
    //3
    int index = sp;
    sake.push_back(sp);
    dfs(index);
    //4
    printf("%d 0", minTakeBike);
    for (int i = (int)result.size() - 2; i >= 0; i--) //-2因为最后一个是0
    {
        printf("->%d", result[i]);
    }
    printf(" %d", minRestBike);

    return 0;
}



运行用时

在这里插入图片描述

结尾

看在我写了这么多注释的份上可以给我点个赞嘛,求求惹=]砰砰砰,给我加点写下去的油呀@.@
也欢迎关注我的CSDN账号呀,接下来两个月我应该会按这个格式更新所有的PTA甲级题目

                                        **开心code每一天**
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值