[PAT]1087. All Roads Lead to Rome (30)

/**************************************************************
1087. All Roads Lead to Rome (30)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue
Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<=N<=200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format "City1 City2 Cost". Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.

Output Specification:

For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommended. If such a route is still not unique, then we output the one with the maximum average happiness -- it is guaranteed by the judge that such a solution exists and is unique.

Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommended route. Then in the next line, you are supposed to print the route in the format "City1->City2->...->ROM".

Sample Input:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
Sample Output:
3 3 195 97
HZH->PRS->ROM
****************************************************************/
#include <iostream>
#include <map>
#include <string>
#define INF 1<<30
using namespace std;
int mat[210][210];
int dist[210];
bool mark[210];
//记录开心值
int happiness[210];
//记录总的开心值
int sumhap[210];
//记录平均开心值
int avg[210];
int rout[210];
//记录有多少条最短路径
int difr[210];
//记录路径长度
int ct[210];
string cities[210];
map<string,int> m;
int num=-1;
int n;
int ston(string s){
	if(m.find(s)!=m.end()) return m[s];
	else{
		num++;
		m[s]=num;
		return num;

	}

}
void init(){
	for(int i=0;i<n;i++){
		dist[i]=INF;
		mark[i]=false;
		happiness[i]=0;
		sumhap[i]=0;
		difr[i]=0;
		avg[i]=0;
		rout[i]=0;
		ct[i]=0;
		for(int j=0;j<n;j++){
			mat[i][j]=INF;
		}
	}
}
void dijk(){
	
	for(int i=0;i<n;i++){
		int p;
		//选出最短加入路径
		int min=INF;
		for(int j=0;j<n;j++) if(mark[j]==false&&dist[j]<min) min=dist[p=j];
		if(min==INF) return;
		mark[p]=true;
		for(int j=0;j<n;j++){
			if(mark[j]==true) continue;
			if(dist[j]>dist[p]+mat[p][j]){
				dist[j]=dist[p]+mat[p][j];
				rout[j]=p;
				sumhap[j]=sumhap[p]+happiness[j];
				ct[j]=ct[p]+1;
				avg[j]=sumhap[j]/ct[j];
				difr[j]=difr[p];
			}
			else if(dist[j]==dist[p]+mat[p][j]){
				difr[j]+=difr[p];
				if(sumhap[j]<sumhap[p]+happiness[j]){
					rout[j]=p;
					sumhap[j]=sumhap[p]+happiness[j];
					ct[j]=ct[p]+1;
				    avg[j]=sumhap[j]/ct[j];
				}else if(sumhap[j]==sumhap[p]+happiness[j]){
					if(avg[j]<sumhap[j]/(ct[p]+1)){
						rout[j]=p;
						ct[j]=ct[p]+1;
						avg[j]=sumhap[j]/ct[j];

					}

				}
			}
		}
	}

}
void printfrout(int x){
	if(rout[x]!=0) printfrout(rout[x]);
	
	cout<<cities[rout[x]]<<"->";

}

int main(){
	int k;
	string scity;
	string city;
	int hp;
	string sa,sb;
	int ia,ib,cost;
	while(cin>>n>>k>>scity){
		init();
		num=ston(scity);
		cities[num]=scity;

		for(int i=0;i<n-1;i++){
			cin>>city>>hp;
			num=ston(city);
			happiness[num]=hp;
			cities[num]=city;
		}
		for(int i=0;i<k;i++){
			cin>>sa>>sb>>cost;
			ia=ston(sa);
			ib=ston(sb);
			mat[ia][ib]=mat[ib][ia]=cost;
		}
		
		
		dist[0]=0;
		difr[0]=1;
		dijk();
		ib=ston("ROM");
		cout<<difr[ib]<<" "<<dist[ib]<<" "<<sumhap[ib]<<" "<<avg[ib]<<endl;
		printfrout(ib);
		cout<<"ROM"<<endl;
	}
}
/**************************************************************
    author: ws
    Language: C++
****************************************************************/

