icpc 2018 World Finals Problem : A-Catch the Plane

Keywords: Python less

1. Title

Your plane to the ICPC Finals departs in a short time, and the only way to get to the airport is by bus.
Unfortunately, some of the bus drivers are considering going on strike, so you do not know whether
you can get to the airport on time. Your goal is to plan your journey in such a way as to maximize the
probability of catching your plane.
You have a detailed map of the city, which includes all the bus stations. You are at station 0 and the
airport is at station 1. You also have a complete schedule of when each bus leaves its start station and
arrives at its destination station. Additionally, for each bus you know the probability that it is actually
going to run as scheduled, as opposed to its driver going on strike and taking the bus out of service.
Assume all these events are independent. That is, the probability of a given bus running as planned does
not change if you know whether any of the other buses run as planned.
If you arrive before the departure time of a bus, you can transfer to that bus. But if you arrive exactly
at the departure time, you will not have enough time to get on the bus. You cannot verify ahead of time
whether a given bus will run as planned – you will find out only when you try to get on the bus. So if
two or more buses leave a station at the same time, you can try to get on only one of them.
Topic:
Your plane to the ICPC final will take off soon, and the only way to get to the airport is by bus.Unfortunately, some bus drivers are considering a strike, so you don't know if you can get to the airport on time.Your goal is to plan your journey in a way that maximizes your chances of catching up with the plane.

You have a detailed map of the city, including all bus stops.You are at station 0 and the airport is at station 1.You also have a complete schedule showing how long each bus leaves its starting point and arrives at its destination.
In addition, for each bus, you know the probability that it actually starts on a timetable, so you know the probability that its drivers will strike and stop service.Suppose all these events are independent.
That is, if you know whether any other bus is running on schedule, it does not change the probability that a given bus is running on schedule.

If you arrive before a bus leaves, you can change to that bus.But if you arrive just at the time when the bus leaves, you don't have enough time to get on.You can't verify in advance whether a given bus will run as planned, only if you decide to get on.
Therefore, if two or more buses leave a station at the same time, you can only try to take one of them.
Input sample:

Enter a description:

The first line of input contains two integers m(1 < m < 10610 ^ 6106) and n(2 < n < 10610 ^ 6106), representing the number of buses and the number of bus stops in the city.

The second line contains an integer k(1 < K < 101810 ^{18} 1018), which indicates when you must arrive at the airport.

The next m lines are descriptions of m buses.Each row contains integers a and b(0 < a, B < n, a neq= b), representing the start and destination of the car, respectively.Next, the integers s s and t(0 < s < T < k)) indicate the departure time from station a and the arrival time a t station B.The last value p(0 < p < 1, up to 10 digits after the decimal point) in each row indicates the probability that the bus will depart on schedule.

Output:

Gives you the probability of catching up with the plane on the best route.Output error does not exceed 10_610^{6}10_6

2. Analysis

Take input sample 1 (output 0.3124) as an example, and the following is its corresponding bus schedule:

Shift Departure station Destination Station Departure time Departure probability Arrival time
(1) 0 1 0 20% 900
(2) 0 2 100 100% 500
(3) 2 1 500 100% 700
(4) 2 1 501 10% 701
(5) 0 3 200 50% 400
(6) 3 1 500 10% 800
(7) 3 0 550 90% 650
(8) 0 1 700 10% 900

Look at the table above, which lists the start and end points of several bus routes, as well as the departure and arrival times.Next to the departure time, the probability of the route's normal operation is indicated, and if it is not, 100% of the route's normal operation is indicated.

We started at station 0, assuming we had bus number (1).If it works, it goes directly to the airport (station 1) and nothing else.If this train doesn't start properly, consider the following transfer plan.

At this point, you can consider taking the (2) bus from station 0 to station 2 and then from station 2 to station 1.First, the bus (2) will certainly start normally, but the time to reach station 2 is 500. Then look at bus (3). The departure time is 500, so I can't catch the bus (3).The departure time of bus (4) is 501, which can catch up, but the probability of normal departure is only 10%.We'll keep this scheme for a moment.See if there are any other options.

Consider taking the (5) bus from station 0 to station 3. The probability of departure is 50%, and the time to reach station 3 is 400.(6) The bus starts from 3 to 1, and the departure time is 500. It can catch up in time. The departure probability is 10%. If it starts normally, it will arrive at the airport directly.If you do not start normally, you can only return to station 0 by bus (7) at station 3 and then arrive at the airport by bus (8), and the probability of these two vehicles starting normally is 90% and 10%, respectively.

From the above analysis, the following tree chart can be drawn, in which the departure station is Station 0 and its number is inside.Each rectangular node below represents each route, and each rectangle has two parts. The key pairs in the first part represent the departure and destination sites of the route bus, respectively, and the probability of normal departure.The second part shows the probability of departure failure.For example, compared to the above departure timetable, there is a 0.2 probability from station 0 to reach station 1 by bus (1), while a 0.8 probability is other.The following figure shows:


