문제

강호는 코딩 교육을 하는 스타트업 스타트링크에 지원했다. 오늘은 강호의 면접날이다. 하지만, 늦잠을 잔 강호는 스타트링크가 있는 건물에 늦게 도착하고 말았다.

스타트링크는 총 F층으로 이루어진 고층 건물에 사무실이 있고, 스타트링크가 있는 곳의 위치는 G층이다. 강호가 지금 있는 곳은 S층이고, 이제 엘리베이터를 타고 G층으로 이동하려고 한다.

보통 엘리베이터에는 어떤 층으로 이동할 수 있는 버튼이 있지만, 강호가 탄 엘리베이터는 버튼이 2개밖에 없다. U버튼은 위로 U층을 가는 버튼, D버튼은 아래로 D층을 가는 버튼이다. (만약, U층 위, 또는 D층 아래에 해당하는 층이 없을 때는, 엘리베이터는 움직이지 않는다)

강호가 G층에 도착하려면, 버튼을 적어도 몇 번 눌러야 하는지 구하는 프로그램을 작성하시오. 만약, 엘리베이터를 이용해서 G층에 갈 수 없다면, "use the stairs"를 출력한다.

 

입력

첫째 줄에 F, S, G, U, D가 주어진다. (1 ≤ S, G ≤ F ≤ 1000000, 0 ≤ U, D ≤ 1000000) 건물은 1층부터 시작하고, 가장 높은 층은 F층이다.

 

출력

첫째 줄에 강호가 S층에서 G층으로 가기 위해 눌러야 하는 버튼의 수의 최솟값을 출력한다. 만약, 엘리베이터로 이동할 수 없을 때는 "use the stairs"를 출력한다.

 

예제

 

풀이 방법

S층에서 G층으로 가기 위해 눌러야 하는 최소한의 버튼 수를 구하는 문제였습니다.

 

먼저 현재 위치를 우선순위 큐에 넣어주었습니다. 현재 위치가 도착 층수인 G층 이라면 우선순위 큐에 같이 넣어주었던 누른 버튼의 수를 출력하면서 반복문을 종료하고, 그 외에 경우에 위로 U층만큼, 아래로 D층만큼 이동하면서 만약 한 번도 도착하지 않았던 층수라면 도착했다고 표시해주고 큐에 해당 위치 정보를 넣어주었습니다. 만약 큐에 아무것도 없어 반복문이 종료되었고, 도착하고자 하는 층수에 도착했는지를 확인해주는 flag변수를 통해 flag가 false라면 도착 층수에 도달하지 못한다는 의미이므로 use the stairs를 출력해주었습니다.

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_5014_스타트링크 {
    
    static class info implements Comparable<info>{
        int floor, check;
 
        public info(int floor, int check) {
            super();
            this.floor = floor;
            this.check = check;
        }
 
        @Override
        public int compareTo(info o) {
            return this.check-o.check;
        }
        
    }
    
    static int F,S,G,U,D;
    static int [] map;
    static PriorityQueue<info> queue = new PriorityQueue<>();
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        F = Integer.parseInt(st.nextToken()); //층 총수
        S = Integer.parseInt(st.nextToken()); // 현재 층수
        G = Integer.parseInt(st.nextToken()); // 도착 층수
        U = Integer.parseInt(st.nextToken()); //위로 U만큼
        D = Integer.parseInt(st.nextToken()); //아래로 D만큼
        
        map = new int[F+1];
        
        queue.add(new info(S,0));
        
        int [] dx = {U,-D};
        boolean flag = false;
        while(!queue.isEmpty()) {
            info now = queue.poll();
            
            
            if(now.floor==G) {
                flag=true;
                System.out.println(now.check);
                break;
            }
            
            for(int i=0;i<2;i++) {
                int nx = now.floor+dx[i];
                if(range(nx) && map[nx]==0) {
                    map[nx]=1;
                    queue.add(new info(nx,now.check+1));
                }
            }
        }
        if(!flag) System.out.println("use the stairs");
        
    }
    
    public static boolean range(int x) {
        return x>=1 && x<=F;
    }
 
}
cs

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 10282번 해킹 [JAVA]  (0) 2021.06.17
백준 19942 다이어트 [JAVA]  (0) 2021.06.16
백준 9207번 페그 솔리테어 [JAVA]  (0) 2021.06.15
백준 17143번 낚시왕 [JAVA]  (0) 2021.06.15
백준 16235번 나무 재테크 [JAVA]  (0) 2021.06.11

문제

페그 솔리테어는 구멍이 뚫려있는 이차원 게임판에서 하는 게임이다. 각 구멍에는 핀을 하나 꽂을 수 있다.

핀은 수평, 수직 방향으로 인접한 핀을 뛰어넘어서 그 핀의 다음 칸으로 이동하는 것만 허용된다. 인접한 핀의 다음 칸은 비어있어야 하고 그 인접한 핀은 제거된다.

현재 게임판에 꽂혀있는 핀의 상태가 주어진다. 이때, 핀을 적절히 움직여서 게임판에 남아있는 핀의 개수를 최소로 하려고 한다. 또, 그렇게 남기기 위해 필요한 최소 이동횟수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 테스트 케이스의 개수 1 ≤ N ≤ 100이 주어진다. 각 테스트 케이스는 게임판의 초기 상태이다.

