import sys
rows = 4
cols = 4
matrix = [[0, 1,1,1], [30, 30,-1,40],[0, 20,20,40],[10, -1,30,40]]
offsets = ((-1, 0), (1, 0), (0, -1), (0, 1))
class Node:
def __init__(self, x, y):
self.x = x
self.y = y
self.initial_energy = 0
self.remaining_energy = 0
self.has_energy_booster = False
def bfs():
if matrix[0][0] == 0 or matrix[rows - 1][cols - 1] == 0:
return -1
queue = []
src = Node(0, 0)
if matrix[0][0] == -1:
src.initial_energy = 0
src.remaining_energy = 100
src.has_energy_booster = True
else:
src.initial_energy = matrix[0][0]
src.remaining_energy = 0
src.has_energy_booster = False
queue.append(src)
distance_from_start = [[sys.maxsize] * cols for _ in range(rows)]
remaining_energy_at_destination = [[0] * cols for _ in range(rows)]
distance_from_start[0][0] = src.initial_energy
remaining_energy_at_destination[0][0] = src.remaining_energy
while len(queue) > 0:
cur = queue.pop(0)
for offsetX, offsetY in offsets:
newX = cur.x + offsetX
newY = cur.y + offsetY
if newX < 0 or newX >= rows or newY < 0 or newY >= cols or matrix[newX][newY] == 0:
continue
initial_energy = cur.initial_energy
remaining_energy = cur.remaining_energy
has_energy_booster = cur.has_energy_booster
if matrix[newX][newY] == -1:
remaining_energy = 100
has_energy_booster = True
else:
remaining_energy -= matrix[newX][newY]
if remaining_energy < 0:
if has_energy_booster:
continue
else:
initial_energy -= remaining_energy
remaining_energy = 0
if initial_energy > 100:
continue
if initial_energy > distance_from_start[newX][newY]:
continue
if initial_energy < distance_from_start[newX][newY] or remaining_energy > \
remaining_energy_at_destination[newX][newY]:
distance_from_start[newX][newY] = initial_energy
remaining_energy_at_destination[newX][newY] = remaining_energy
nxt = Node(newX, newY)
nxt.initial_energy = initial_energy
nxt.remaining_energy = remaining_energy
nxt.has_energy_booster = has_energy_booster
queue.append(nxt)
if distance_from_start[rows - 1][cols - 1] == sys.maxsize:
return -1
else:
return distance_from_start[rows - 1][cols - 1]
print(bfs())