PAT A1072 Gas Station 注意事项

题目链接→https://pintia.cn/problem-sets/994805342720868352/problems/994805396953219072

注意点1: 加油站编号处理

  • 错误案例 , 忽略了 加油站的编号可以为10, 找了半天才发现 。 一定要仔细读题目!。
int getId(string s) {
    
    	//将编号转化为整数(数组下标) 
	if (s[0] == 'G') {
    
    
		return n + s[1] - '0';
	} else {
    
    
		return stoi(s);
	}
}
  • 正确(使用stoi函数更加方便)

    int getId(string s) {
          
          	// 将字符串转化为整数(数组下标)
    	if (s[0] == 'G') {
          
          		// 加油站
    		return n + stoi(s.substr(1));	// G后面的数字
    	} else {
          
          
    		return stoi(s);	
    	}
    }
    

注意点2:平均数计算

尽量不要将所有数加一起再求平均值,可能会发生溢出。

avg += 1.0 * d[i] / n;	// 在运算过程中计算平均值

注意点3

题目需要多次使用Dijskra算法, 每次运行算法要对vis数组(标记顶点是否访问)赋初值。

AC代码

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXV = 1030, INF = 1000000000;
bool vis[MAXV];
int G[MAXV][MAXV], d[MAXV], n, m, k, Ds;

void Dijskra(int s) {
    
    	//求s到其他所有顶点的最短路径
	memset(vis, 0, sizeof(vis));
	fill(d, d + MAXV, INF);
	d[s] = 0;
	for (int i = 0; i < n + m; i++) {
    
    	//n + m个顶点, 循环次数
		int u = -1, MIN = INF;
		for (int j = 1; j <= n + m; j++) {
    
    	// 寻找最小值
			if (vis[j] == false && d[j] < MIN) {
    
    
				MIN = d[j];
				u = j;
			}
		}
		if (u == -1) return; 	//图不连通
		vis[u] = true;
		for (int v = 1; v <= n + m; v++) {
    
    	// 更新 d 数组
			if (vis[v] == false && d[u] + G[u][v] < d[v]) {
    
    
				d[v] = d[u] + G[u][v];
			}
		}
	}
}

int getId(string s) {
    
    	// 将字符串转化为整数(数组下标)
	if (s[0] == 'G') {
    
    
		return n + stoi(s.substr(1));
	} else {
    
    
		return stoi(s);
	}
}

int main() {
    
    
	cin >> n >> m >> k >> Ds;
	int u, v, w;
	string s, t;
	fill(G[0], G[0] + MAXV * MAXV, INF);	// 无穷大表示不可达
	for (int i = 0; i < k; i++) {
    
    
		cin >> s >> t >> w;
		u = getId(s), v = getId(t);
		G[u][v] = G[v][u] = w;
	}

	int ansId = -1, minDis;
	double ansAvg = INF, avg, ansDis = -1;
	for (int v = n + 1; v <= n + m; v++) {
    
    
		Dijskra(v);
		avg = 0.0, minDis = INF;
		for (int i = 1; i <= n; i++) {
    
    
			if (d[i] > Ds) {
    
    
				minDis = -1;
				break;
			}
			if(d[i] < minDis) minDis = d[i];
			avg += 1.0 * d[i] / n;
		}
		if (minDis == -1) continue;	//该加油站不满足条件, 距离村庄的距离超过界限
		if (minDis > ansDis || (minDis == ansDis && avg < ansAvg)) {
    
    	// 平均距离更小, 或平均距离相同但 最小距离较远
			ansDis = minDis;
			ansId = v - n;
			ansAvg = avg;
		}
	}

	if (ansId == -1) {
    
    
		cout << "No Solution";
	} else {
    
    
		printf("G%d\n%.1lf %.1lf", ansId, ansDis, ansAvg);
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/VariatioZbw/article/details/122862720
今日推荐