게임판은 모두 같은 모양을 가진다. (예제 참고) '.'는 빈 칸, 'o'는 핀이 꽂혀있는 칸, '#'는 구멍이 없는 칸이다. 핀의 개수는 최대 8이며, 각 테스트 케이스는 빈 줄로 구분되어져 있다.

 

출력

각 테스트 케이스에 대해서, 핀을 움직여서 남길 수 있는 핀의 최소 개수와 그 개수를 만들기 위해 필요한 최소 이동 횟수를 출력한다.

 

예제

풀이 방법

핀을 적절히 움직여서 게임판에 남아있는 핀의 개수를 최소로하는 동시에, 최소로 남기기 위해 필요한 최소 이동 횟수를 구하는 문제였습니다. 

 

게임판의 존재하는 핀의 개수를 카운트해주고, remainPin 변수에 핀의 개수를 넣어주었습니다. 게임판의 해당 위치가 핀이 꽂혀있는 칸이라면 dfs() 메서드를 통해 현재 위치의 다음 위치가 게임판의 범위를 넘지 않으면서 핀이 꽂혀있는 칸이고 그 다다음 칸이 빈칸이라면 해당 위치의 핀을 이동할 수 있으므로, 이동시켜주고 핀의 개수를 하나 줄이고, 움직인 수를 하나 늘린 뒤, 다음 게임판에서 핀이 꽂혀있는 위치를 찾은 뒤 위에 과정을 반복해주었습니다. 과정이 끝난 후, 마지막으로 남아있는 핀의 개수와, 이동 횟수를 출력해주었습니다.

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main_BJ_9207_페그솔리테어 {
    
    static char [][] map;
    static int xx=5,yy=9,remainPin, move;
    
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc=0; tc<T;tc++) {
            map = new char[xx][yy];
            
            int pin=0;
            for(int i=0;i<xx;i++) {
                String str = br.readLine();
                for(int j=0;j<yy;j++) {
                    map[i][j] = str.charAt(j);
                    if(map[i][j]=='o') pin++;
                }
            }
            
            remainPin = pin;
            
            for(int i=0;i<xx;i++) {
                for(int j=0;j<yy;j++) {
                    if(map[i][j]=='o') dfs(i,j,pin,0);
                }
            }
            
            br.readLine();
            
            sb.append(remainPin+" "+move+"\n");
        }
        
        System.out.println(sb.toString());
 
    }
    
    public static void dfs(int x, int y , int remain, int moveCnt) {
        if(remain<=remainPin) {
            remainPin = remain;
            move = moveCnt;
        }
        
        for(int d=0;d<4;d++) {
            int nx = x + dx[d];
            int ny = y + dy[d];
            
            if(range(nx,ny) && map[nx][ny]=='o') {
                int nnx = nx +dx[d];
                int nny = ny +dy[d];
                
                if(range(nnx,nny) && map[nnx][nny]=='.') {
                    map[x][y]=map[nx][ny]='.';
                    map[nnx][nny]='o';
                    
                    for(int i=0;i<xx;i++) {
                        for(int j=0;j<yy;j++) {
                            if(map[i][j]=='o') dfs(i,j,remain-1,moveCnt+1);
                        }
                    }
                    
                    map[x][y]=map[nx][ny]='o';
                    map[nnx][nny]='.';
                }
            }
            
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<xx && y>=0 && y<yy;
    }
 
}
cs

문제

낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다. 칸에는 상어가 최대 한 마리 들어있을 수 있다. 상어는 크기와 속도를 가지고 있다.

낚시왕은 처음에 1번 열의 한 칸 왼쪽에 있다. 다음은 1초 동안 일어나는 일이며, 아래 적힌 순서대로 일어난다. 낚시왕은 가장 오른쪽 열의 오른쪽 칸에 이동하면 이동을 멈춘다.

  1. 낚시왕이 오른쪽으로 한 칸 이동한다.
  2. 낚시왕이 있는 열에 있는 상어 중에서 땅과 제일 가까운 상어를 잡는다. 상어를 잡으면 격자판에서 잡은 상어가 사라진다.
  3. 상어가 이동한다.

상어는 입력으로 주어진 속도로 이동하고, 속도의 단위는 칸/초이다. 상어가 이동하려고 하는 칸이 격자판의 경계를 넘는 경우에는 방향을 반대로 바꿔서 속력을 유지한채로 이동한다.

왼쪽 그림의 상태에서 1초가 지나면 오른쪽 상태가 된다. 상어가 보고 있는 방향이 속도의 방향, 왼쪽 아래에 적힌 정수는 속력이다. 왼쪽 위에 상어를 구분하기 위해 문자를 적었다.

상어가 이동을 마친 후에 한 칸에 상어가 두 마리 이상 있을 수 있다. 이때는 크기가 가장 큰 상어가 나머지 상어를 모두 잡아먹는다.

낚시왕이 상어 낚시를 하는 격자판의 상태가 주어졌을 때, 낚시왕이 잡은 상어 크기의 합을 구해보자.

 

입력

첫째 줄에 격자판의 크기 R, C와 상어의 수 M이 주어진다. (2 ≤ R, C ≤ 100, 0 ≤ M ≤ R×C)

