<白駿>Gold 2-14499サイコロ転がり


さいころを振る


タイムアウトメモリで正解を提出した人の正解率2秒512 MB 3468815297107623084%

質問する


サイズN×M人マップが存在します.地図の右側は東で、上は北です.この地図にはサイコロが置いてあり、サイコロの展開図は以下の通りです.地図の座標は(r,c)で表され,rは北から来た格の個数,cは西から来た格の個数である.
X 2 X
4 1 3
X 5 X
X 6 X
サイコロは地図上に置いてあり、上は1、東向きは3、置いた場所の座標は(x,y).最初はサイコロの各面に0と書いてありました.
地図の各段には整数が書いてあります.サイコロを投げると、移動した四角形の数字が0の場合、サイコロの底の数字が四角形にコピーされます.0でない場合、セルの数値はサイコロの底面にコピーされ、セルの数値は0になります.
サイコロの座標と移動コマンドが与えられた場合、サイコロを移動するたびに上記の値が要求されるプログラムを作成します.
サイコロは地図の外に移動できません.外に移動する場合は、コマンドを無視し、出力できません.

入力


1行目は、地図の縦サイズN、横サイズM(1≦N、M≦20)、サイコロの座標x、y(0≦x≦N−1、0≦y≦M−1)、およびコマンドの個数K(1≦K≦1000)を与える.
2行目からN行目まで、地図の数字は北から南まで、各行は西から東まで順番に与えられます.サイコロの格子に書いてある数字はいつも0です.地図の各段に書かれている数字は10未満の自然数または0です.
最後の行には、移動のコマンドが順番に表示されます.東1、西2、北3、南4.

しゅつりょく


移動するたびにサイコロに書いてある数字が出力されます.外に移動する場合は、コマンドを無視し、出力できません.

入力例1


4 2 0 0 8
0 2
3 4
5 6
7 8
4 4 4 1 3 3 3 2

サンプル出力1


0
0
3
0
0
8
6
3

入力例2


3 3 1 1 9
1 2 3
4 0 5
6 7 8
1 3 2 2 4 4 1 1 3

サンプル出力2


0
0
0
3
0
1
0
6
0

入力例3


2 2 0 0 16
0 2
3 4
4 4 4 4 1 1 1 1 3 3 3 3 2 2 2 2

サンプル出力3


0
0
0
0

入力例4


3 3 0 0 16
0 1 2
3 4 5
6 7 8
4 4 1 1 3 3 2 2 4 4 1 1 3 3 2 2

サンプル出力4


0
0
0
6
0
8
0
2
0
8
0
2
0
8
0
2

に答える

from collections import deque
import sys; rl = sys.stdin.readline
N, M, x, y, K = map(int, rl().split())
map_ = [list(map(int, rl().split())) for _ in range(N)]
cmds = list(map(int, rl().split()))
dx = [0, 0, 0, -1, 1] # 원점, 동, 서, 북, 남
dy = [0, 1, -1, 0, 0]

dice = {  # 주사위의 각 면에 적힌 숫자
  1:0,
  2:0,
  3:0,
  4:0,
  5:0,
  6:0
}

dice_row = deque([6, 4, 1, 3])  # 동, 서 방향 회전축
dice_col = deque([6, 2, 1, 5])  # 남, 북 방향 회전축

if map_[x][y] != 0:   # 처음 밑면 숫자 체크
  dice[6] = map_[x][y]

for cmd in cmds:
  nx, ny = x + dx[cmd], y + dy[cmd] # 동, 서, 남, 북 방향으로 인덱스 변경

  if 0 <= nx < N and 0 <= ny < M: # 인덱스가 범위 안에 있는지 체크
    x, y = nx, ny

    if cmd == 1 or cmd == 2:  # 동, 서 축 회전
      if cmd == 1:
        dice_row.appendleft(dice_row.pop())
      else:
        dice_row.append(dice_row.popleft())
      dice_col[0] = dice_row[0]
      dice_col[2] = dice_row[2]
    else: # 남, 북 축 회전
      if cmd == 3:
        dice_col.appendleft(dice_col.pop())
      else:
        dice_col.append(dice_col.popleft())
      dice_row[0] = dice_col[0]
      dice_row[2] = dice_col[2]

    now = dice_row[0]

    if map_[x][y] == 0: # 바닥에 쓰여있는 수가 0일 때
      map_[x][y] = dice[now]
    else:
      dice[now] = map_[x][y]
      map_[x][y] = 0

    print(dice[7 - now]) # 윗 면을 출력
サイコロを投げるときに生じる地面の変化に悩んだ.
問題は,東,北順に転がる場合の底面と,北,東順に転がる場合の底面が異なることである.
30分ほど考えて、立方体のx軸の真ん中の線とy軸の真ん中の線を回転させる形のアイデアを思いつきました.
  • インデックス資料構造により左、右回転を実現する.
  • dice row,dice colインデックスの0番目のインデックスは、現在の下部のインデックス
  • である.
  • 棟、西軸回転時にdice rowを回転し、dice colの0,2インデックス値をdice rowの0,2インデックス値
  • に変更
  • 男性は、北軸回転時にdice colを回転する、dice rowの0、2インデックス値をdice colの0、2インデックス値
  • に変更する.
    床の数字とサイコロの数字の相互作用は実現上問題ありません.