1018 Public Bike Management (30分)
题目大意为:结点0为PBMC,需要城市中的每一个结点的bike的数量为容量的一半,当结点不符合上述要求时,需要PBMC进行调整。
现给你一个问题结点,需要找到一条从0到问题结点的最短路径,如果存在多条最短路径,则计算出需要带的自行车最少的那条路径。
tips:
-
途径路上多余的bike需要带上,可以用于补充之后结点缺少的bike
-
带回的途中,不需要进行调整(意思是在去到目的地的过程中,需要把途径的不符合要求的结点调整为C/2)
因此需要在dijkstra算法找到最短结点以后,在对每条路径进行检查(DFS),从而找到带bike最少的那条路径进行输出。
具体可以看柳婼大神的代码(太强了) 附上链接:柳婼大神的题解
但我的代码为回归途中也可以进行调整(也就是将带回的bike给前面缺少的进行补充)
(做题的时候一直没有搞明白为什么没过测试点,去网上找答案才发现QAQ,感觉我的思路也是正常的啊,贴这个代码算是我的一点倔强吧哈哈哈)
#include<iostream> //输入输出流头文件
#include<math.h> //数学函数
#include<vector> //变长数组容器
using namespace std; //标准命名空间
int a[501][501];
int path[501];
void createMatrix(int m);
void findRote(int c,int n,int p,int *now);
int findMinDist(int n,int *dist,int *flag);
int main(){ //主函数
#ifdef ONLINE_JUDGE //如果有oj系统(在线判定),则忽略文件读入,否则使用文件作为标准输入
#else
freopen("1.txt", "r", stdin); //从1.txt输入数据
#endif
int c,n,p,m;
cin>>c>>n>>p>>m;
int *now=new int[n+1];
for(int i=1;i<=n;i++){
cin>>now[i];
}
createMatrix(m);
findRote(c,n,p,now);
return 0; //返回0,如果不返回0,PAT会报错
}
void createMatrix(int m){
for(int i=0;i<m;i++){
int x,y,d;
cin>>x>>y>>d;
a[x][y]=d;
a[y][x]=d;
}
}
void findRote(int c,int n,int p,int *now){
int *dist=new int[n+1];
int *flag=new int[n+1];
int *restore=new int[n+1];
int *take=new int[n+1];
for(int i=1;i<=n;i++){//从PBMC到各个结点的最短距离
dist[i]=a[0][i];
path[i]=0;
flag[i]=0;
restore[i]=c/2-now[i];
take[i]=restore[i];
}
flag[0]=1;
while(1){
int v=findMinDist(n,dist,flag);
if(v==-1)break;
else{
flag[v]=1;
for(int i=0;i<n+1;i++){
if(flag[i]==0&&a[v][i]){
if(dist[i]>dist[v]+a[v][i]){
dist[i]=dist[v]+a[v][i];
//path[i].vector.clear()//题目正确解答:需要将原来的最短路径全部清除
//path[i].push(v)
path[i]=v;
restore[i]=take[i]+restore[v];
}
else if(a[v][i]&&dist[i]==dist[v]+a[v][i]){
//如果有多条最短路径则将其直接push
//path[i].push(v)
if(abs(restore[v]+take[i])<abs(restore[i])){
path[i]=v;
restore[i]=take[i]+restore[v];
}
}//else if
}//if(flag[v]==0...)
}//for
}//else
}//while
int v=p;
vector<int> pa;
pa.push_back(p);
while(path[v]!=0){
pa.push_back(path[v]);
v=path[v];
}
pa.push_back(0);
if(restore[p]>0)cout<<restore[p]<<' ';
else cout<<0<<' ';
for(int i=pa.size()-1;i>=0;i--){
cout<<pa[i];
if(i)cout<<"->";
else cout<<' ';
}
if(restore[p]<0)cout<<-restore[p];
else cout<<0;
}
int findMinDist(int n,int *dist,int *flag){
int min=2147483647;int k=-1;
for(int i=1;i<n+1;i++){
if(flag[i]==0){
if(dist[i]<min){
min=dist[i];
k=i;
}
}
}
return k;
}
补充:可以使用vector来存储多条路径,再对每条路径的途径过程进行模拟,找到最少的bike:
if(restore[i]<0){
back[i]+=back[v];
}
else{//这里表示take[i]>0,并且back为0
if(back[v]<take[i]){//如果前面结点多出来的大于当前结点需要的
back[i]=back[v]-take[i];
take[i]=0;
}
else{//前面多余的不能满足当前所需
take[i]=take[i]-back[v];
}
}
再筛选出最少的take[i],进行输出。当然也可以在模拟前,设置一个mintake,然后再模拟过程中,把小的赋给mintake,并保存相应的back。最后进行输出。