둘째 줄부터 M개의 줄에 상어의 정보가 주어진다. 상어의 정보는 다섯 정수 r, c, s, d, z (1 ≤ r ≤ R, 1 ≤ c ≤ C, 0 ≤ s ≤ 1000, 1 ≤ d ≤ 4, 1 ≤ z ≤ 10000) 로 이루어져 있다. (r, c)는 상어의 위치, s는 속력, d는 이동 방향, z는 크기이다. d가 1인 경우는 위, 2인 경우는 아래, 3인 경우는 오른쪽, 4인 경우는 왼쪽을 의미한다.

두 상어가 같은 크기를 갖는 경우는 없고, 하나의 칸에 둘 이상의 상어가 있는 경우는 없다.

 

출력

낚시왕이 잡은 상어 크기의 합을 출력한다.

 

예제

 

풀이 방법

낚시왕이 왼쪽에서 오른쪽으로 한칸씩 이동하면서 잡은 상어의 크기의 합을 구하는 문제였습니다.

 

이 낚시왕 문제는 한달전에 시도했으나 틀린 부분을 찾지 못하여 이번에 다시 풀게 되었습니다.

먼저, 이 문제에서

1. 낚시왕 오른쪽으로 한 칸 이동

2. 낚시왕이 있는 해당 열에서 땅과 가장 가까운 상어 잡기, 격자판에서 해당  상어 제거

3. 상어 이동

이라는 세 가지의 과정이 있습니다.

 

첫 번째로 for문을 이용해 낚시왕의 위치를 한 칸씩 이동해 준 뒤, sharkCatch() 메서드를 통해 해당 열에서 가장 가까운 위치에 있는 상어를 잡았습니다. 이동하면서 잡은 상어의 크기의 합을 담아둘 ans변수에 잡은 상어의 크기 값을 넣어주고 격자판에서 해당 상어를 제거해주었습니다. 마지막으로 상어들이 이동하는 sharkMove() 메서드에서 변경된 상어들의 위치를 일시적으로 담아두기 위해 격자판과 동일한 크기의 copy배열을 사용해 움직인 상어들의 위치를 찍어주었습니다. 해당 스피드만큼 상어가 이동한 후, 이동한 상어 위치에 다른 상어가 없다면 배열에 해당 상어 정보를 넣어주고, 움직인 상어가 기존의 있던 상어보다 크기가 큰 경우 기존에 있던 상어는 사라지고 움직인 상어의 정보를 배열에 넣어주었습니다. 반대로 이동한 상어가 기존의 있던 상어보다 크기가 작은 경우 그 상어는 해당 위치에 존재할 수 없으므로 상어 정보를 remove 큐에 넣어주었습니다. 모든 상어들의 이동이 끝난 후, 상어들의 정보가 담겨있는 list과 비교해서 제거될 상어들의 정보를 제거해 준 뒤, 원래 격자판인 map 배열에 상어들이 이동하고 난 뒤의 위치를 복사해 넣어주었습니다.

이 과정을 낚시왕이 왼쪽에서 오른쪽으로 이동할 때까지 반복하여 잡은 상어의 크기를 출력해주었습니다.

 

 

코드

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
 
public class Main_BJ_17143_낚시왕 {
    
    static class info{
        int x,y,speed,dir,size;
 
        public info(int x, int y, int speed, int dir, int size) {
            super();
            this.x = x;
            this.y = y;
            this.speed = speed;
            this.dir = dir;
            this.size = size;
        }
    }
    
    static int R,C,M, ans=0;
    static int [][] map, copy;
    static int [] dx = {0,-1,1,0,0};
    static int [] dy = {0,0,0,1,-1};
    
    static ArrayList<info> shark = new ArrayList<>();
    static Queue<Integer> remove = new LinkedList<>();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        R = Integer.parseInt(st.nextToken()); //X
        C = Integer.parseInt(st.nextToken()); //Y
        M = Integer.parseInt(st.nextToken()); //상어 수
        
        map = new int[R+1][C+1];
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            int z = Integer.parseInt(st.nextToken());
            
            shark.add(new info(r,c,s,d,z));
            map[r][c] = z;
        }
        
        
        for(int i=1;i<=C;i++) {
            //상어잡기
            sharkCatch(i);
            //상어움직이기
            sharkMove();    
        }
        System.out.println(ans);
 
    }
    
    public static void print() {
        for(int i=1;i<R+1;i++) {
            for(int j=1;j<C+1;j++) {
                System.out.print(map[i][j]+" ");
            }
            System.out.println();
        }
    }
    
    public static void sharkCatch(int y) {
        Loop:
        for(int x=1;x<R+1;x++) {
            if(map[x][y]!=0) {
                for(int i=0;i<shark.size();i++) {
                    if(shark.get(i).x==&& shark.get(i).y==y) {
                        ans+=shark.get(i).size;
                        map[x][y]=0;
                        shark.remove(i);
                        break Loop;
                    }
                }
            }
        }
    }
    
    public static void sharkMove() {
        
        copy = new int[R+1][C+1];
        
        for (int i=0;i<shark.size();i++) {
            info temp = shark.get(i);
            
            map[temp.x][temp.y] = 0;
            
            for (int j = 0; j < temp.speed ; j++) {// d==1 상, d==2 하, d==3 우, d==4 좌
 
                if (temp.dir == 1 && temp.x == 1) temp.dir = 2;
                else if (temp.dir == 2 && temp.x == R)temp.dir = 1;
                else if (temp.dir == 3 && temp.y == C)temp.dir = 4;
                else if (temp.dir == 4 && temp.y == 1)temp.dir = 3;
 
                temp.x += dx[temp.dir];
                temp.y += dy[temp.dir];
            } //상어 이동 끝
            
            if(copy[temp.x][temp.y]==0) {
                copy[temp.x][temp.y] = temp.size;
            }else if(copy[temp.x][temp.y]<temp.size) { //움직인 상어가 기존에 있던 상어보다 큰 경우
                remove.add(copy[temp.x][temp.y]);
                copy[temp.x][temp.y] = temp.size;
            }else {
                remove.add(temp.size);
            }
        }
        
        while(!remove.isEmpty()) {
            int temp = remove.poll();
            for(int i=0;i<shark.size();i++) {
                if(temp==shark.get(i).size) {
                    shark.remove(i); break;
                }
            }
        }
        map = copy;
    }
 
}
cs

