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 −>S1 −>⋯−>Sp 回收的车数量
若不唯一,带回的需要尽量少.
例子
例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
题解
第一次
思路
- 输入,用二维数组matrix储存
- 用dijstra找最短路径.这里需要用到三个数组known标记结束点,cost标记花费和path标记上一个节点.
- dfs遍历最短路,在遍历出的每条路径再进行遍历,得到从初始点带出的和末尾剩余的,按要求筛选到result数组里.
- 输出数组.
预期时间复杂度
不知道
编写用时
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每一天**