PAT A1072 Gas Station(30)

题意

  • 这个题读起来有点烦,是这样的,首先有N个居民房和M个加油站,每个加油站都对应着一个最小距离和平均距离,加油站的最小距离是指从他到其他所有居民房的最短路径的最小值(从N条最短路径里面选),现在让你选择一个加油站,首先他到所有居民房的最短路径均不能大于服务范围(每个加油站都一样),其次他的最小距离在所有加油站的最小距离中最大(从M个加油站中选),若不唯一,选择平均距离最小的,若再不唯一,选择编号最小的。若没有一个加油站能服务到所有居民房,那么输出No Solution

注意

  1. 因为算每个加油站的最小距离和平均距离需要知道最短路径长度,所以每个加油站都要来一遍dijkstra,每算出来一个加油站到一个居民房的最短路径(S集新元素)就更新这个加油站的最小距离和平均距离,同时也要判断是否小等于服务范围,不然这个加油站的dijkstra直接结束。
  2. 把平均距离先按照距离和处理,最后再除。
  3. 把每个加油站的信息算完以后,再在加油站之间比这俩数,不满足服务范围的加油站不用考虑。
  4. 加油站编号还要处理一下。

代码

#include <iostream>
#include <algorithm>
#include <climits>
#include <string>  
using namespace std;

const int Nmax = 1011;
int N, M, K, Ds;
int road[Nmax][Nmax];

int dist[Nmax];
bool S[Nmax];

bool isM[11];
int minRoad[11];
int avgRoad[11];

void DIJKSTRA()
{
	fill(isM, isM + 11, false);
	fill(minRoad, minRoad + 11, INT_MAX);
	fill(avgRoad, avgRoad + 11, 0);
	for (int i = 1; i <= M; i++)
	{
		fill(S, S + Nmax, false);
		fill(dist, dist + Nmax, INT_MAX);
		dist[i + N] = 0;
		for (int k = 1; k <= N + M; k++)
		{
			int min = INT_MAX;
			int u;
			for (int j = 1; j <= N + M; j++)
			{
				if (!S[j] && dist[j] < min)
				{
					min = dist[j];
					u = j;
				}
			}
			if (dist[u] > Ds && u <= N)
			{
				isM[i] = true;                 //
				break;
			}
			S[u] = true;
			if (u <= N)
			{
				avgRoad[i] += dist[u];
				if (dist[u] < minRoad[i])
					minRoad[i] = dist[u];
			}
			for (int j = 1; j <= N + M; j++)
			{
				if (!S[j] && road[u][j] != INT_MAX)
				{
					if (dist[u] + road[u][j] < dist[j])
					{
						dist[j] = dist[u] + road[u][j];
					}
				}
			}
		}
	}
}

void select()
{
	int opt = 0;
	int max = -1;
	for (int i = 1; i <= M; i++)
	{
		if (!isM[i])
		{
			if (minRoad[i] > max)
			{
				max = minRoad[i];
				opt = i;
			}
			else if (minRoad[i] == max && avgRoad[i] < avgRoad[opt])
			{
				opt = i;
			}
		}
	}
	if (opt == 0)
	{
		cout << "No Solution";
		return;
	}
	double minR, avgR;
	minR = minRoad[opt];
	avgR = (double)(avgRoad[opt]) / (double)(N);
	cout << "G" << opt << endl;
	printf("%.1f %.1f", minR, avgR);
}

int main()
{
	cin >> N >> M >> K >> Ds;
	string r1, r2;
	int r3, r4;
	fill(road[0], road[0] + Nmax*Nmax, INT_MAX);
	for (int i = 0; i < K; i++)
	{
		cin >> r1 >> r2;
		if (r1[0] == 'G')
			r3 = atoi(r1.substr(1, r1.size() - 1).c_str()) + N;
		else
			r3 = atoi(r1.c_str());

		if (r2[0] == 'G')
			r4 = atoi(r2.substr(1, r2.size() - 1).c_str()) + N;
		else
			r4 = atoi(r2.c_str());

		cin >> road[r3][r4];
		road[r4][r3] = road[r3][r4];
	}
	DIJKSTRA();
	select();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值