문제

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터 떨어진 칸의 개수, c는 가장 왼쪽으로부터 떨어진 칸의 개수이다. r과 c는 1부터 시작한다.

상도는 전자통신공학과 출신답게 땅의 양분을 조사하는 로봇 S2D2를 만들었다. S2D2는 1×1 크기의 칸에 들어있는 양분을 조사해 상도에게 전송하고, 모든 칸에 대해서 조사를 한다. 가장 처음에 양분은 모든 칸에 5만큼 들어있다.

매일 매일 넓은 땅을 보면서 뿌듯한 하루를 보내고 있던 어느 날 이런 생각이 들었다.

나무 재테크를 하자!

나무 재테크란 작은 묘목을 구매해 어느정도 키운 후 팔아서 수익을 얻는 재테크이다. 상도는 나무 재테크로 더 큰 돈을 벌기 위해 M개의 나무를 구매해 땅에 심었다. 같은 1×1 크기의 칸에 여러 개의 나무가 심어져 있을 수도 있다.

이 나무는 사계절을 보내며, 아래와 같은 과정을 반복한다.

봄에는 나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가한다. 각각의 나무는 나무가 있는 1×1 크기의 칸에 있는 양분만 먹을 수 있다. 하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다. 만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다.

여름에는 봄에 죽은 나무가 양분으로 변하게 된다. 각각의 죽은 나무마다 나이를 2로 나눈 값이 나무가 있던 칸에 양분으로 추가된다. 소수점 아래는 버린다.

가을에는 나무가 번식한다. 번식하는 나무는 나이가 5의 배수이어야 하며, 인접한 8개의 칸에 나이가 1인 나무가 생긴다. 어떤 칸 (r, c)와 인접한 칸은 (r-1, c-1), (r-1, c), (r-1, c+1), (r, c-1), (r, c+1), (r+1, c-1), (r+1, c), (r+1, c+1) 이다. 상도의 땅을 벗어나는 칸에는 나무가 생기지 않는다.

겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가한다. 각 칸에 추가되는 양분의 양은 A[r][c]이고, 입력으로 주어진다.

K년이 지난 후 상도의 땅에 살아있는 나무의 개수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 N, M, K가 주어진다.

둘째 줄부터 N개의 줄에 A배열의 값이 주어진다. r번째 줄의 c번째 값은 A[r][c]이다.

다음 M개의 줄에는 상도가 심은 나무의 정보를 나타내는 세 정수 x, y, z가 주어진다. 처음 두 개의 정수는 나무의 위치 (x, y)를 의미하고, 마지막 정수는 그 나무의 나이를 의미한다.

 

출력

첫째 줄에 K년이 지난 후 살아남은 나무의 수를 출력한다.

 

예제

코드

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_16235_나무재테크2 {
    
    static class tree {
        int x, y, age;
 
        public tree(int x, int y, int age) {
            super();
            this.x = x;
            this.y = y;
            this.age = age;
        }
    }
    
    static int N,M,K;
    static int [][] land ,add;
    static int [] dx = {-1,-1,-1,0,1,1,1,0};
    static int [] dy = {-1,0,1,1,1,0,-1,-1};
    
    static Queue<tree> live, die;
    static PriorityQueue<tree> pq = new PriorityQueue<>(new Comparator<tree>() {
        @Override
        public int compare(tree o1, tree o2) {
            return o1.age-o2.age;
        }
    });
    
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        N = Integer.parseInt(st.nextToken()); // 땅 크기
        M = Integer.parseInt(st.nextToken()); // 나무 개수
        K = Integer.parseInt(st.nextToken()); // ~년
        
        land = new int[N][N];
        add = new int[N][N];
        
        live = new LinkedList<>();
        die = new LinkedList<>();
        
        for(int i=0;i<N;i++) Arrays.fill(land[i], 5);
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<N;j++) {
                add[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            
            int x = Integer.parseInt(st.nextToken())-1;
            int y = Integer.parseInt(st.nextToken())-1;
            int age = Integer.parseInt(st.nextToken());
            pq.add(new tree(x,y,age));
        }
        
        
        for(int i=0;i<K;i++) {
            spring();
            summer();
            fall();
            winter();
        }
        System.out.println(pq.size());
 
    }
    
    public static void spring() {
        int size = pq.size();
        
        for(int i=0;i<size;i++) {
            tree info = pq.poll();
            if(land[info.x][info.y]>=info.age) {
                land[info.x][info.y]-=info.age;
                live.add(new tree(info.x,info.y,info.age+1));
            }else die.add(info);
        }
    }
    
    public static void summer() {
        int size = die.size();
        
        for(int i=0;i<size;i++) {
            tree info = die.poll();
            land[info.x][info.y]+=info.age/2;
        }
    }
    
    public static void fall() {
        int size = live.size();
        
        for(int i=0;i<size;i++) {
            tree info = live.poll();
            if(info.age%5==0) {
                for(int d=0;d<8;d++) {
                    int nx = info.x+dx[d];
                    int ny = info.y+dy[d];
                    if(range(nx,ny)) pq.add(new tree(nx,ny,1));
                }
            }
            pq.add(info);
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<N;
    }
    
    public static void winter() {
        for(int i=0;i<N;i++) {
            for(int j=0;j<N;j++) {
                land[i][j]+=add[i][j];
            }
        }
    }
}
cs

 

