여니의 취준 준비/코딩테스트 (Python)

[14499] 주사위 굴리기 in python

여니's 2022. 1. 9. 10:28

문제출처

https://www.acmicpc.net/problem/14499

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지

www.acmicpc.net


 

 


in Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
   static int n,m,x,y,k;
   static int[][] map;
   static int[] dice;
   static int[] dxs= {0,0,0,-1,1};// 동, 서, 북, 남
   static int[] dys= {0,1,-1,0,0};
   static int up,front,right;
   
   public static void main(String[] args) throws IOException {
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(br.readLine());
      n=Integer.parseInt(st.nextToken());
      m=Integer.parseInt(st.nextToken());
      x=Integer.parseInt(st.nextToken());
      y=Integer.parseInt(st.nextToken());
      k=Integer.parseInt(st.nextToken());
      dice= new int[]{0,0,0,0,0,0,0}; 
      up=1; front=2; right=3;
      
      // 1. 격자 맵 입력받기
      map=new int[n][m];
      for (int i = 0; i < n; i++) {
         st=new StringTokenizer(br.readLine());
         for (int j = 0; j < m; j++) {
            map[i][j]=Integer.parseInt(st.nextToken());
         }
      }
      // 2. 이동하는 명령 입력받기
      st=new StringTokenizer(br.readLine());
      for (int i = 0; i < k; i++) {
         int inputNum= Integer.parseInt(st.nextToken());
         // 3. 주사위 이동
         diceMove(inputNum);
      }
   }
 
   public static void diceMove(int inputNum) {
      int nx=x+dxs[inputNum];
      int ny=y+dys[inputNum];
      // 1.1 주사위 이동 가능
      if(canMove(nx,ny)) {         
         // 2.1. 주사위 회전 
         // 동쪽으로 이동
         if (inputNum==1) { 
             int temp=up;
             up=7-right;
             right=temp;
         }
         // 서쪽으로 이동
         else if(inputNum==2) {
             int temp=up;
             up=right;
             right=7-temp;
         }
         // 북쪽으로 이동
         else if(inputNum==3) {
             int temp=up;
             up=front;
             front=7-temp;
         }
         // 남쪽으로 이동
         else if(inputNum==4){
             int temp=up;
             up=7-front;
             front=temp;
         }
         
         // 3.1 이동할 칸에 0이 쓰여있는경우 -> 이동할 칸에 주사위 바닥에 쓰여있는 숫자 복사
         if(map[nx][ny]==0) {
             map[nx][ny]=dice[7-up];
         }
         // 3.2 이동할 칸에 0이 쓰여있지 않은 경우 -> 이동할 칸에 쓰여있는 숫자를 주사위 바닥에 복사, 칸에 쓰여있는 숫자는 0으로 변경
         else {
             dice[7-up]=map[nx][ny];
             map[nx][ny]=0;
         }
         
         // 2.4 주사위 윗면 출력
         System.out.println(dice[up]);
         x=nx; y=ny;
      }
      
      // 1.2 이동불가 -> 해당 명령은 무시하고 다음 명령으로 넘어간다. 
         
      
   }
 
   public static boolean canMove(int x, int y) {
      return x>=0 && x<&& y>=0 && y<m;
   }
 
}
 
/*
 * 초기 주사위 : 모든 면에 0이 적혀있다.
 * 이동한 칸에 쓰여있는 숫자가 0 -> 주사위 바닥에 쓰여있는 숫자가 칸에 복사된다.
 * 이동한 칸에 쓰여있는 숫자가 0이 아니면 -> 칸에 쓰여있는 숫자가 주사위 바닥에 복사, 칸에 쓰여있는 숫자는 0
 * 이동할때마다 주사위 상단에 쓰여있는 숫자 출력하기
 * 격자밖으로 이동하려고 하면 해당 명령 무시, 출력도 하면 안된다. 
 * */
cs

 

주사위 회전 시

