|
|
@ -1,11 +1,13 @@ |
|
|
|
import queue |
|
|
|
import queue |
|
|
|
|
|
|
|
|
|
|
|
q = queue.Queue() |
|
|
|
MAX_STEPS = 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
q = queue.PriorityQueue() |
|
|
|
valves = {} |
|
|
|
valves = {} |
|
|
|
valvesConsider = {} |
|
|
|
valvesConsider = {} |
|
|
|
destinationQue = queue.Queue() |
|
|
|
|
|
|
|
shortest = None |
|
|
|
|
|
|
|
distanceMap = {} |
|
|
|
distanceMap = {} |
|
|
|
|
|
|
|
eliminated = {} |
|
|
|
|
|
|
|
numTotalSteps = 0 |
|
|
|
|
|
|
|
|
|
|
|
class Valve(): |
|
|
|
class Valve(): |
|
|
|
def __init__(self, flowRate, tunnels, name): |
|
|
|
def __init__(self, flowRate, tunnels, name): |
|
|
@ -16,25 +18,71 @@ class Valve(): |
|
|
|
def getFlowrate(self): |
|
|
|
def getFlowrate(self): |
|
|
|
return self.flowRate |
|
|
|
return self.flowRate |
|
|
|
|
|
|
|
|
|
|
|
def moves(self, destination, length): |
|
|
|
def genDistanceMap(self): |
|
|
|
global shortest |
|
|
|
nextValves = queue.PriorityQueue() |
|
|
|
if shortest is not None and length >= shortest: |
|
|
|
nextValves.put((0, self)) |
|
|
|
return |
|
|
|
|
|
|
|
if self.name == destination: |
|
|
|
distanceMap[(self.name, self.name)] = 0 |
|
|
|
if shortest is None or length <= shortest: |
|
|
|
|
|
|
|
shortest = length |
|
|
|
while not nextValves.empty(): |
|
|
|
return |
|
|
|
curDist, valve = nextValves.get() |
|
|
|
_length = length + 1 |
|
|
|
|
|
|
|
for val in self.tunnels: |
|
|
|
for tunnel in valve.tunnels: |
|
|
|
destinationQue.put((val, destination, _length)) |
|
|
|
if (self.name, tunnel) in distanceMap: |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nextValve = valves[tunnel] |
|
|
|
|
|
|
|
nextDist = curDist + 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
distanceMap[(self.name, nextValve.name)] = nextDist |
|
|
|
|
|
|
|
nextValves.put((nextDist, nextValve)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __lt__(self, other): |
|
|
|
|
|
|
|
return self.flowRate < other.flowRate and self.name < other.name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def maxRemaining(remainingTime, possibleValves): |
|
|
|
|
|
|
|
nextSteps = [2 * x for x in range(int(remainingTime / 2) + 1)] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
allValveValues = list(reversed([v for _, v in possibleValves.items()])) |
|
|
|
|
|
|
|
possibleRemaining = 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for timeOffset in nextSteps: |
|
|
|
|
|
|
|
if timeOffset > remainingTime: |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(allValveValues) == 0: |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openFor = remainingTime - timeOffset |
|
|
|
|
|
|
|
possibleRemaining += allValveValues[0] * (remainingTime - timeOffset) |
|
|
|
|
|
|
|
allValveValues = allValveValues[1:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(allValveValues) == 0: |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
possibleRemaining += allValveValues[0] * (remainingTime - timeOffset) |
|
|
|
|
|
|
|
allValveValues = allValveValues[1:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return possibleRemaining |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def step(position1, position2, busy1, busy2, currentTime, pressure, _valvesCons): |
|
|
|
def step(position1, position2, busy1, busy2, currentTime, pressure, _valvesCons): |
|
|
|
global curentbest |
|
|
|
global curentbest |
|
|
|
|
|
|
|
global numTotalSteps |
|
|
|
|
|
|
|
global maxRemaining |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
numTotalSteps += 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if maxRemaining(MAX_STEPS - currentTime, _valvesCons) + pressure < curentbest: |
|
|
|
|
|
|
|
# There's no way we can get better than the current max pressure, so bail. |
|
|
|
|
|
|
|
eliminated.setdefault('maxRemaining', 0) |
|
|
|
|
|
|
|
eliminated['maxRemaining'] += 1 |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
done = False |
|
|
|
done = False |
|
|
|
if pressure > curentbest: |
|
|
|
if pressure > curentbest: |
|
|
|
print(1) |
|
|
|
|
|
|
|
curentbest = pressure |
|
|
|
curentbest = pressure |
|
|
|
if len(_valvesCons) == 0: |
|
|
|
if len(_valvesCons) == 0: |
|
|
|
return |
|
|
|
return |
|
|
@ -42,47 +90,45 @@ def step(position1, position2, busy1, busy2, currentTime, pressure, _valvesCons) |
|
|
|
for destination in _valvesCons: |
|
|
|
for destination in _valvesCons: |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
_dist = distanceMap[(position1, destination)] |
|
|
|
_dist = distanceMap[(position1, destination)] |
|
|
|
if (currentTime + _dist + 1) >= 26: |
|
|
|
if (currentTime + _dist + 1) >= MAX_STEPS: |
|
|
|
continue |
|
|
|
continue |
|
|
|
_busy1 =_dist + 1 |
|
|
|
_busy1 = _dist + 1 |
|
|
|
_pressure = pressure + ((26 - currentTime - _busy1)* _CopyCons[destination]) |
|
|
|
_pressure = pressure + ((MAX_STEPS - currentTime - _busy1) * _CopyCons[destination]) |
|
|
|
_CopyCons.pop(destination) |
|
|
|
_CopyCons.pop(destination) |
|
|
|
done = True |
|
|
|
done = True |
|
|
|
q.put((destination, position2, _busy1, busy2, currentTime, _pressure, _CopyCons)) |
|
|
|
q.put((_pressure * -1, destination, position2, _busy1, busy2, currentTime, _CopyCons)) |
|
|
|
if done: |
|
|
|
if done: |
|
|
|
return |
|
|
|
return |
|
|
|
if busy2 == 0: |
|
|
|
if busy2 == 0: |
|
|
|
for destination in _valvesCons: |
|
|
|
for destination in _valvesCons: |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
_dist = distanceMap[(position2, destination)] |
|
|
|
_dist = distanceMap[(position2, destination)] |
|
|
|
if (currentTime + _dist + 1) >= 26: |
|
|
|
if (currentTime + _dist + 1) >= MAX_STEPS: |
|
|
|
continue |
|
|
|
continue |
|
|
|
_busy2 =_dist + 1 |
|
|
|
_busy2 =_dist + 1 |
|
|
|
_pressure = pressure + ((26 - currentTime - _busy2)* _CopyCons[destination]) |
|
|
|
_pressure = pressure + ((MAX_STEPS - currentTime - _busy2)* _CopyCons[destination]) |
|
|
|
_CopyCons.pop(destination) |
|
|
|
_CopyCons.pop(destination) |
|
|
|
q.put((position1, destination, busy1, _busy2, currentTime, _pressure, _CopyCons)) |
|
|
|
done = True |
|
|
|
|
|
|
|
q.put((_pressure * -1, position1, destination, busy1, _busy2, currentTime, _CopyCons)) |
|
|
|
|
|
|
|
if done: |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
if busy1 <= 0 and busy2 <= 0: |
|
|
|
return |
|
|
|
return |
|
|
|
_currentTime = currentTime + 1 |
|
|
|
elif busy2 == 0: |
|
|
|
_busy1 = busy1 - 1 |
|
|
|
idle = busy1 |
|
|
|
_busy2 = busy2 - 1 |
|
|
|
elif busy1 == 0: |
|
|
|
|
|
|
|
idle = busy2 |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
idle = min(busy1, busy2) |
|
|
|
|
|
|
|
_currentTime = currentTime + idle |
|
|
|
|
|
|
|
_busy1 = busy1 - idle |
|
|
|
|
|
|
|
_busy2 = busy2 - idle |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
_CopyCons = _valvesCons.copy() |
|
|
|
if _currentTime >= 26: |
|
|
|
if _currentTime >= MAX_STEPS: |
|
|
|
return |
|
|
|
return |
|
|
|
q.put((position1, position2, _busy1, _busy2, _currentTime, pressure, _CopyCons)) |
|
|
|
q.put((pressure * -1, position1, position2, _busy1, _busy2, _currentTime, _CopyCons)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def distance(position, destination): |
|
|
|
|
|
|
|
global destinationQue |
|
|
|
|
|
|
|
global shortest |
|
|
|
|
|
|
|
shortest = None |
|
|
|
|
|
|
|
destinationQue.put((position, destination, 0)) |
|
|
|
|
|
|
|
while not destinationQue.empty(): |
|
|
|
|
|
|
|
_position, _destination, length = destinationQue.get() |
|
|
|
|
|
|
|
valves[_position].moves(_destination, length) |
|
|
|
|
|
|
|
return shortest |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openvalves = [] |
|
|
|
openvalves = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -103,21 +149,8 @@ for line in inp: |
|
|
|
newValve = Valve( flowRate, tunnels, _valve) |
|
|
|
newValve = Valve( flowRate, tunnels, _valve) |
|
|
|
valves[_valve] = newValve |
|
|
|
valves[_valve] = newValve |
|
|
|
|
|
|
|
|
|
|
|
n = 0 |
|
|
|
for _, valve in valves.items(): |
|
|
|
|
|
|
|
valve.genDistanceMap() |
|
|
|
for start in valvesConsider: |
|
|
|
|
|
|
|
n += 1 |
|
|
|
|
|
|
|
distanceMap[('AA', start)] = distance('AA', start) |
|
|
|
|
|
|
|
print(n) |
|
|
|
|
|
|
|
for end in valvesConsider: |
|
|
|
|
|
|
|
if (start, end) in distanceMap: |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
n += 1 |
|
|
|
|
|
|
|
_dist = distance(start, end) |
|
|
|
|
|
|
|
distanceMap[(start, end)] = _dist |
|
|
|
|
|
|
|
distanceMap[(end, start)] = _dist |
|
|
|
|
|
|
|
print(n) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i in distanceMap: |
|
|
|
for i in distanceMap: |
|
|
|
print(i, distanceMap[i]) |
|
|
|
print(i, distanceMap[i]) |
|
|
@ -126,12 +159,13 @@ position = 'AA' |
|
|
|
currentTime = 0 |
|
|
|
currentTime = 0 |
|
|
|
pressure = 0 |
|
|
|
pressure = 0 |
|
|
|
curentbest = 0 |
|
|
|
curentbest = 0 |
|
|
|
q.put((position, position, 0, 0, currentTime, pressure, valvesConsider)) |
|
|
|
q.put((pressure, position, position, 0, 0, currentTime, valvesConsider)) |
|
|
|
|
|
|
|
|
|
|
|
while not q.empty(): |
|
|
|
while not q.empty(): |
|
|
|
print(q.qsize()) |
|
|
|
#print(q.qsize()) |
|
|
|
position1, position2, busy1, busy2, currentTime, pressure, _valvesConsider = q.get() |
|
|
|
pressure, position1, position2, busy1, busy2, currentTime, _valvesConsider = q.get() |
|
|
|
step(position1, position2, busy1, busy2, currentTime, pressure, _valvesConsider) |
|
|
|
# print(q.qsize(), pressure, position1, position2, busy1, busy2, currentTime, numTotalSteps, eliminated) |
|
|
|
|
|
|
|
step(position1, position2, busy1, busy2, currentTime, pressure * -1, _valvesConsider) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(curentbest) |
|
|
|
print(curentbest) |
|
|
|