풀이 방법

K 년이 지난 후 땅에 살아있는 나무의 개수를 구하는 문제였습니다.

봄 : 자신의 나이만큼 양분 먹고 나이 +1 (땅에 여러 개의 나무가 있다면 나이가 어린 나무부터 양분 먹기 / 양분이 부족해 나이만큼 양분을 먹을 수 없다면 즉시 죽는다)

여름 : 봄에 죽은 나무의 나이 / 2 만큼 양분+

가을 : 나무의 나이가 5의 배수인 나무는 인접한 8개의 칸에 나이가 1인 나무들 번식

겨울 : 땅에 양분 추가

 

봄에는 나이가 어른 나무부터 양분을 먹어야 하기 때문에 나무의 정보를 나이를 기준으로 정렬하여 우선순위 큐에 넣어주었습니다. 나무가 양분을 먹을 수 있다면 live큐에 나이+1를 해준 나무의 정보를 넣어주고, 만약 양분이 부족하다면 나무는 즉시 죽으므로 die큐에 나무의 정보를 넣어주었습니다. 여름에는 죽은 나무의 나이/2 만큼 양분을 더해주고, 가을에는 나무의 나이가 5의 배수라면 인접한 8개의 칸에 나이가 1인 나무들을 번식할 수 있으므로 pq에 넣어주었습니다. pq에 넣어준 이유는 사계절이 지나 다시 봄이온다면 나이가 적은 나무부터 양분을 먹어야하기 때문에 나이순으로 나무 정보를 우선순위 큐인 pq에 넣어주었습니다. 겨울에는 입력된 양분을 땅에 추가해주었습니다. 이 과정을 K 년 반복 후, 살아있는 나무의 개수를 출력해주었습니다.

 

문제

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.

만약에 이동하는 도중에 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 K개 까지 부수고 이동하여도 된다.

한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.

맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.

 

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

 

출력

첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.

 

예제

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_2206_벽부수고이동하기2 {
 
    static class info {
        int x, y, dis, wall;
 
        public info(int x, int y, int dis, int wall) {
            this.x = x;
            this.y = y;
            this.dis = dis;
            this.wall = wall;
        }
    }
 
    static int N, M,K, ans = Integer.MAX_VALUE;
    static int[][] map;
    static boolean[][][] visited;
    static int[] dx = { -1010 };
    static int[] dy = { 010-1 };
 
    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());
        K = Integer.parseInt(st.nextToken());
 
        map = new int[N][M];
        visited = new boolean[N][M][K+1];
 
        for (int i = 0; i < N; i++) {
            String str = br.readLine();
            for (int j = 0; j <M; j++) {
                map[i][j] = str.charAt(j) - 48;
            }
        }
        move();
    }
 
    public static void move() {
        Queue<info> queue = new LinkedList<>();
 
        queue.offer(new info(0010));
 
        visited[0][0][0= true;
 
        while (!queue.isEmpty()) {
            info temp = queue.poll();
 
            if (temp.x == N-1 && temp.y == M-1) {
                System.out.println(temp.dis);
                return ;
            }
 
            for (int i = 0; i < 4; i++) {
                int nx = temp.x + dx[i];
                int ny = temp.y + dy[i];
                int breakWall = temp.wall;
                int count = temp.dis;
 
                if (range(nx, ny)) {
                    if (map[nx][ny] == 1) { //벽일때
                        if(breakWall <&& !visited[nx][ny][breakWall+1]) {
                            visited[nx][ny][breakWall+1= true;
                            queue.offer(new info(nx, ny, count+1, breakWall+1));
                        }
                    } 
                    else {
                        if (!visited[nx][ny][breakWall]) {
                            visited[nx][ny][breakWall] = true;
                            queue.offer(new info(nx, ny, count + 1 ,breakWall));
                        }
                    }
                }
            }
        }
        System.out.println(-1);
    }
 
    public static boolean range(int x, int y) {
        return x >= 0 && y >= 0 && x < N && y < M;
    }
 
}
cs

 

풀이 방법

왼쪽 상단에서 오른쪽 하단의 위치까지 이동하는데 만약 이동하는 도중 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 K개 까지 부수고 이동하는데 최단 경로를 구하는 문제였습니다.

 

벽을 몇 개 부수고 이동했는지 확인하기 위해 3차원 배열을 이용했습니다. 먼저, 처음 위치인 (0, 0) 좌표 값과 이동한 거리, 그리고 벽을 부순 개수의 정보를 큐에 넣어주었습니다. 상하좌우로 이동하면서 만약 다음 이동할 위치가 벽이고, 현재까지 부슨 벽의 개수가 K보다 적고 방문하지 않은 곳이라면 해당 위치에 방문했다고 표시해주고 큐에 해당 정보를 넣어주었습니다. 그 외에 다음 이동할 위치가 길이라면 이동할 수 있으므로 방문했다고 표시해주고 큐에 해당 정보를 넣어주었습니다. 이 과정을 반복하다가 만약 오른쪽 아래에 도착했다면 도착하는데 걸린 거리를 출력해주었습니다. 만약 오른쪽 하단의 위치까지 이동할 수 없다면 -1을 출력해주었습니다.

 

문제

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.

로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다.

로봇 청소기는 다음과 같이 작동한다.

  1. 현재 위치를 청소한다.
  2. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
    1. 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
    2. 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
    3. 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
    4. 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.

로봇 청소기는 이미 청소되어있는 칸을 또 청소하지 않으며, 벽을 통과할 수 없다.

 

입력

첫째 줄에 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 50)