주사위의 윗면, 앞면, 오른쪽면을

각각 1,2,3 으로 숫자를 지정해준다.

 

그러면 필연적으로

아랫면, 뒷면, 왼쪽면은

각각 6, 5, 4가 되어야한다.

 

왜냐하면 일반적인 주사위는

마주보는 양면의 합이 7이 되어야하기 때문이다.

 

이를 이용하면

쉽게 문제를 풀 수 있다. 

 

 

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
   static int n,m,x,y,k;
   static int[][] map;
   static int[] dice;
   static int[] dxs= {0,0,0,-1,1};// 동, 서, 북, 남
   static int[] dys= {0,1,-1,0,0};
   static int up,front,right;
   
   public static void main(String[] args) throws IOException {
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(br.readLine());
      n=Integer.parseInt(st.nextToken());
      m=Integer.parseInt(st.nextToken());
      x=Integer.parseInt(st.nextToken());
      y=Integer.parseInt(st.nextToken());
      k=Integer.parseInt(st.nextToken());
      dice= new int[]{0,0,0,0,0,0,0}; 
      up=1; front=2; right=3;
      
      // 1. 격자 맵 입력받기
      map=new int[n][m];
      for (int i = 0; i < n; i++) {
         st=new StringTokenizer(br.readLine());
         for (int j = 0; j < m; j++) {
            map[i][j]=Integer.parseInt(st.nextToken());
         }
      }
      // 2. 이동하는 명령 입력받기
      st=new StringTokenizer(br.readLine());
      for (int i = 0; i < k; i++) {
         int inputNum= Integer.parseInt(st.nextToken());
         // 3. 주사위 이동
         diceMove(inputNum);
      }
   }
   public static void diceMove(int inputNum) {
      int nx=x+dxs[inputNum];
      int ny=y+dys[inputNum];
      // 1.1 주사위 이동 가능
      if(canMove(nx,ny)) {         
         // 2.1. 주사위 회전 
    	 // 동쪽으로 이동
         if (inputNum==1) { 
        	 int temp=up;
        	 up=7-right;
        	 right=temp;
         }
         // 서쪽으로 이동
         else if(inputNum==2) {
        	 int temp=up;
        	 up=right;
        	 right=7-temp;
         }
         // 북쪽으로 이동
         else if(inputNum==3) {
        	 int temp=up;
        	 up=front;
        	 front=7-temp;
         }
         // 남쪽으로 이동
         else if(inputNum==4){
        	 int temp=up;
        	 up=7-front;
        	 front=temp;
         }
         
         // 3.1 이동할 칸에 0이 쓰여있는경우 -> 이동할 칸에 주사위 바닥에 쓰여있는 숫자 복사
         if(map[nx][ny]==0) {
        	 map[nx][ny]=dice[7-up];
         }
         // 3.2 이동할 칸에 0이 쓰여있지 않은 경우 -> 이동할 칸에 쓰여있는 숫자를 주사위 바닥에 복사, 칸에 쓰여있는 숫자는 0으로 변경
         else {
        	 dice[7-up]=map[nx][ny];
        	 map[nx][ny]=0;
         }
         
         // 2.4 주사위 윗면 출력
         System.out.println(dice[up]);
         x=nx; y=ny;
      }
      
      // 1.2 이동불가 -> 해당 명령은 무시하고 다음 명령으로 넘어간다. 
         
      
   }
   public static boolean canMove(int x, int y) {
      return x>=0 && x<n && y>=0 && y<m;
   }
}
/*
 * 초기 주사위 : 모든 면에 0이 적혀있다.
 * 이동한 칸에 쓰여있는 숫자가 0 -> 주사위 바닥에 쓰여있는 숫자가 칸에 복사된다.
 * 이동한 칸에 쓰여있는 숫자가 0이 아니면 -> 칸에 쓰여있는 숫자가 주사위 바닥에 복사, 칸에 쓰여있는 숫자는 0
 * 이동할때마다 주사위 상단에 쓰여있는 숫자 출력하기
 * 격자밖으로 이동하려고 하면 해당 명령 무시, 출력도 하면 안된다. 
 * */

