Orig Description
Problem F: Mysterious Dungeons
The Kingdom of Aqua Canora Mystica is a very affluent and peaceful country, but around the
kingdom, there are many evil monsters that kill people. So the king gave an order to you to kill
the master monster.
You came to the dungeon where the monster lived. The dungeon consists of a grid of square
cells. You explored the dungeon moving up, down, left and right. You finally found, fought
against, and killed the monster.
Now, you are going to get out of the dungeon and return home. However, you found strange
carpets and big rocks are placed in the dungeon, which were not there until you killed the
monster. They are caused by the final magic the monster cast just before its death! Every rock
occupies one whole cell, and you cannot go through that cell. Also, each carpet covers exactly
one cell. Each rock is labeled by an uppercase letter and each carpet by a lowercase. Some of
the rocks and carpets may have the same label.
While going around in the dungeon, you observed the following behaviors. When you enter
into the cell covered by a carpet, all the rocks labeled with the corresponding letter (e.g., the
rocks with ‘A’ for the carpets with ‘a’) disappear. After the disappearance, you can enter the
cells where the rocks disappeared, but if you enter the same carpet cell again or another carpet
cell with the same label, the rocks revive and prevent your entrance again. After the revival,
you have to move on the corresponding carpet cell again in order to have those rocks disappear
again.
Can you exit from the dungeon? If you can, how quickly can you exit? Your task is to write
a program that determines whether you can exit the dungeon, and computes the minimum
required time.
Input
The input consists of some data sets.
Each data set begins with a line containing two integers, W and H (3 ≤ W, H ≤ 30). In each
of the following H lines, there are W characters, describing the map of the dungeon as W × H
grid of square cells. Each character is one of the following:
‘@’ denoting your current position,
‘<’ denoting the exit of the dungeon,
A lowercase letter denoting a cell covered by a carpet with the label of that letter,
An uppercase letter denoting a cell occupied by a rock with the label of that letter,
‘#’ denoting a wall, and
‘.’ denoting an empty cell.
Every dungeon is surrounded by wall cells (‘#’), and has exactly one ‘@’ cell and one ‘<’ cell.
There can be up to eight distinct uppercase labels for the rocks and eight distinct lowercase
labels for the carpets.
You can move to one of adjacent cells (up, down, left, or right) in one second. You cannot move
to wall cells or the rock cells.
A line containing two zeros indicates the end of the input, and should not be processed.
Output
For each data set, output the minimum time required to move from the ‘@’ cell to the ‘<’ cell,
in seconds, in one line. If you cannot exit, output -1.
Sample Input
8 3
########
#
Extracted Specification
An integer W (3 ≤ W ≤ 30), representing some width.
An integer H (3 ≤ H ≤ 30), representing some height.
A list of H strings, each containing W characters from the set {'@', '<', 'a'-'z', 'A'-'Z', '#', '.'}.
The end of the input is indicated by a line containing two zeros.
### Example Input:
```
8 3
########
#
Test Case Generator
Sure, here is a Python function to generate test cases for the "Mysterious Dungeons" problem. This function will generate random dungeon configurations based on the given constraints:
```python
import random
import string
def generate_grid(W, H):
grid = [['#'] * W for _ in range(H)]
# Place walls around the grid
for i in range(W):
grid[0][i] = '#'
grid[H-1][i] = '#'
for i in range(H):
grid[i][0] = '#'
grid[i][W-1] = '#'
# Place @ and < ensuring they are not on walls
at_x, at_y = random.randint(1, H-2), random.randint(1, W-2)
grid[at_x][at_y] = '@'
exit_x, exit_y = random.randint(1, H-2), random.randint(1, W-2)
while (exit_x, exit_y) == (at_x, at_y):
exit_x, exit_y = random.randint(1, H-2), random.randint(1, W-2)
grid[exit_x][exit_y] = '<'
# Place rocks and carpets randomly
num_labels = random.randint(1, 8)
labels = random.sample(string.ascii_letters, num_labels * 2)
carpet_labels = labels[:num_labels]
rock_labels = [l.upper() for l in carpet_labels]
for label in carpet_labels + rock_labels:
x, y = random.randint(1, H-2), random.randint(1, W-2)
while grid[x][y] != '.':
x, y = random.randint(1, H-2), random.randint(1, W-2)
grid[x][y] = label
# Fill the remaining cells with empty spaces
for i in range(1, H-1):
for j in range(1, W-1):
if grid[i][j] == '#':
continue
if grid[i][j] == '.':
grid[i][j] = random.choice(['.', '#'])
return grid
def tcgen():
test_cases = []
while True:
W = random.randint(3, 30)
H = random.randint(3, 30)
grid = generate_grid(W, H)
test_cases.append((W, H, grid))
if random.random() < 0.1: # Randomly decide when to stop
break
test_cases.append((0, 0, [])) # Termination case
return test_cases
def format_test_case(tc):
W, H, grid = tc
if W == 0 and H == 0:
return "0 0\n"
result = f"{W} {H}\n"
for row in grid:
result += ''.join(row) + '\n'
return result
# Generate test cases
test_cases = tcgen()
# Print formatted test cases
for tc in test_cases:
print(format_test_case(tc))
```
This code will generate random dungeons with the constraints given in the problem statement. Each dungeon is surrounded by walls, and it includes exactly one starting position (`@`) and one exit (`<`). There can be up to eight distinct pairs of carpets and rocks. The function will keep generating random test cases until it decides to stop, and it always includes the termination case `0 0`.
You can then run this code and use the generated test cases to test your solution to the problem.
Extract Arguments
def extract_arguments(fh):
data_sets = []
while True:
line = fh.readline().strip()
if line == "0 0":
break
W, H = map(int, line.split())
grid = [fh.readline().strip() for _ in range(H)]
data_sets.append((W, H, grid))
return data_sets
# if __name__ == "__main__":
# input_path = sys.argv[1]
# with open(input_path, 'r') as fh:
# data_sets = extract_arguments(fh)
# for data in data_sets:
# f(*data)