题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024
题目大意:有一个公共自行车管理中心PBMC,记为S0。一共有N个车站,从1~N 编号,每个车站中的车辆数目为Cm/2时才称为“完美状态”,Cm为每个车站的最大容量。现在需要通过最短路去调整Sp车站的车辆,使其变为“完美状态”。在由S0到Sp的路程中,所经过的所有车站也将被调整为“完美状态”。当有多条最短路时,将选择从S0带出车辆最少的那条路。如果答案还是不唯一,将选择带回车辆最少的那条路。
输入为Cm N Sp M , 其中M条路,第二行为N个数,代表每个车站的初始车辆数。之后M行, 给出两个车站的距离。
先输出需要从PBMC带出的车辆数,然后打印你选择的那条路,最后输出带回PBMC的车辆数。
注意:
(1)题目并没有说到达Sp之后原路返回,所以不能把经过的车站数*Cm/2,与这些车站一共有多少辆车做多退少补,即后面经过的站多余出来的车辆不能补到之前的车站中。
(2)该题不满足最优子结构,因此不能在Dijk中判断是否满足带出或带回更少,从而更新pre[j]。应该把所有最短路都存下来,然后dfs去遍历每条最短路,再计算比较。
for(int j=1;j<=n;j++){ //错误写法
if(!vis[j]){
if(dis[j]>dis[pos]+g[pos][j]){
dis[j]=dis[pos]+g[pos][j];
pre[j]=pos;
}
else if(dis[j]==dis[pos]+g[pos][j]){
pre[j]=judge(j,pos);//遍历j和pos的pre数组,比较谁更好
}
}
}
(3)只得20分:用Dijk算出到达Sp最短路的数值,然后从S0开始去dfs,到达Sp且当前路程为最短路时,去跟ans路径进行比较和更新。
思路:在做Dijk的同时保存所有最短路,用vector记录某个点的所有pre点。然后从Sp点开始往回遍历所有最短路,选出最优的一条。
#include<bits/stdc++.h>
using namespace std;
const int maxn=500+10;
const int INF=0x3f3f3f3f;
int Cm,n,Sp,m,bike[maxn],vis[maxn],dis[maxn];
int g[maxn][maxn],x,y,z,min_a=INF,min_b=INF;
vector<int> pre[maxn];
vector<int> ans,v;
void Dijk(){
memset(dis,INF,sizeof(dis));
dis[0]=0;
for(int i=0;i<=n;i++){
int pos=-1,_min=INF;
for(int j=0;j<=n;j++){
if(!vis[j]&&dis[j]<_min){
pos=j;
_min=dis[j];
}
}
if(pos!=-1) {
vis[pos]=1;
}
for(int j=0;j<=n;j++){
if(!vis[j]&&g[pos][j]!=INF){
if(dis[j]>dis[pos]+g[pos][j]){
dis[j]=dis[pos]+g[pos][j];
pre[j].clear();
pre[j].push_back(pos);
}
else if(dis[j]==dis[pos]+g[pos][j]){
pre[j].push_back(pos);
}
}
}
}
}
void judge(){
int a=0,b=0,tmp; //a是借出,b是带回
for(int i=v.size()-1;i>=0;i--){
int p=v[i];
if(bike[p]<Cm){
tmp=Cm-bike[p];
if(b-tmp>=0) {
a+=0;
b=b-tmp;
}
else {
a+=tmp-b;
b=0;
}
}
else if(bike[p]>Cm){
b+=bike[p]-Cm;
}
}
if(a<min_a){
min_a=a;
min_b=b;
ans=v;
}else if(a==min_a&&b<min_b){
min_b=b;
ans=v;
}
}
void dfs(int p){
if(p==0) {
judge();
return;
}
v.push_back(p);
for(int i=0;i<pre[p].size();i++){
dfs(pre[p][i]);
}
v.pop_back();
}
void Print(){
printf("%d 0",min_a);
for(int i=ans.size()-1;i>=0;i--){
printf("->%d",ans[i]);
}
printf(" %d\n",min_b);
}
int main()
{
cin>>Cm>>n>>Sp>>m;
Cm/=2;
for(int i=1;i<=n;i++)
cin>>bike[i];
memset(g,INF,sizeof(g));
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
g[x][y]=z;
g[y][x]=z;
}
Dijk();
dfs(Sp);
Print();
}