in Python

 

주사위 굴리기...

배열에 모든 경우의 수를 다 적었던...

(미련한 뻘짓이었다!)

 

 

주사위 모양

2

4 1 3

5

6

 

 

1이 윗면

6이 아랫면

 


1. 동쪽

: 동쪽 이동시에는 4,1,3,6번째만 계속 움직이고

2와 5는 망부석

 

1번 자리에는 4번이 오고

4번 자리에는 6번이 오고

6번 자리에는 3번이 오고

3번 자리에는 1번이 오게 된다.

 

하지만 dice[1],dice[2]...dice[6]의 값만 바뀌는거지

상대적인 위치는 그대로!

dice[1]은 윗면, dice[6]은 아랫면

 


2. 서쪽

: 서쪽 이동시에도 동쪽과 마찬가지로 4,1,3,6번째만 계속 움직인다.

 

1번 자리에는 3번이 오고

3번 자리에는 6번이 오고

6번 자리에는 4번이 오고

4번 자리에는 1번이 온다.

 


3. 북쪽

: 북쪽 이동시엔 2,1,5,6번째만 계속 움직인다.

4,3번째는 망부석

 

2번 자리에는 1번이

1번 자리에는 5번이

5번 자리에는 6번이

6번 자리에는 2번이 온다.

 

 


4. 남쪽

: 남쪽 이동시엔 2,1,5,6번째만 계속 움직인다.

 

1번 자리에는 2번이

5번 자리에는 1번이

6번 자리에는 5번이

2번 자리에는 6번이 온다.

n, m, x, y, k = map(int, input().split())
# 동,서,북,남 = 1,2,3,4
dx = [0,0, 0, -1, 1]
dy = [0,1, -1, 0, 0]
array = [list(map(int, input().split())) for _ in range(n)]
moves = list(map(int, input().split()))
dice = [0, 0, 0, 0, 0, 0, 0]  # 1,2,3,4,5,6(1이 윗면, 6이 바닥면)
top = 0


def moveDice(dir):
    if dir == 1:  # 동쪽
        dice[1], dice[4], dice[3], dice[6] = dice[4], dice[6], dice[1], dice[3]
    elif dir == 2:  # 서쪽
        dice[1], dice[3], dice[6], dice[4] = dice[3], dice[6], dice[4], dice[1]
    elif dir == 3:  # 북쪽
        dice[1], dice[5], dice[6], dice[2] = dice[5], dice[6], dice[2], dice[1]
    else:  # 남쪽
        dice[1], dice[2], dice[6], dice[5] = dice[2], dice[6], dice[5], dice[1]

def check(nx,ny):
    if array[nx][ny] == 0:
        array[nx][ny] = dice[6]
    else:
        dice[6] = array[nx][ny]
        array[nx][ny]=0
'''
동쪽이동시
4 1 3 6 -> 6 4 1 3

서쪽이동시
4 1 3 6 -> 1 3 6 4

북쪽이동시
2 1 5 6 -> 1 5 6 2 

남쪽이동시
2 1 5 6 -> 6 2 1 5 

'''

for move in moves:
    nx = x + dx[move]
    ny = y + dy[move]
    if 0 <= nx < n and 0 <= ny < m:
        x=nx
        y=ny
        if move == 1:  # 동쪽
            moveDice(move)
            check(nx,ny)
            print(dice[1])
        elif move == 2:  # 서쪽
            moveDice(move)
            check(nx, ny)
            print(dice[1])
        elif move == 3:  # 북쪽
            moveDice(move)
            check(nx, ny)
            print(dice[1])
        else:  # 남쪽
            moveDice(move)
            check(nx,ny)
            print(dice[1])