Python 带权顶点图的最短路径计算

Python 带权顶点图的最短路径计算,python,shortest-path,dijkstra,path-finding,kattis,Python,Shortest Path,Dijkstra,Path Finding,Kattis,我目前正在研究一个kattis问题:寻宝。目标是找到一条花费最少天数到达宝藏的路径 我目前使用Dijkstra算法和加权顶点来计算通往宝藏的最短路径。我已经定义了一个类“节点”,在其中我定义了它的权重和前一个节点(如果已分配)。我使用heapq,需要覆盖节点类中的lt方法 当定义最短路线时,我尝试计算完成这条最短路线所需的天数 我知道这不是罚款规则,对不起 定义邻居节点和路径查找 def createNode(行): rl=列表() 对于第行中的x: rl.append(节点(x)) 返回rl

我目前正在研究一个kattis问题:寻宝。目标是找到一条花费最少天数到达宝藏的路径

我目前使用Dijkstra算法和加权顶点来计算通往宝藏的最短路径。我已经定义了一个类“节点”,在其中我定义了它的权重和前一个节点(如果已分配)。我使用heapq,需要覆盖节点类中的lt方法

当定义最短路线时,我尝试计算完成这条最短路线所需的天数

我知道这不是罚款规则,对不起

定义邻居节点和路径查找

def createNode(行):
rl=列表()
对于第行中的x:
rl.append(节点(x))
返回rl
行,列,耐力=映射(int,input().split(“”))
宝藏地图=列表()
对于范围内的行(行):
宝藏地图。附加(列表(输入())
宝藏地图=列表(地图(createNode,宝藏地图))
对于范围内的x(len(宝藏地图)):
对于范围内的y(len(宝藏地图[x]):
瓷砖=宝藏地图[x][y]
#将平铺添加到南链接
如果x-1>=0且宝藏地图[x-1][y]不是无:
添加邻居(宝藏地图[x-1][y])
如果y+1=0且宝藏地图[x][y-1]不是无:
添加邻居(宝藏地图[x][y-1])
已访问=列表()
节点=列表()
对于宝藏地图中的x:
对于x中的y:
如果y.name不是“#”:
nodes.append(y)
heapq.heapify(节点)
端点=无
如果len(节点)<2:
打印(-1)
#以最小负载搜索路径
而节点:
curr=heapq.heapop(节点)
如果当前名称为“G”:
端点=电流
打破
对于当前的节点,get_Neights():
如果节点未处于已访问状态,且不是node.load>耐力:
如果当前重量+当前负载<节点重量:
节点。添加上一个节点(当前)
已访问。附加(curr)
heapq.heapify(节点)
计算从开始到结束所需天数的代码:(我再次知道这可能会更好)

如果端点不是无:
nexNode=endpoint.previous
发现=错误
耐力使用=列表()
而nexNode:
如果nexNode.name==“S”:
#也许算一算这一天吧
找到=真
要使用的耐力。追加(nexNode.load)
nexNode=nexNode.previous
天数=1
耐力
计数器=0
使用耐力。反向()
#计算完成所需的天数
在使用耐力时:
tocheck=耐力要使用。pop()
#打印(“当前天数:{},当前耐力:{},撤回耐力{}”。格式(
#天、币、币)
如果电流>耐力:
打印(-1)
打破
如果(当前检查)<0:
天数+=1
耐力
curr-=tocheck
如果发现:
打印(天)
其他:
打印(-1)
其他:
打印(-1)
结果正如我所期望的,我根据自己的测试用例和kattis上的测试用例得到了最短路径和正确的天数。但由于某种原因,当我将项目提交给kattis时,前8个左右的测试用例通过了,然后我突然得到:“错误答案”,我不知道我的思维或代码中的错误在哪里。我的方法是正确的还是应该使用不同的方法。还是仅仅在计算天数时犯了一个简单的错误


提前感谢

这里有一个几乎可以使用的解决方案,缺少一个小检查

这样,您需要了解它的功能:)

BIG_NUMBER=9999
耐力成本={F':2,'M':3}
def可能更新(字段1、字段2、迷宫、花费的时间、n、m、k、更新的字段):
i1,j1=字段1
i2,j2=字段2

如果不是(0)您确定可以将查找最短路线与计算天数分开吗?想象一下最短路线穿过山脉,但绕着山脉的路线稍长一些。这条路线可能需要更少的天数,因为您可以每天使用所有的体力。我想这就是问题所在。我将尝试不同的方法。谢谢非常感谢!@fafl,我尝试了很多,但都没有成功。你知道我如何解决这个问题,或者这种问题是如何命名的,这样我可以寻找其他的可能性吗?谢谢你,非常感谢,我知道它在做什么,我看到了你缺少的检查。我也喜欢你在没有课的情况下处理问题的方式。我通常编写面向对象的代码,但这种方法非常简单明了。@Kasper很高兴听到你成功的消息:)@Kasper如果它解决了你的问题,不要忘记接受答案,这样人们就可以知道你成功地解决了你的问题:)
BIG_NUMBER = 9999
STAMINA_COST = {'F': 2, 'M': 3}

def maybe_update(field1, field2, maze, time_taken, n, m, k, updated_fields):
    i1, j1 = field1
    i2, j2 = field2
    if not (0 <= i2 < n and 0 <= j2 < m):
        # Out of bounds
        return
    field = maze[i2][j2]
    if field == '#':
        # Can not walk on river
        return
    days_taken, stamina_taken = time_taken[i1][j1]
    stamina_to_move = STAMINA_COST.get(field, 1)
    stamina_taken += stamina_to_move
    if k < stamina_taken:
        days_taken += 1
        stamina_taken = stamina_to_move
    new_time_taken = (days_taken, stamina_taken)
    if new_time_taken < time_taken[i2][j2]:
        time_taken[i2][j2] = new_time_taken
        updated_fields.add((i2, j2))

def main():
    # Read input
    n, m, k = map(int, input().split())
    maze = []
    for i in range(n):
        line = input()
        maze.append(line)

    # Create map of how long it takes to get somewhere
    # Each field has (days_spent, stamina_spent)
    time_taken = []
    for i in range(n):
        time_taken.append([(BIG_NUMBER, BIG_NUMBER) for j in range(m)])

    # Look for the start and mark it as (1, 0), also look for the gold
    updated_fields = set()
    for i in range(n):
        for j in range(m):
            if maze[i][j] == 'S':
                time_taken[i][j] = (1, 0)
                updated_fields.add((i, j))
            elif maze[i][j] == 'G':
                gold_at = (i, j)

    # BFS to propagate time_taken
    while updated_fields:
        i, j = updated_fields.pop()
        maybe_update((i, j), (i + 1, j), maze, time_taken, n, m, k, updated_fields)
        maybe_update((i, j), (i - 1, j), maze, time_taken, n, m, k, updated_fields)
        maybe_update((i, j), (i, j + 1), maze, time_taken, n, m, k, updated_fields)
        maybe_update((i, j), (i, j - 1), maze, time_taken, n, m, k, updated_fields)

    # Print days taken to get to the gold
    i, j = gold_at
    days_taken = time_taken[i][j][0]
    print(-1 if days_taken == BIG_NUMBER else days_taken)

if __name__ == '__main__':
    main()