<think>好的,我需要帮助用户理解代码`self.all_roads_: List[List[QPointF, None], None] = []`的含义。首先,用户可能对类型注解的语法不太熟悉,特别是涉及到嵌套列表和可能存在`None`的情况。 首先,我应该检查这个类型注解是否正确。Python中的`typing.List`通常需要指定单一类型参数,例如`List[int]`。如果列表包含多种类型,应该使用`Union`,比如`List[Union[QPointF, None]]`。但用户写的`List[List[QPointF, None], None]`看起来有问题,因为`List`的第二个参数应该是类型,而这里可能混淆了嵌套结构。 接下来,我需要解释用户可能的意图。他们可能想定义一个二维列表,其中每个子列表包含`QPointF`对象或`None`,并且整个外层列表也可能为`None`。但正确的写法应该是`List[Optional[List[Optional[QPointF]]]]`,或者更清晰的层定义。 然后,我应该指出当前代码中的语法错误,并给出修正建议。例如,使用`Union`或`Optional`来组合类型,并正确嵌套`List`。同时,提醒用户`None`在类型注解中的正确用法,以及如何初始化这样的结构。 可能用户在使用PyQt的QPointF,所以需要确认是否导入了相关模块。另外,类型注解在运行时不会有强制检查,建议使用mypy等工具进行静态检查,或者添加运行时验证。 最后,总结正确的写法,并提供一个示例,帮助用户理解如何正确声明和初始化这样的嵌套列表结构。</think>在 Python 类型注解中,`self.all_roads_: List[List[QPointF, None], None] = []` 的写法存在 **语法错误** 且 **语义不清晰**。以下是逐层解析和修正方案: --- ### 错误析 #### 1. **类型注解语法错误** - `List` 的泛型参数必须是 **单一类型** 或 **联合类型**,例如: ```python List[QPointF] # 列表元素只能是 QPointF 对象 List[Union[QPointF, int]] # 元素可以是 QPointF 或 int ``` - 原代码 `List[List[QPointF, None], None]` 试图在 `List` 中定义多个类型参数(`QPointF` 和 `None`),这在 Python 类型系统中是无效的。 #### 2. **嵌套结构语义不明确** - `List[List[QPointF, None], None]` 可能想表达两种含义: - 外层列表元素可以是 `List[QPointF 或 None]` 或 `None` - 内层列表元素可以是 `QPointF` 或 `None` --- ### 正确注解方案 #### 场景假设 假设该变量需要表示: - 一个**道路集合**(外层列表) - 每条道路由多个 **坐标点(`QPointF`)** 或 **空值(`None`)** 组成(内层列表) - 整个道路集合可能为空(即外层列表元素为 `None`) #### 修正代码 ```python from typing import List, Optional, Union from PyQt5.QtCore import QPointF # 假设 QPointF 来自 PyQt class YourClass: def __init__(self): # 明确注解:外层列表可包含子列表或 None,子列表可包含 QPointF 或 None self.all_roads_: List[Optional[List[Optional[QPointF]]]] = [] ``` --- ### 层解析 | 结构层级 | 类型注解 | 说明 | |---------------|---------------------------|----------------------------------------------------------------------| | **外层列表** | `List[...]` | 存储所有道路的集合 | | **中间层** | `Optional[...]` | 每条道路可能为 `None`(例如未初始化或占位符) | | **内层列表** | `List[Optional[QPointF]]` | 每条道路由多个坐标点组成,坐标点可为 `QPointF` 或 `None`(例如缺失点) | --- ### 使用示例 ```python # 创建对象 obj = YourClass() # 添加一条有效道路(包含两个坐标点) road1 = [QPointF(10, 20), QPointF(30, 40)] obj.all_roads_.append(road1) # 添加一条带缺失点的道路 road2 = [QPointF(50, 60), None, QPointF(70, 80)] obj.all_roads_.append(road2) # 添加一个空占位符 obj.all_roads_.append(None) # 访问数据 if obj.all_roads_[0] is not None: first_point = obj.all_roads_[0][0] # 类型提示会识别为 Optional[QPointF] ``` --- ### 常见问题解决方案 #### 1. **类型检查工具(如 mypy)报错** ```bash error: List expects exactly one type argument ``` **修正方法**:用 `Union` 或 `Optional` 组合多类型: ```python # 错误写法 List[QPointF, None] # 正确写法 List[Union[QPointF, None]] 或 List[Optional[QPointF]] # Optional[X] 等价于 Union[X, None] ``` #### 2. **运行时类型不匹配** Python 类型注解 **不会强制检查类型**,若需运行时验证: ```python from typing import List, Optional from PyQt5.QtCore import QPointF class RoadValidator: @staticmethod def validate_road(road: Optional[List[Optional[QPointF]]]) -> bool: if road is None: return True # 允许空占位符 return all(isinstance(point, (QPointF, type(None))) for point in road) # 使用示例 if not RoadValidator.validate_road(road1): raise ValueError("非法道路数据") ``` #### 3. **性能优化建议** - 若需高频访问坐标点,可用 `numpy` 替代嵌套列表: ```python import numpy as np from PyQt5.QtCore import QPointF # 将 QPointF 转换为 NumPy 数组 road_np = np.array([[p.x(), p.y()] if p is not None else [np.nan, np.nan] for p in road1]) ``` - 使用掩码处理 `None` 值: ```python mask = [point is not None for point in road2] valid_points = [point for point in road2 if point is not None] ``` --- ### 技术栈推荐 | 需求场景 | 推荐方案 | 工具链 | |------------------|----------------------------------|---------------------| | 严格类型检查 | `mypy` + `pydantic` 模型验证 | mypy, pydantic | | 高性能坐标处理 | 转换为 NumPy 数组 | numpy, numba | | 图形界面交互 | 直接使用 `QPointF` 列表 | PyQt5, PySide6 | | 数据持久化 | 序列化为 JSON 或二进制格式 | pickle, msgpack | --- 通过明确层类型注解和结合业务场景选择工具,可以显著提升代码可维护性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值