//链接: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;
}
DFS实例注释:pat共享单车管理程序。
最新推荐文章于 2022-03-20 13:12:11 发布