Calculate the final output from this tree:

p = max{0.2+0.8*1*(0.1), 0.2+0.8*[0.5*(0.1+0.9*0.9*0.1+0.5*0.1), 0.2+0.8*0.1] = 0.3124}

Multiply by 0 is omitted (certainly not at the airport).The probability of two parts of each rectangular node (including subnodes) needs to be added together.Considering that there can only be at most one child node on the left part of the normal departure, and that if the departure fails, there may be more than one child node on the right part of the rectangular node (representing different transfer methods), then it is necessary to split it to calculate the probability of comparing each case and ultimately to get the maximum probability.

Similarity analysis input sample 2 yields:

p = max{0.5+0.5*0.4, 0.5+0.5*0.2, 0.5+0.5*0.4, 0.5+0.5*0.2} = 0.7}

3. Python Code Implementation

from decimal import Decimal

pathCount = 0
pathList = []
stationCount = 0
maxArriveTime = 0

# Node class, representing route
class Node:
    pT = 0  # Probability of normal departure
    pF = 1 - pT  # Probability of strikes
    startStation = 0  # Route departure station
    endStation = 0  # Route Destination Site
    startTime = 0  # Departure time
    endTime = 0  # Arrival time
    leftNode = None  # Left Subtree
    rightNodes = []  # Right Subtree

    def __init__(self, startStation, endStation, startTime, endTime, pT):
        self.startStation = int(startStation)
        self.endStation = int(endStation)
        self.startTime = int(startTime)
        self.endTime = int(endTime)
        self.pT = Decimal(pT)
        self.pF = Decimal(1.0) - self.pT

    def prt(self):
        print(self.startStation, self.endStation, self.startTime, self.endTime, self.pT, self.pF)

def printNodes(list):
    for node in list:
        node.prt()

# Load input data. /input1.txt
def loadInput(path):
    pathList = []
    f = open(path)
    ln = 0
    for line in f:
        if ln == 0:
            pathCount, stationCount = line.split()
        else:
            if ln == 1:
                maxArriveTime = line
            else:
                startStation, endStation, startTime, endTime, pT = line.split()
                node = Node(startStation, endStation, startTime, endTime, pT)
                pathList.append(Node(node.startStation, node.endStation, node.startTime, node.endTime, node.pT))
        ln = ln + 1
    f.close()
    return pathCount, stationCount, pathList, maxArriveTime

# Find a route starting from startStation
def findNodeStartAs(startStation, lastEndTime):
    stations = []
    for node in pathList:
        if (node.startStation == startStation and node.startTime > lastEndTime):
            stations.append(node)
    return stations

# Building a tree from a timetable
def buildTree(node):
    if node:
        # Fallback finds all routes starting from the last departure and adds them all to the right subtree
        rightStations = findNodeStartAs(node.startStation, node.startTime)

        # Find all the routes starting from the current station and select the first as the left subtree
        leftStations = findNodeStartAs(node.endStation, node.endTime)
        if len(leftStations) > 0:
            leftNode = leftStations[0]

        # No matter what the probability is, the first departure car is set to leftNode
        if node.endStation != 1:
            node.leftNode = leftNode
        # Construct left subtree recursively
        buildTree(node.leftNode)

        # Since the departure probability is less than 1, other considerations are needed, so a right subtree is added.
        if node.pT < 1:
            node.rightNodes = rightStations
            # Recursively build right subtree
            for rnode in node.rightNodes:
                buildTree(rnode)

# Calculate maximum probability
def caculateProbability(node):
    if node == None:
        return 0

    # Recursively find the maximum probability value of the right subtree, that is, the maximum probability value of the departure failure and transfer
    rightNodesP = []
    rightP = 0;
    if node.rightNodes and len(node.rightNodes) > 0:
        for rnode in node.rightNodes:
            rightNodesP.append(caculateProbability(rnode))
            rightP = max(rightNodesP)

    # Recursively find the maximum probability value of the left subtree, that is, the normal departure probability value
    leftP = 1;
    if node.leftNode:
        leftP = caculateProbability(node.leftNode)
    else:
        leftP = 1

    # Left subtree probability plus right subtree probability
    return node.pT * leftP + node.pF * rightP

# Step1: Read input samples
pathCount, stationCount, pathList, maxArriveTime = loadInput("./input1.txt")

# Step2: Construct a virtual initial node
initNode = Node(0, 0, 0, -1, 1)

# Step3: Execute the method to construct the tree
buildTree(initNode)

# Step4: Execute the method of calculating probability
print("Sample 1 output:",caculateProbability(initNode))

Output after execution:

0.3124

Verify that the output of input sample 2 is 0.7, and that's OK.

THE END.

Posted by ViperSBT on Fri, 26 Apr 2019 23:36:36 -0700