from collections import deque def bfs(graph, start, finish): # initialize the queue and visited set q = deque([(start, 1)]) visited = set([start]) while q: curr, prob = q.popleft() if curr == finish: return prob # check all neighboring cells for dx, dy, command in [(0, 1, 'east'), (0, -1, 'west'), (1, 0, 'south'), (-1, 0, 'north')]: nx, ny = curr[0] + dx, curr[1] + dy if (nx, ny) not in graph: continue if graph[nx, ny] == '#': continue if graph[nx, ny] == '*': # if we hit a hazard, we can't move anymore continue # check if the command will make us move in the right direction if (dx == 1 and command in ('south', 'north')) or (dx == -1 and command in ('north', 'south')): prob_command = 0.5 elif (dy == 1 and command in ('east', 'west')) or (dy == -1 and command in ('west', 'east')): prob_command = 0.5 else: prob_command = 0.0 if (nx, ny) == finish: # if we reach the finish, add to probability and continue to next cell q.append(((nx, ny), prob * prob_command)) continue if (nx, ny) not in visited: # if we haven't visited the cell before, add to queue and visited set q.append(((nx, ny), prob * prob_command)) visited.add((nx, ny)) return 0.0 def solve_case(case_num, grid): graph = {} starts = {} finishes = {} # build the graph and find interesting cells for i in range(len(grid)): for j in range(len(grid[i])): if grid[i][j] != '#': graph[i, j] = grid[i][j] if grid[i][j].islower(): starts[grid[i][j]] = (i, j) elif grid[i][j].isupper(): finishes[grid[i][j]] = (i, j) # find all drivable pairs drivable_pairs = [] for start, start_pos in starts.items(): for finish, finish_pos in finishes.items(): prob = bfs(graph, start_pos, finish_pos) if prob >= 1 - 10 ** (-100): drivable_pairs.append(start + finish) # output the results if not drivable_pairs: print(f"Case #{case_num}: NONE") else: drivable_pairs.sort() print(f"Case #{case_num}: {' '.join(drivable_pairs)}") # read input T = int(input()) for i in range(T): R, C = map(int, input().split()) grid = [input().strip() for _ in range(R)] solve_case(i+1, grid)