둘째 줄에 로봇 청소기가 있는 칸의 좌표 (r, c)와 바라보는 방향 d가 주어진다. d가 0인 경우에는 북쪽을, 1인 경우에는 동쪽을, 2인 경우에는 남쪽을, 3인 경우에는 서쪽을 바라보고 있는 것이다.

셋째 줄부터 N개의 줄에 장소의 상태가 북쪽부터 남쪽 순서대로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 빈 칸은 0, 벽은 1로 주어진다. 지도의 첫 행, 마지막 행, 첫 열, 마지막 열에 있는 모든 칸은 벽이다.

로봇 청소기가 있는 칸의 상태는 항상 빈 칸이다.

 

출력

로봇 청소기가 청소하는 칸의 개수를 출력한다.

 

예제

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_14503_로봇청소기 {
    
    static int N,M,r,c,d, ans;
    static int [][] map;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
 
        N = Integer.parseInt(st.nextToken());
        M= Integer.parseInt(st.nextToken());
        
        map = new int [N][M];
        
        st = new StringTokenizer(br.readLine());
        
        r = Integer.parseInt(st.nextToken());
        c = Integer.parseInt(st.nextToken());
        d = Integer.parseInt(st.nextToken());
        
        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());
            }
        }
        
        isClean(r,c,d);
        
        System.out.println(ans);
 
    }
    
    public static void isClean(int x, int y, int dir) {
        
        if(map[x][y]==0) {
            map[x][y]=2;
            ans++;
        }
        
        boolean flag = false;
        int direction = dir;
        
        for(int i=0;i<4;i++) {
            //북서남동으로 회전
            int nd = (dir+3)%4;
            int nx = x+dx[nd];
            int ny = y+dy[nd];
            if(range(nx,ny)) {
                if(map[nx][ny]==0) { // 왼쪽방향에 청소할 공간 존재
                    isClean(nx,ny,nd);
                    flag = true;
                    break;    
                } 
            }
            dir = nd;
        }
        
        //여기에 왔다면 c/d만 가능
        if(!flag) {
            // 처음 위치에서 뒤로 한칸
            int nd = (direction+2) %4;
            int nx = x+dx[nd];
            int ny = y+dy[nd];
            if(range(nx,ny) && map[nx][ny]!=1) {
                isClean(nx,ny,direction); //바라보는 방향 유지하면서 후진
            }
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<N && y>=0 && y<M;
    }
 
}
cs

 

풀이 방법

로봇 청소기가 청소하는 영역의 개수를 구하는 문제였습니다.

 

만약 해당 위치가 벽이 아니라면 청소할 수 있는 곳이므로 영역의 개수를 +해주었습니다. 해당 위치에서 왼쪽 방향에 청소할 영역이 존재한다면 그 방향으로 회전 및 한 칸 전진 후 1번부터 다시 진행하도록 해주었습니다. 반대로 왼쪽방향에 청소할 영역이 없다면 북서남동 방향으로 회전하면서 청소할 영역을 찾았습니다. isClean() 메소드에서 69번 줄에 왔다면 작동 조건 2-a, 2-b를 만족하지 않는다는 의미므로 2-c, 2-d 고려해볼 수 있습니다. 만약 해당 위치에서 뒤로 한칸 이동할 수 있는 경우에는 후진 후 다시 2번부터 진행하도록 해주고, 뒤로 한칸 이동할 수 없는 경우에는 작동을 멈춰 지금까지 청소한 영역의 개수를 출력해주었습니다.

문제

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다.

우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이때, 주어진 수의 순서를 바꾸면 안 된다.

예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.

  • 1+2+3-4×5÷6
  • 1÷2+3+4-5×6
  • 1+2÷3×4-5+6
  • 1÷2×3-4+5+6

식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉, 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.

  • 1+2+3-4×5÷6 = 1
  • 1÷2+3+4-5×6 = 12
  • 1+2÷3×4-5+6 = 5
  • 1÷2×3-4+5+6 = 7

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다. 

 

출력

첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다. 연산자를 어떻게 끼워넣어도 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.

 

