def drivable_pairs(grid, rows, cols): """ This function takes a grid of R rows and C columns, and returns a list of all drivable pairs with the start letter first and the finish letter second, in alphabetical order. Parameters: grid (list): A list of strings representing the grid. rows (int): The number of rows in the grid. cols (int): The number of columns in the grid. Returns: list: A list of all drivable pairs with the start letter first and the finish letter second, in alphabetical order. """ # Initialize the list of drivable pairs drivable_pairs = [] # Iterate through the grid for i in range(rows): for j in range(cols): # Check if the current cell is an interesting start if grid[i][j].islower(): # Get the start letter start_letter = grid[i][j] # Iterate through the grid again for x in range(rows): for y in range(cols): # Check if the current cell is an interesting finish if grid[x][y].isupper(): # Get the finish letter finish_letter = grid[x][y] # Check if the start and finish letters are different if start_letter != finish_letter: # Check if the start and finish letters are drivable if is_drivable(grid, rows, cols, i, j, x, y): # Append the drivable pair to the list drivable_pairs.append(start_letter + finish_letter) # Sort the list of drivable pairs in alphabetical order drivable_pairs.sort() # Return the list of drivable pairs return drivable_pairs def is_drivable(grid, rows, cols, start_row, start_col, finish_row, finish_col): """ This function takes a grid of R rows and C columns, and two coordinates representing the start and finish cells, and returns True if the start and finish cells are drivable, False otherwise. Parameters: grid (list): A list of strings representing the grid. rows (int): The number of rows in the grid. cols (int): The number of columns in the grid. start_row (int): The row coordinate of the start cell. start_col (int): The column coordinate of the start cell. finish_row (int): The row coordinate of the finish cell. finish_col (int): The column coordinate of the finish cell. Returns: bool: True if the start and finish cells are drivable, False otherwise. """ # Initialize the queue of cells to visit queue = [] # Add the start cell to the queue queue.append((start_row, start_col)) # Initialize the visited set visited = set() # Initialize the probability of reaching the finish cell probability = 0 # Iterate through the queue while queue: # Get the current cell row, col = queue.pop(0) # Check if the current cell is the finish cell if row == finish_row and col == finish_col: # Increase the probability of reaching the finish cell probability += 0.5 # Check if the probability is greater than or equal to 1 - 10^(-100) if probability >= 1 - 10**(-100): # Return True return True # Continue to the next iteration continue # Check if the current cell is already visited if (row, col) in visited: # Continue to the next iteration continue # Add the current cell to the visited set visited.add((row, col)) # Iterate through the 4 directions for direction in ["north", "south", "east", "west"]: # Get the next cell next_row, next_col = get_next_cell(grid, rows, cols, row, col, direction) # Check if the next cell is valid if next_row != -1 and next_col != -1: # Add the next cell to the queue queue.append((next_row, next_col)) # Return False return False def get_next_cell(grid, rows, cols, row, col, direction): """ This function takes a grid of R rows and C columns, and two coordinates representing the current cell, and a direction, and returns the coordinates of the next cell. Parameters: grid (list): A list of strings representing the grid. rows (int): The number of rows in the grid. cols (int): The number of columns in the grid. row (int): The row coordinate of the current cell. col (int): The column coordinate of the current cell. direction (str): The direction of the next cell. Returns: tuple: The coordinates of the next cell. """ # Check the direction if direction == "north": # Get the next cell next_row = row - 1 next_col = col elif direction == "south": # Get the next cell next_row = row + 1 next_col = col elif direction == "east": # Get the next cell next_row = row next_col = col + 1 elif direction == "west": # Get the next cell next_row = row next_col = col - 1 # Check if the next cell is valid if next_row < 0 or next_row >= rows or next_col < 0 or next_col >= cols or grid[next_row][next_col] == "#" or grid[next_row][next_col] == "*": # Return an invalid cell return -1, -1 # Return the next cell return next_row, next_col # Read the number of test cases t = int(input()) # Iterate through the test cases for i in range(1, t + 1): # Read the number of rows and columns rows, cols = map(int, input().split()) # Initialize the grid grid = [] # Read the grid for _ in range(rows): grid.append(list(input())) # Get the list of drivable pairs drivable_pairs = drivable_pairs(grid, rows, cols) # Check if there are any drivable pairs if len(drivable_pairs) == 0: # Print the output print("Case #{}: NONE".format(i)) else: # Print the output print("Case #{}: {}".format(i, " ".join(drivable_pairs)))