【Pat 甲级】1018 Public Bike Management (30分)

突然觉得什么都放自己本地不方便

所以还是建了个博客

------------------------------------------------------------------------

以下是代码原文和注释

 

#include <iostream>
using namespace std;
#define maxv 501	// 题目说车站最多500,加上基地就是501
#define inf 1000000000	//c语言表示的最大整数,1后面9个0
int G[maxv][maxv], d[maxv], pre[maxv], cur_c[maxv], sum[maxv] = {0};	// cur_c表示此时的容量, sum表示到此点的 车辆数
bool vis[maxv];

int main(){
	// 准备工作
	int c, n, s, m;	// c每个站点的最大容量----  n车站的数量-----  s出现问题的车站---  m是全部的道路条数
	cin >> c >> n >> s >> m;
	fill(d, d+n+1, inf); //毕竟0是基地,n不包含0,从1开始算
	d[0] = 0;
	int pc = c / 2;	//pc指的是pefect_cap,一半
	// 获取每个车站此时的容量
	for (int i = 1; i <= n; i++)  cin >> cur_c[i];


	//初始化图
	for (int i = 0; i < n + 1; i++)
		for (int j = 0; j < n + 1; j++)
			G[i][j] = inf;	
	//获取图的路况
	for (int i = 0; i < m; i++){
		int a, b;
		cin >> a, b;
		cin >> G[a][b];
		G[b][a] = G[a][b];	//无向图
	}

	//开始所谓的贪心算法
	for (int i = 0; i < n+1; i++){
		int u = -1, min = inf;	// u是临时变量,表示正在拜访的点,min是这些点中,距离上一个点最近的距离
		for (int j = 0; j < n; j++){
			if (vis[j] == false && d[j] < min){	// 如果此时j没有被拜访过,而且此时他到原点的距离比最小值小,
				u = j;
				min = d[j];
			}
			vis[u] = true;
			// 以上都是为了找出此时距离原点最近的(还没有拜访过的)点u
			for (int v = 0; v < n; v++){	//这里的v是u的邻接点,这个循环是为了调整每个v到原点的最小距离
				if (vis[v] == false && G[u][v] != inf){
					if (d[u] + G[u][v] < d[v]){	// 如果v到原点的距离,比用u当中介点要小,就调整 d[v]
						d[v] = d[u] + G[u][v];
						pre[v] = u;
						// 正数代表从基地带出去,负数代表带回基地
						sum[v] = pc-cur_c[v] + sum[u];	//	-----------------*********************可能存在0被算了进去。************
					}
					else if (d[u] + G[u][v] == d[v]){
						int tmp = pc - cur_c[v] + sum[u];
						/*
						只有三种情况可以替代原来的路径
						1.原来带出,之后带出,原来带出多于之后带出
						2.原来带回,之后带出(无带回)
						3.原来带回,之后带回,之后带回少于原来带回
						可以融合为两种可能
						*/
						if ((sum[v] > 0 && tmp < sum[v]) || (sum[v]<0 && tmp>sum[v])){
							pre[v] = u;
							sum[v] = tmp;
						}
					}
				}
			}
		}
	}
	/*
	接下来,判断sum[s]的正负,正的在前面输出,最后输出0; 负的前面输出0,最后输出绝对值
	中间的路径根据pre数组倒过来打印就可
	*/
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值