#!/usr/bin/python3 # Author: Jirka Setnička import math from collections import deque from typing import Tuple smerSouradnice = { 'L': (0, -1), 'P': (0, 1), 'N': (-1, 0), 'D': (1, 0), '-': (0, 0) } class Policko: typ: str prvniRaketa: int d: int # Vzdálenost v krocích od startu smer: str # V jakém směru jsme přišli na políčko, pro rekonstrukci cesty def __init__(self, typ: str): self.typ = typ self.prvniRaketa = math.inf self.odkud = None # Ještě nenavštíveno, pro rekonstrukci cesty class Turret: pozice: Tuple[int, int] smer: Tuple[int, int] interval: int def __init__(self, r: int, s: int, smer: str, interval: int): self.pozice = (r, s) self.smer = smerSouradnice[smer] self.interval = interval ################################################################################ # 1. Načtení vstupu (R, S, T) = map(int, input().split()) start = (0, 0, 0) mapa = [] for r in range(R): vstup = input() radek = [] for s in range(S): typ = vstup[s] if typ == "S": start = (0, r, s) # Startujeme v čase 0 typ = "." # Z hlediska mapy je to prázdné políčko radek.append(Policko(typ)) mapa.append(radek) turrety = [] intervaly = set() for t in range(T): r, s, smer, interval = input().split() turrety.append(Turret(int(r), int(s), smer, int(interval))) intervaly.add(int(interval)) # 2. Spočtení nejmenšího společného násobku intervalů a zduplikování mapy lcm = intervaly.pop() for i in intervaly: lcm = lcm * i // math.gcd(lcm, i) mapy = [] mapy.append(mapa) for _ in range(1, lcm): mapy.append([ [Policko(policko.typ) for policko in radek] for radek in mapa ]) # 3. Zaneseme do jednotlivých "vrstev" všechny rakety vystřelené z turretů for t in turrety: (r, s) = t.pozice (dr, ds) = t.smer d = -1 # v jaké vzdálenosti od turretu jsme while True: d += 1 r += dr s += ds # Pokud jsme venku z mapy, tak končíme if r >= R or r < 0 or s >= S or s < 0: break # Pokud raketa narazila do zdi nebo jiného turretu, tak končíme if mapy[0][r][s].typ == '#' or mapy[0][r][s].typ == 'T': break # Spočteme v jakém čase se tu raketa objeví = do jaké "vrstvy" ji zakreslit faze = d % lcm # Pokud je interval menší než lcm, musíme to udělat cyklicky pro všechny # vystřelené během lcm (tedy tolikrát, kolikrát se interval vejde do lcm) for i in range(lcm // t.interval): ted = (faze + i*t.interval) % lcm pristi = (faze + i*t.interval + 1) % lcm mapy[ted][r][s].typ = 'X' # teď je tu raketa mapy[pristi][r][s].typ = 'x' # v příštím kroku tu bude raketový plamen # Zaznamenáme si i časy, kdy poprvé od začátku se políčko v této fázi # stane obsazeným raketou, do té doby je volné (speciální případ na # začátku, než první rakety dolétnout až do konce svých drah). mapy[ted][r][s].prvniRaketa = min(mapy[ted][r][s].prvniRaketa, d + i*t.interval) mapy[pristi][r][s].prvniRaketa = min(mapy[pristi][r][s].prvniRaketa, d + i*t.interval + 1) # 4. Spustíme prohledávání do šířky a najdeme cestu fronta = deque() fronta.append(start) (_, r, s) = start cil = None while fronta: (d, r, s) = fronta.popleft() d += 1 for smer in "-LPND": (dr, ds) = smerSouradnice[smer] rr = r + dr ss = s + ds if rr >= R or rr < 0 or ss >= S or ss < 0: continue faze = d % lcm policko = mapy[faze][rr][ss] if policko.typ == 'C': policko.odkud = smer cil = (d, rr, ss) break if policko.odkud is not None: continue # již zpracováno if policko.typ == '.' or (policko.typ.upper() == 'X' and policko.prvniRaketa > d): # Buď prázdné políčko nebo políčko s raketou, která sem ale ještě # nestihla dolétnout (výjimka pro začátek) policko.odkud = smer fronta.append((d, rr, ss)) if cil is not None: break # 5. Vypsání cesty z cíle (d, r, s) = cil print(d) cesta = [] while d > 0: faze = d % lcm odkud = mapy[faze][r][s].odkud cesta.append(odkud) (dr, ds) = smerSouradnice[odkud] r -= dr s -= ds d -= 1 print("".join(reversed(cesta)))