求解从城市1到城市n且至少访问3个奇数城市的最小代价路径问题
问题修正方案
原代码的核心错误
- 初始状态错误:起点是城市1,而1是奇数,所以初始访问的奇数城市数量应该是1,原代码中
start_state返回(0, 1)不符合实际情况。 - 后继状态计算逻辑错误:在
succ_and_cost的循环中,直接修改了原状态的number_of_odd_visited_citites变量,导致后续循环的计数会基于前一次修改后的值累加,这会造成奇数城市数量统计错误。正确的做法是每次基于原状态的数值,独立计算新状态的计数。
修正后的代码
class OddCitiesProblem: def __init__(self, n, costs): self.n = n self.costs = costs # cost to move from i to j is costs[i][j] def start_state(self) -> tuple[int, int]: # 城市1是奇数,初始已访问1个奇数城市 return (1, 1) # (已访问奇数城市数, 当前城市) def is_end(self, state) -> bool: number_of_odd_visited_citites, current_state = state # 终点是城市n,且已访问至少3个奇数城市 return current_state == self.n and number_of_odd_visited_citites >= 3 def succ_and_cost(self, state: tuple[int, int]) -> list[tuple]: number_of_odd_visited_citites, current_city = state result = [] # 每个元素是(新状态, 移动代价) for next_city in range(current_city + 1, self.n + 1): # 基于原状态的计数,计算新的奇数城市数量 new_odd_count = number_of_odd_visited_citites if next_city % 2 == 1: new_odd_count += 1 # 超过3个的话,只记录3即可(因为只需要至少3个,多了不影响条件) new_odd_count = min(new_odd_count, 3) new_state = (new_odd_count, next_city) # 注意索引转换:城市编号从1开始,costs是0索引的二维数组 cost = self.costs[current_city - 1][next_city - 1] result.append((new_state, cost)) return result
关键修改说明
- 初始状态修正:将
start_state的返回值改为(1, 1),因为起点城市1本身就是奇数,初始已访问1个奇数城市。 - 后继状态计数修正:在循环中不再修改原状态的
number_of_odd_visited_citites,而是每次创建临时变量new_odd_count基于原状态值计算,确保每个后继状态的计数都是独立正确的。 - 逻辑一致性:保留
min(new_odd_count, 3)的处理,因为当已访问的奇数城市数达到3后,后续再访问奇数城市不会改变状态的这部分值,减少状态空间的大小,提升搜索效率。
内容的提问来源于stack exchange,提问作者Murad Aliyev
相关产品推荐
相关产品推荐

