题目翻译:
给定车站的信息,公共自行车管理中心(PBMC)不断监测所有站点的实时容量。
如果一个车站自行车存量刚满一半,则称其处于理想状态。
如果一个车站已满或空了,PBMC 会收集或派送自行车以将该车站的状况调整到最佳状态。
而且,途中的所有车站也会调整至最佳。
现在给定需要调整的站点,PBMC 将始终选择到达该站点的最短路径,前去该站点进行车辆调整。
如果最短路径多于一条,则将选择需要从 PBMC 发送的自行车数量最少的那条路径。如果还出现相同的路径,则选择那条调整完后带回 PBMC 车辆数量最小的路径。
上图给出了一个示例,车站以及 PBMC 由点表示,道路由边表示。
边上的数字是从一个站点到达另一个站点所花费的时间。
点内的数字是车站目前的自行车存量。
假设每个站点最多存 10 辆车。
我们现在要给车站 S3 送自行车,共有两条最短路径可选:
PBMC→S1→S3 ,这种路线需要从 PBMC 发送 4 辆自行车,因为我们可以从 S1 收集 1 辆车,并需要给 S3 派送 5 辆车,这样两个站点就都调整到最佳状态了。
PBMC→S2→S3 ,这种路线与上一条路线距离相同,但是只需要从 PBMC 发送 3 辆自行车,因此这条路径应该被选择。
题解思路:
用dfs求解即可,注意dfs中的细节,具体看代码
代码:
#include<bits/stdc++.h>
using namespace std;
int Cmax, N, Sp, M;//Cmax:单个车站最大容纳量;N:车站总数;Sp:问题车站的下标;M:路线的数量。
int C[501];//用以存储车站当前的自行车数量。
int dis[501][501];//用以存储顶点之间路线的距离。
vector<int> v[501];//用来表示结点之间的邻居关系。
int mindis[501];//用来存储结点0到其余结点的最小距离
#define MAX_DISTANCE 100000
vector<int> path;//记录路径
vector<int> best_path; // 存储最优路径
int final_len = MAX_DISTANCE, final_take, final_back;
void dfs(int curstation, int curlen, int curtake,int curback)
{
if (curlen > mindis[curstation]) return;
path.push_back(curstation);
if (curstation == Sp)
{
if (curlen < final_len || (curlen == final_len && curtake < final_take) || (curlen == final_len && curtake == final_take && curback < final_back))
{
final_len = curlen;
final_take = curtake;
final_back = curback;
best_path = path;
}
}
else
{
if (curlen < mindis[curstation])
mindis[curstation] = curlen;
for (int i = 0; i < v[curstation].size(); i++)
{
int j = v[curstation][i];
if (C[j] + curback < Cmax / 2)//现在结点的自行车数量加上将要带回去的还不能使当前结点达到完美状态
dfs(j, curlen + dis[curstation][j], curtake + Cmax / 2 - C[j] - curback, 0);//在原来的基础上额外拿一些
else//可以使得结点达到完美状态
dfs(j, curlen + dis[curstation][j], curtake, curback - Cmax / 2 + C[j]);//从现有的站带走一些
}
}
path.pop_back();
}
int main()
{
cin >> Cmax >> N >> Sp >> M;
for (int i = 1;i <= N;i++) cin >> C[i];
for (int i = 0;i < M;i++)
{
int t1, t2, t3;
cin >> t1 >> t2 >> t3;
v[t1].push_back(t2);
v[t2].push_back(t1);
dis[t1][t2] = dis[t2][t1] = t3;
}
for (int i = 0;i <= N;i++)
mindis[i] = MAX_DISTANCE;
dfs(0, 0, 0,0);
cout << final_take << " ";
cout << best_path[0];
for (int i = 1; i < best_path.size(); i++)
cout << "->" << best_path[i];
cout << " " << final_back;
}
坑点:
无
二刷:
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
const int MAXCOST = 0x3f3f3f3f;
int cmax, n, sp, m;
int Cnum[N];//站点自行车数量
int mindis[N];//起点到其余各点的最短距离,方便dfs剪枝
vector<int> v[N];//邻接表
int dis[N][N];//花费
vector<int> path, best_path;
int final_len = MAXCOST, final_take, final_back;
void dfs(int curlen, int curnode, int curtake, int curback) {
if (curlen > mindis[curnode]) return;
else mindis[curnode] = curlen;
path.push_back(curnode);
if (curnode == sp) {
if (curlen < final_len || (curlen == final_len && curtake < final_take) || (curlen == final_len && curtake == final_take && curback < final_back)) {
final_len = curlen;
final_take = curtake;
final_back = curback;
best_path = path;
}
}
else {
for (auto i : v[curnode]) {
if (curback + Cnum[i] < cmax / 2)
dfs(curlen + dis[curnode][i], i, curtake + cmax / 2 - curback - Cnum[i], 0);
else
dfs(curlen + dis[curnode][i], i, curtake, curback + Cnum[i] - cmax / 2);
}
}
path.pop_back();
}
int main() {
cin >> cmax >> n >> sp >> m;
for (int i = 1;i <= n;i++) cin >> Cnum[i];
for (int i = 0;i < m;i++) {
int a, b, c;cin >> a >> b >> c;
v[a].push_back(b);
v[b].push_back(a);
dis[a][b] = dis[b][a] = c;
}
memset(mindis, 0x3f, sizeof(mindis));
dfs(0, 0, 0, 0);
cout << final_take << " ";
for (int i = 0;i < best_path.size();i++) {
if (i != 0) cout << "->";
cout << best_path[i];
}
cout << " " << final_back;
}