예제

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_14888_연산자끼워넣기 {
    
    static int N, max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
    static int [] number, sign, cal;
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        
        N = Integer.parseInt(br.readLine());
        
        number = new int[N];
        sign = new int[4];
        cal = new int[N];
        
        st = new StringTokenizer(br.readLine());
        for(int i=0;i<N;i++) {
            number[i] = Integer.parseInt(st.nextToken());
        }
        
        st = new StringTokenizer(br.readLine());
        for(int i=0;i<4;i++) {
            sign[i] = Integer.parseInt(st.nextToken());
        }
        
        backtracking(1);
        System.out.println(max);
        System.out.println(min);
 
    }
    
    public static void backtracking(int cnt) {
        if(cnt ==N) {
            
            int result = number[0];
            
            for(int i=1;i<N;i++) {
                if(cal[i]==0) {
                    result = result+number[i];
                }else if(cal[i]==1) {
                    result = result-number[i];
                }else if(cal[i]==2) {
                    result = result*number[i];
                }else if(cal[i]==3) {
                    result = result/number[i];
                }
            }
            
            max = Math.max(result, max);
            min = Math.min(result, min);
            
            return;
        }
        
        for(int i=0;i<4;i++) {
            if(sign[i]>0) {
                cal[cnt] = i;
                sign[i]--;
                backtracking(cnt+1);
                sign[i]++;
            }
        }
        
    }
}
cs

 

풀이 방법

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과의 최대/최소를 구하는 문제였습니다.

 

N개의 수를 담을 number배열과 연산자의 개수를 담을 sign배열, 그리고 계산할 연산자를 담을 cal배열을 사용했습니다.

backtracking() 메서드에서 sign배열의 길이만큼 for문을 통해 만약 연산자가 존재한다면 cal배열에 연산자 값을 넣어주고 해당 sign값을 -1 해주었습니다. N-1개의 연산자를 cal배열에 다 넣어줬을 경우, number배열과 cal배열에 들어있는 연산자를 이용해 결괏값을 계산해주었습니다. 

 

문제

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다.

N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 N이 주어진다. (1 ≤ N < 15)

 

출력

첫째 줄에 퀸 N개를 서로 공격할 수 없게 놓는 경우의 수를 출력한다.

 

예제

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main_BJ_9663_NQueen {
    
    static int N, ans;
    static int [] map;
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        N = Integer.parseInt(br.readLine());
        
        map = new int[N];
        
        backtracking(0);
        System.out.println(ans);
    }
    
    public static void backtracking(int cnt) {
        if(cnt ==N) {
            ans++;
            return;
        }
        
        for(int i=0;i<N;i++) {
            map[cnt] =i;
            if(isCheck(cnt)) {
                backtracking(cnt+1);
            }
        }
    }
    
    public static boolean isCheck(int x) {
        for(int i=0;i<x;i++) {
            if(map[i]==map[x]) return false;
            else if(Math.abs(map[i]-map[x])==Math.abs(i-x)) return false;
        }
        return true;
    }
 
}
cs

 

문제

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.

게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다.

뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.

  • 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
  • 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
  • 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.

사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하라.

 

입력

첫째 줄에 보드의 크기 N이 주어진다. (2 ≤ N ≤ 100) 다음 줄에 사과의 개수 K가 주어진다. (0 ≤ K ≤ 100)

다음 K개의 줄에는 사과의 위치가 주어지는데, 첫 번째 정수는 행, 두 번째 정수는 열 위치를 의미한다. 사과의 위치는 모두 다르며, 맨 위 맨 좌측 (1행 1열) 에는 사과가 없다.

다음 줄에는 뱀의 방향 변환 횟수 L 이 주어진다. (1 ≤ L ≤ 100)

다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데,  정수 X와 문자 C로 이루어져 있으며. 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다. X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순으로 주어진다.

 

출력

첫째 줄에 게임이 몇 초에 끝나는지 출력한다.

 

예제

코드

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
107
108
109
110
111
112
113
114
115
116
117
118
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_3190_뱀 {
    
    static class info{
        int time;
        String direction;
        
        int x, y;
        
        public info(int x, int y) {
            super();
            this.x = x;
            this.y = y;
        }
 
        public info(int time, String direction) {
            super();
            this.time = time;
            this.direction = direction;
        }
    }
    
    static int N,K,L, time;
    static int [][] map;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    
    static Queue<info> queue = new LinkedList<>();
    static Deque<info> snake = new LinkedList<>();
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        N = Integer.parseInt(br.readLine());
        K = Integer.parseInt(br.readLine());
        
        map = new int[N][N];
        
        for(int i=0;i<K;i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken())-1;
            int y = Integer.parseInt(st.nextToken())-1;
            
            map[x][y] = 1;
        }
        
        L = Integer.parseInt(br.readLine());
        
        for(int i=0;i<L;i++) {
            st = new StringTokenizer(br.readLine());
            int time = Integer.parseInt(st.nextToken());
            String direction = st.nextToken();
            
            queue.add(new info(time,direction));
        }
        
        move();
        System.out.println(time+1);
 
    }
    
    public static void move() {
        
        int dir = 1;
        
        snake.add(new info(0,0));
        map[0][0]=2;
        
        while(true) {
            info snail = snake.peekFirst();
            
            int nx = snail.x+dx[dir];
            int ny = snail.y+dy[dir];
            if(!range(nx,ny)) break;
            else {
                if(map[nx][ny]==1) { //다음 이동할 곳이 사과라면
                    snake.addFirst(new info(nx,ny));
                    map[nx][ny] =2;
                }else if(map[nx][ny]==2) {
                    break;
                }else { //아무것도 없다면
                    info del = snake.pollLast();
                    map[del.x][del.y] = 0;
                    snake.addFirst(new info(nx,ny));
                    map[nx][ny] =2;
                }
                time++;
                if(!queue.isEmpty()) {
                    
                    info temp = queue.peek();
                    
                    if(time==temp.time) {
                        if(temp.direction.equals("D")) {
                            if(dir==3) dir=0;
                            else dir++;
                        }else if(temp.direction.equals("L")) {
                            if(dir==0) dir=3;
                            else dir--;
                        }
                        queue.poll();
                    }
                }
            }
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<N;
    }
}
cs

 

