PAT甲级 1018 Public Bike Management (30分) Dijkstra算法+DFS/C++

1018 Public Bike Management (30分)

题目大意为:结点0为PBMC,需要城市中的每一个结点的bike的数量为容量的一半,当结点不符合上述要求时,需要PBMC进行调整。

现给你一个问题结点,需要找到一条从0到问题结点的最短路径,如果存在多条最短路径,则计算出需要带的自行车最少的那条路径。

tips:

  1. 途径路上多余的bike需要带上,可以用于补充之后结点缺少的bike

  2. 带回的途中,不需要进行调整(意思是在去到目的地的过程中,需要把途径的不符合要求的结点调整为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。最后进行输出。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值