본문으로 바로가기

[백준 14891] 톱니바퀴 -JAVA //le_effort//

category 알고리즘 2020. 3. 11. 22:29

 

삼성 SW 역랑 테스트 기출문제.

 

구현+시뮬레이션 문제이다.

 

풀이 방법:

돌리기 전 기존 상태에서 마주 보고 있는 인덱

 

톱니바퀴의 개수 4개와  각각의 톱니바퀴당 8개의 톱니(?)를 가지고 있다.

 

 

그림으로 표현하면 이렇다 

배열은 map[i][j]    

i = i번째 톱니바퀴

j = i번째 톱니바퀴의 톱니들 1~8까지

 

맞닿는 부분이 서로 달라야 하므로 비교를 해줄 때

인덱스 번호 3번과 7번만 비교를 하면 된다.

이때 주의를 해야 하는 점은 돌리기 전 인덱스와 비교를 해줘야 한다.

 

나는 돌리기 전에 돌릴 수 있는 여부를 재귀 함수를 통해 리스트에 받아 놓고

루프당 리스트에 담아있는 돌릴 수 있는 숫자와 방향을 한꺼번에 돌렸다

 

방향이 1일 땐 시계방향,  -1 일땐 반시계 방향이니

기존의 방향에 -1을 곱하면 기존 방향과 반대로 구현된다.

1* -1 = -1

-1 * -1 = 1

 

1
2
3
4
5
6
7
8
9
10
11
public static void get_turn_list(int num, int d) {
        list.add(new Node(num,d));
        if(num-1>=1 && !visited[num-1&&map[num][7]!=map[num-1][3]) {
            visited[num-1]=true;
            get_turn_list(num-1,d*-1);
        }
        if(num+1<=4 && !visited[num+1&&map[num][3!= map[num+1][7]) {
            visited[num+1]=true;
            get_turn_list(num+1,d*-1);
        }
    }
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

int num = 돌릴 톱니바퀴의 번호

int d = 돌릴 톱니바퀴의 방향

visited 배열은 중복되는 번호가 들어가길 방지하기 위해 넣어주었으며

 

조건에 다 맞으면 넣어주는 식으로 했다.

이를 통해 모든 돌릴 수 있는 톱니바퀴를 다 리스트에 넣었으면

 

돌려주면 된다.

 

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
public static void turn(int num, int d) {
        for(int i=1; i<=4; i++) {
            for(int j=1; j<=8; j++) {
                copy_map[i][j]= map[i][j];
            }
        }
        if(d==1) {    // 시계방향
            for(int i=1; i<=8; i++) {
                if(i==1) {
                    map[num][1]=copy_map[num][8];
                }
                else {
                    map[num][i] = copy_map[num][i-1];
                }
            }
        }
        else {
            for(int i=8; i>=1; i--) {
                if(i==8) {
                    map[num][8= copy_map[num][1];
                }
                else {
                    map[num][i] = copy_map[num][i+1];
                }
            }
        }
    }
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

시계방향과 반시계 방향 일 때 시작과 끝 인덱스는 따로 빼줘야 한다.

그 후 합을 구하면 된다. 

 

전체 코드

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
106
import java.io.*;
import java.util.*;
public class Main {
    static int map[][];
    static int copy_map[][];
    static boolean visited[];
    static int k;
    static int sum=0;
    static ArrayList<Node>list = new ArrayList<>();
    static Queue<Node> q = new LinkedList<>();
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        map = new int[5][9];
        copy_map = new int[5][9];
        for(int i=1; i<=4; i++) {    // 톱니바퀴가 4개
            String str = br.readLine();
            for(int j=1; j<=8; j++) {    // 한 톱니바퀴당 8개
                map[i][j] = str.charAt(j-1)-'0';
            }
        }
        k = Integer.parseInt(br.readLine());    // 회전수
        
        for(int i=0; i<k; i++) {
            String[] t = br.readLine().split(" ");
            int num = Integer.parseInt(t[0]);    // 회전시킬 톱니바퀴 번호
            int d = Integer.parseInt(t[1]);        // 돌릴 방향
            q.add(new Node(num,d));
        }
        solve();
    }
    public static void solve() {
        while(!q.isEmpty()) {
            list.clear();
            visited = new boolean[5];
            Node a =q.poll();
            int num = a.num;
            int d = a.d;
            visited[num]=true;
            get_turn_list(num,d);
            for(int i=0; i<list.size(); i++) {
                turn(list.get(i).num,list.get(i).d);
            }
        }
        
        if(map[1][1]==1) {
            sum+=1;
        }
        if(map[2][1]==1) {
            sum+=2;
        }
        if(map[3][1]==1) {
            sum+=4;
        }
        if(map[4][1]==1) {
            sum+=8;
        }
        System.out.println(sum);
    }
    public static void turn(int num, int d) {
        for(int i=1; i<=4; i++) {
            for(int j=1; j<=8; j++) {
                copy_map[i][j]= map[i][j];
            }
        }
        if(d==1) {    // 시계방향
            for(int i=1; i<=8; i++) {
                if(i==1) {
                    map[num][1]=copy_map[num][8];
                }
                else {
                    map[num][i] = copy_map[num][i-1];
                }
            }
        }
        else {
            for(int i=8; i>=1; i--) {
                if(i==8) {
                    map[num][8= copy_map[num][1];
                }
                else {
                    map[num][i] = copy_map[num][i+1];
                }
            }
        }
    }
    public static void get_turn_list(int num, int d) {
        list.add(new Node(num,d));
        if(num-1>=1 && !visited[num-1&&map[num][7]!=map[num-1][3]) {
            visited[num-1]=true;
            get_turn_list(num-1,d*-1);
        }
        if(num+1<=4 && !visited[num+1&&map[num][3!= map[num+1][7]) {
            visited[num+1]=true;
            get_turn_list(num+1,d*-1);
        }
    }
}
class Node{
    int num,d;
    Node(int num,int d){
        this.num=num;
        this.d=d;
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
>cs

 

돌릴 방향을 다 정해두고 한꺼번에 돌리는 건 편리하고 좋은 것 같다.

앞으로도 이런 방식으로 풀 수 있으면 돌릴 방향을 다 받아두고

한꺼번에 돌리는 식으로 하는 게 좋겠다.