풀이 방법

사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하는 문제였습니다.

 

사과의 위치를 map 배열에 1로 표시해주고, 뱀의 이동경로는 큐에 넣어주었습니다. 뱀은 (0, 0) 위치에서 시작하므로 snake덱에 뱀의 정보를 넣어주고 map 배열에 2로 뱀의 위치를 표시해주었습니다. 뱀이 다음 위치로 이동하는데 세 가지의 경우가 존재할 수 있습니다. 첫 번째로 뱀이 이동할 다음 위치가 사과인 경우에 꼬리는 움직이지 않고 덱 맨 처음에 다음 위치 정보를 넣어주었습니다. 그리고 다음 위치가 사과가 없는 길이라면 몸은 길어지지 않고 한 칸 앞으로 이동한 것이 되므로 꼬리에 해당하는 정보를 지우고 다음 위치를 덱 맨 앞에 넣어주었습니다. 마지막으로 다음 위치가 자신의 몸일 경우에는 부딪히므로 게임이 끝나도록 반복문을 종료해주었습니다. 뱀이 이동할 때마다 1초씩 증가시켰으며, n초가 지난 후에는 왼쪽, 오른쪽으로 이동경로를 변경할 수 있도록해주었습니다. 

문제

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수 있을까?

 

입력

입력의 첫째 줄에는 테스트 케이스의 개수가 주어진다.

각 테스트 케이스는 세 줄로 이루어져 있다. 첫째 줄에는 체스판의 한 변의 길이 l(4 ≤ l ≤ 300)이 주어진다. 체스판의 크기는 l × l이다. 체스판의 각 칸은 두 수의 쌍 {0, ..., l-1} × {0, ..., l-1}로 나타낼 수 있다. 둘째 줄과 셋째 줄에는 나이트가 현재 있는 칸, 나이트가 이동하려고 하는 칸이 주어진다.

 

 

출력

각 테스트 케이스마다 나이트가 최소 몇 번만에 이동할 수 있는지 출력한다.

 

 

예제

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_7562_나이트의이동 {
    
    static class info {
        int x, y, cnt;
 
        public info(int x, int y, int cnt) {
            this.x = x;
            this.y = y;
            this.cnt = cnt;
        }
    }
    
    static int l, goalX, goalY;
    static int [][] map;
    
    static int [] dx = {-1,-2,-2,-1,1,2,2,1};
    static int [] dy = {-2,-1,1,2,2,1,-1,-2};
    
    static PriorityQueue<info> pq = new PriorityQueue<>(new Comparator<info>() {
 
        @Override
        public int compare(info o1, info o2) {
            return o1.cnt-o2.cnt;
        }
    });
 
    static StringBuilder sb = new StringBuilder();
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc = 0; tc<T;tc++) {
            l = Integer.parseInt(br.readLine());
            
            map = new int[l][l];
            
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
            
            map[x][y]=1;
            pq.add(new info(x,y,0));
                
            st = new StringTokenizer(br.readLine());
            goalX = Integer.parseInt(st.nextToken());
            goalY = Integer.parseInt(st.nextToken());
            
            map[goalX][goalY]=2;
            
            bfs();
            pq.clear();
        }
        System.out.println(sb.toString());
    }
    
    public static void bfs() {
        
        while(!pq.isEmpty()) {
            info temp = pq.poll();
            
            if(temp.x==goalX && temp.y==goalY) {
                sb.append(temp.cnt+"\n");
                return;
            }
            
            for(int i=0;i<8;i++) {
                int nx = temp.x+dx[i];
                int ny = temp.y+dy[i];
                
                if(range(nx,ny)) {
                    if(map[nx][ny]==0) {
                        map[nx][ny]=1;
                        pq.add(new info(nx,ny,temp.cnt+1));
                    }else if(map[nx][ny]==2) {
                        sb.append(temp.cnt+1+"\n");
                        return;
                    }
                }
            }
        }
        
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<l;
    }
 
}
cs

 

'문제 > 백준' 카테고리의 다른 글

백준 9663번 N-Queen [JAVA]  (0) 2021.06.11
백준 3190번 뱀 [JAVA]  (0) 2021.06.11
백준 4485번 녹색 옷 입은 애가 젤다지? [JAVA]  (0) 2021.04.21
백준 15683번 감시 [JAVA]  (0) 2021.04.21
백준 13905번 세부 [JAVA]  (0) 2021.04.21

+ Recent posts