문제

젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다!

젤다의 전설 시리즈의 주인공, 링크는 지금 도둑루피만 가득한 N x N 크기의 동굴의 제일 왼쪽 위에 있다. [0][0]번 칸이기도 하다. 왜 이런 곳에 들어왔냐고 묻는다면 밖에서 사람들이 자꾸 "젤다의 전설에 나오는 녹색 애가 젤다지?"라고 물어봤기 때문이다. 링크가 녹색 옷을 입은 주인공이고 젤다는 그냥 잡혀있는 공주인데, 게임 타이틀에 젤다가 나와있다고 자꾸 사람들이 이렇게 착각하니까 정신병에 걸릴 위기에 놓인 것이다.

하여튼 젤다...아니 링크는 이 동굴의 반대편 출구, 제일 오른쪽 아래 칸인 [N-1][N-1]까지 이동해야 한다. 동굴의 각 칸마다 도둑루피가 있는데, 이 칸을 지나면 해당 도둑루피의 크기만큼 소지금을 잃게 된다. 링크는 잃는 금액을 최소로 하여 동굴 건너편까지 이동해야 하며, 한 번에 상하좌우 인접한 곳으로 1칸씩 이동할 수 있다.

링크가 잃을 수밖에 없는 최소 금액은 얼마일까?

 

 

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다.

각 테스트 케이스의 첫째 줄에는 동굴의 크기를 나타내는 정수 N이 주어진다. (2 ≤ N ≤ 125) N = 0인 입력이 주어지면 전체 입력이 종료된다.

이어서 N개의 줄에 걸쳐 동굴의 각 칸에 있는 도둑루피의 크기가 공백으로 구분되어 차례대로 주어진다. 도둑루피의 크기가 k면 이 칸을 지나면 k루피를 잃는다는 뜻이다. 여기서 주어지는 모든 정수는 0 이상 9 이하인 한 자리 수다.

 

 

출력

각 테스트 케이스마다 한 줄에 걸쳐 정답을 형식에 맞춰서 출력한다. 형식은 예제 출력을 참고하시오.

 

 

예제

 

코드

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
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_4485_녹색옷입은애가젤다지 {
    static int [][] map;
    static boolean [][] visited;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    static int N, ans;
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        int count=0;
        while(true) {
            count++;
            N = Integer.parseInt(br.readLine());
            
            if(N==0break;
            
            map = new int[N][N];
            
            for(int i=0;i<N;i++) {
                st = new StringTokenizer(br.readLine()," ");
                for(int j=0;j<N;j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                }
            }
            ans=0;
            bfs();
            sb.append("Problem "+count+": "+ans+"\n");
        }
        System.out.println(sb.toString());
 
    }
    
    public static void bfs() {
        PriorityQueue<int []> pq = new PriorityQueue<>(new Comparator<int []>() {
 
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[2]-o2[2];
            }
        });
        
        visited = new boolean[N][N];
        
        pq.add(new int[] {0,0, map[0][0]});
        visited[0][0= true;
        
        while(!pq.isEmpty()) {
            int [] info = pq.poll();
            
            if(info[0]==N-1 && info[1]==N-1) {
                ans = info[2];
                return;
            }
            
            for(int i=0;i<4;i++) {
                int nx = info[0]+dx[i];
                int ny = info[1]+dy[i];
                
                if(range(nx,ny) && !visited[nx][ny]) {
                    visited[nx][ny] = true;
                    pq.add(new int[] {nx,ny, info[2]+map[nx][ny]});
                }
            }
            
        }
    }
    
    public static boolean range(int x , int y) {
        return x>=0 && y>=0 && x<&& y<N;
    }
}
cs

 

풀이 방법

링크가 제일 오른쪽 아래 칸까지 이동하는데 잃는 최소 금액을 구하는 문제였습니다.

 

저는 bfs로 문제를 풀었습니다. 

 

우선순위 큐에 현재 좌표값과 현재좌표값의 금액을 정보를 같이 넣어주었습니다. 그리고 난 뒤, 상/우/하/좌로 이동하면서 다음 이동할 위치가 범위를 넘지 않으면서 방문하지 않은 곳이라면 방문 체크해주고 우선순위 큐에 다음 위치정보와 함께 그다음 좌표값의 금액 정보와 함께 이전 금액 정보를 더해서 넣어주었습니다. 이동하면서 오른쪽 아래 칸에 도착했다면 반복문을 종료하고 해당 금액 정보를 ans 변수에 담아 출력해주었습니다.

 

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

백준 3190번 뱀 [JAVA]  (0) 2021.06.11
백준 7562번 나이트의 이동 [JAVA]  (0) 2021.06.11
백준 15683번 감시 [JAVA]  (0) 2021.04.21
백준 13905번 세부 [JAVA]  (0) 2021.04.21
백준 2239번 스토쿠 [JAVA]  (0) 2021.04.21

문제

 

 

입력

첫째 줄에 사무실의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 8)

둘째 줄부터 N개의 줄에는 사무실 각 칸의 정보가 주어진다. 0은 빈 칸, 6은 벽, 1~5는 CCTV를 나타내고, 문제에서 설명한 CCTV의 종류이다. 

CCTV의 최대 개수는 8개를 넘지 않는다.

 

 

출력

첫째 줄에 사각 지대의 최소 크기를 출력한다.

 

 

예제

 

코드

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
134
135
136
137
138
139
140
141
142
143
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main_BJ_15683_감시 {
    
    static class CCTV{
        int x, y, type;
 
        public CCTV(int x, int y, int type) {
            this.x = x;
            this.y = y;
            this.type = type;
        }
        
    }
    
    static int N,M, min = Integer.MAX_VALUE;
    static int [][] map;
    static ArrayList<CCTV> list = new ArrayList<>();
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    static int [][] type1 = {{0},{1},{2},{3}};
    static int [][] type2 = {{0,2},{1,3}};
    static int [][] type3 = {{0,1},{1,2},{2,3},{3,0}};
    static int [][] type4 = {{0,1,2},{1,2,3},{2,3,0},{3,0,1}};
    static int [][] type5 = {{0,1,2,3}};
 
    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];
        
        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());
                
                if(map[i][j]!=0 && map[i][j]!=6) list.add(new CCTV(i,j, map[i][j]));
            }
        }
        
        dfs(0,map);
        System.out.println(min);
    }
    
    public static void dfs(int cnt, int[][] init) {
        
        if(cnt == list.size()) {
            
            int count=0;
            for(int i=0;i<N;i++) {
                for(int j=0;j<M;j++) {
                    if(init[i][j]==0) count++;
                }
            }
            
            min = Math.min(min, count);
            return;
            
        }
        
        CCTV cctv = list.get(cnt);
        
        int [][] visited = new int[N][M];
        
        if(cctv.type==1) {
            for(int i=0;i<4;i++) {
                copy(visited, init); // map배열 복사
                see(cctv.x, cctv.y, visited, i, type1);
                dfs(cnt+1, visited);
            }
        }
        else if(cctv.type==2) {
            for(int i=0;i<2;i++) {
                copy(visited, init);
                see(cctv.x, cctv.y, visited,i,type2);
                dfs(cnt+1, visited);
            }
        }
        else if(cctv.type==3) {
            for(int i=0;i<4;i++) {
                copy(visited, init);
                see(cctv.x, cctv.y, visited,i, type3);
                dfs(cnt+1, visited);
            }
        }
        else if(cctv.type==4) {
            for(int i=0;i<4;i++) {
                copy(visited, init);
                see(cctv.x, cctv.y, visited,i, type4);
                dfs(cnt+1, visited);
            }
        }else {
            copy(visited, init);
            see(cctv.x, cctv.y, visited,0, type5);
            dfs(cnt+1, visited);
        }
        
        
    }
    
    public static void see(int x, int y, int[][] visited, int index, int[][] type) {
        
        visited[x][y] = 1;
        for(int i=0;i<type[index].length;i++) {
            
            int nx =x+dx[type[index][i]];
            int ny =y+dy[type[index][i]];
            
            while(range(nx,ny) && map[nx][ny]!=6) {
                visited[nx][ny] =1;
                nx += dx[type[index][i]];
                ny += dy[type[index][i]];
            }
        }
        
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<M;
    }
    
    
    public static void copy(int [][] target , int [][] init) {
        
        for(int i=0;i<N;i++) {
            for(int j=0;j<M;j++) {
                target[i][j] = init[i][j];
            }
        }
        
    }
 
}
cs

 

 

비트마스크(BitMask)란?

  • 비트 필드에서 비트 연산에 사용되는 데이터로 정수의 이진수 표현을 자료 구조로 쓰는 기법을 말한다.
  • 이진수는 0과 1로 표현
  • 비트연산을 통해 삽입, 삭제, 조회 등이 간단해지며 더 빠른 연산이 가능해진다.

 

연산자

 

 

 

문제

빼빼로 데이를 맞아 혜빈이와 숭이는 세부에 있는 섬에 놀러 갔다. 섬은 바다 위에 떠다니는 집과 집들을 연결하는 오크나무로 되어있는 다리로 이뤄져 있다. 숭이는 혜빈이에게 깜짝 이벤트를 해주기 위해 섬 관리자에게 혜빈이를 이벤트장소에 머물게 해달라고 하였다. 이벤트 당일 날 숭이는 금으로 된 빼빼로들을 들고 이벤트 장소로 이동하려 했다. 하지만 아뿔싸! 각 다리마다 다리 위를 지날 수 있는 무게 제한이 존재했다. 비싼 금빼빼로를 가면서 버리기 아깝던 숭이는 자신이 머물던 집에서 자신이 혜빈이에게 갈 수 있는 최대한의 금빼빼로만을 들고 가려고 한다. 따라서 숭이는 인공위성조차 해킹할 수 있는 당신에게 혜빈이에게 들고 갈 수 있는 최대한의 금빼빼로 개수를 알려달라고 부탁했다. 당신은 인공위성을 해킹하여 집들의 번호와 다리의 무게제한을 알아내었다. 이 정보를 가지고 빨리 숭이를 도와주자.

(금빼빼로 하나의 무게는 1이고, 숭이의 몸무게는 고려하지 않는다.)

 

 

입력

첫 번째 줄에는 섬에 존재하는 집의 수 N(2≤N≤100,000)와 다리의 수 M(1≤M≤300,000)이 주어진다. 두 번째 줄에는 숭이의 출발 위치(s)와 혜빈이의 위치(e)가 주어진다. (1≤s, e≤N, s≠e). 다음 M개의 줄에는 다리의 정보가 주어진다. 각 줄은 “집의 번호 h1(1≤h1≤N), 집의 번호 h2(1≤h2≤N), 다리의 무게제한 k(1≤k≤1,000,000)” 형식으로 주어진다. (h1집과 h2집은 무게제한이 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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main_BJ_13905_세부 {
    static class Edge implements Comparable<Edge> {
        int start, end, weight;
 
        public Edge(int start, int end, int weight) {
            this.start = start;
            this.end = end;
            this.weight = weight;
        }
 
        @Override
        public int compareTo(Edge o) {
            return (this.weight - o.weight) * -1;
        }
 
    }
 
    static int N, M, A, B, C, s, e;
    static int[] parents;
    static Edge[] edgeList;
 
    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());
        
        parents = new int[N+1];
        edgeList = new Edge[M];
        
        st= new StringTokenizer(br.readLine()," ");
        s = Integer.parseInt(st.nextToken());
        e = Integer.parseInt(st.nextToken());
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine()," ");
            A = Integer.parseInt(st.nextToken());
            B = Integer.parseInt(st.nextToken());
            C = Integer.parseInt(st.nextToken());
            
            edgeList[i] = new Edge(A,B,C);
        }
        
        make();
        
        Arrays.sort(edgeList);
        
        
        int res=0;
        for(int i=0;i<edgeList.length;i++) {
            union(edgeList[i].start, edgeList[i].end);    
            res = edgeList[i].weight;
            if(find(s)==find(e)) break;
            
        }
        if(parents[s]!=parents[e]) res=0;
        System.out.println(res);
    }
 
    public static void print() {
        for (int i = 0; i <= N; i++)
            System.out.print(parents[i] + " ");
        System.out.println();
    }
 
    public static void make() {
        for (int i = 0; i <= N; i++)
            parents[i] = i;
    }
 
    public static void union(int a, int b) {
        int aRoot = find(a);
        int bRoot = find(b);
 
        if (aRoot <= bRoot) {
            parents[bRoot] = aRoot;
        }else {
            parents[aRoot] = bRoot;
        }
    }
 
    public static int find(int x) {
        if (parents[x] == x)
            return x;
        return parents[x] = find(parents[x]);
    }
 
}
cs

 

 

문제

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다음을 보자.

위 그림은 참 잘도 스도쿠 퍼즐을 푼 경우이다. 각 행에 1부터 9까지의 숫자가 중복 없이 나오고, 각 열에 1부터 9까지의 숫자가 중복 없이 나오고, 각 3×3짜리 사각형(9개이며, 위에서 색깔로 표시되었다)에 1부터 9까지의 숫자가 중복 없이 나오기 때문이다.

하다 만 스도쿠 퍼즐이 주어졌을 때, 마저 끝내는 프로그램을 작성하시오.

 

 

입력

9개의 줄에 9개의 숫자로 보드가 입력된다. 아직 숫자가 채워지지 않은 칸에는 0이 주어진다.

 

 

출력

9개의 줄에 9개의 숫자로 답을 출력한다. 답이 여러 개 있다면 그 중 사전식으로 앞서는 것을 출력한다. 즉, 81자리의 수가 제일 작은 경우를 출력한다.

 

 

출력

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main_BJ_2239_스토쿠 {
    static int N=9;
    static int [][] puzzle;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        puzzle = new int [N][N];
        
        for(int i=0;i<N;i++) {
            String str = br.readLine();
            for(int j=0;j<N;j++) {
                puzzle[i][j]=str.charAt(j)-48;
            }
        }
        
        input(0,0);
        
    }
    
    public static void input(int x, int y) {
        int nx = x, ny = y+1;
        if(ny==9) {
            nx = x+1;
            ny=0;
        }
        
        
        if(x==9) { //탐색 끝
            for(int i=0;i<N;i++) {
                for(int j=0;j<N;j++) {
                    System.out.print(puzzle[i][j]);
                }
                System.out.println();
            }
            System.exit(0);
        }
        
        
        if(puzzle[x][y]!=0) {
            input(nx,ny);
        }
        else {
            
            for(int i=1;i<=9;i++) {
                
                if(col(y,i) || row(x,i) || (rectangle(x, y, i))) continue;
                
                puzzle[x][y] = i;
                
                input(nx,ny);
                
                puzzle[x][y]=0;
                
            }
        }
    }
    
    
    public static boolean col(int y , int value) { //세로검사
        
        for(int i=0;i<N;i++) {
            if(puzzle[i][y]==value) return true;
        }
        return false;
        
    }
    
    public static boolean row(int x, int value) { //가로검사
        
        for(int i=0;i<N;i++) {
            if(puzzle[x][i]==value) return true;
        }
        return false;
        
    }
    
    public static boolean rectangle(int x, int y, int value) { // 3x3 배열검사
        
        int X = (x/3)*3;
        int Y = (y/3)*3;
        
        for(int i=0;i<3;i++) {
            for(int j=0;j<3;j++) {
                if(puzzle[X+i][Y+j]==value) return true;
            }
        }
        return false;
        
    }
 
}
cs

 

풀이방법

스토쿠를 완성시키기 위해 빈 칸을 채우는 문제였습니다.

 

저는 (0,0)부터 스토쿠 오른쪽 아래인 (8,8)까지 차례대로 진행하였습니다.

해당 위치가 0일경우에는 숫자 1~9를 넣어보면서 가로/세로/3*3 검사를 통해 해당 위치에 들어갈 수 있는 숫자를 넣어주었습니다.

x좌표가 9일 경우 즉 모든 스토쿠의 빈칸을 채웠을 경우, 해당 스토쿠를 출력해주었습니다.

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

백준 15683번 감시 [JAVA]  (0) 2021.04.21
백준 13905번 세부 [JAVA]  (0) 2021.04.21
백준 1238번 파티 [JAVA]  (0) 2021.04.21
백준 16954번 움직이는 미로 탈출 [JAVA]  (0) 2021.04.21
백준 11501번 주식 [JAVA]  (0) 2021.04.13

문제

N개의 숫자로 구분된 각각의 마을에 한 명의 학생이 살고 있다.

어느 날 이 N명의 학생이 X (1 ≤ X ≤ N)번 마을에 모여서 파티를 벌이기로 했다. 이 마을 사이에는 총 M개의 단방향 도로들이 있고 i번째 길을 지나는데 Ti(1 ≤ Ti ≤ 100)의 시간을 소비한다.

각각의 학생들은 파티에 참석하기 위해 걸어가서 다시 그들의 마을로 돌아와야 한다. 하지만 이 학생들은 워낙 게을러서 최단 시간에 오고 가기를 원한다.

이 도로들은 단방향이기 때문에 아마 그들이 오고 가는 길이 다를지도 모른다. N명의 학생들 중 오고 가는데 가장 많은 시간을 소비하는 학생은 누구일지 구하여라.

 

 

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어온다. 시작점과 끝점이 같은 도로는 없으며, 시작점과 한 도시 A에서 다른 도시 B로 가는 도로의 개수는 최대 1개이다.

모든 학생들은 집에서 X에 갈수 있고, X에서 집으로 돌아올 수 있는 데이터만 입력으로 주어진다.

 

 

출력

첫 번째 줄에 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
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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_1238_파티 {
    static class Node implements Comparable<Node> {
        int end, w;
 
        public Node(int end, int w) {
            this.end = end;
            this.w = w;
        }
 
        @Override
        public int compareTo(Node o) {
            return this.w - o.w;
        }
    }
    
    static int [] distance, reverse;
    static boolean visited[];
    static ArrayList<ArrayList<Node>> go, back;
    static int N,M,X;
 
    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());
        X = Integer.parseInt(st.nextToken());
        
        
        go = new ArrayList<>();
        back = new ArrayList<>();
        
        distance = new int[N+1];
        reverse = new int[N+1];
        
        for(int i=0;i<=N;i++) {
            go.add(new ArrayList<>());
            back.add(new ArrayList<>());
        }
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine()," ");
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int weight = Integer.parseInt(st.nextToken());
            
            go.get(start).add(new Node(end,weight));
            back.get(end).add(new Node(start,weight));
        }
        
        int [] gogo = dijkstra(go);
        int [] backback = dijkstra(back);
        
        int max = 0;
        for(int i=1; i<=N; i++) max = Math.max(max, gogo[i] + backback[i]);
        System.out.println(max);    
    }
    
    public static int[] dijkstra(ArrayList<ArrayList<Node>> list) {
        boolean [] visited = new boolean[N+1];
        int [] dis = new int[N+1];
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(X,0));
        
        
        Arrays.fill(dis, Integer.MAX_VALUE);
        dis[X] = 0;
        
        
        while(!pq.isEmpty()) {
            Node idx = pq.poll();
            
            if(visited[idx.end]) continue;
            
            visited[idx.end] = true;
            
            for(Node node : list.get(idx.end)) {
                
                if(!visited[node.end] && dis[node.end]>dis[idx.end] + node.w) {
                    dis[node.end] = dis[idx.end] +node.w;
                    pq.add(new Node(node.end, dis[node.end]));
                }
                
            }
        }
        return dis;
        
    }
 
}
cs

 

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

백준 13905번 세부 [JAVA]  (0) 2021.04.21
백준 2239번 스토쿠 [JAVA]  (0) 2021.04.21
백준 16954번 움직이는 미로 탈출 [JAVA]  (0) 2021.04.21
백준 11501번 주식 [JAVA]  (0) 2021.04.13
백준 13904번 과제 [JAVA]  (0) 2021.04.12

문제

욱제는 학교 숙제로 크기가 8×8인 체스판에서 탈출하는 게임을 만들었다. 체스판의 모든 칸은 빈 칸 또는 벽 중 하나이다. 욱제의 캐릭터는 가장 왼쪽 아랫 칸에 있고, 이 캐릭터는 가장 오른쪽 윗 칸으로 이동해야 한다.

이 게임의 특징은 벽이 움직인다는 점이다. 1초마다 모든 벽이 아래에 있는 행으로 한 칸씩 내려가고, 가장 아래에 있어서 아래에 행이 없다면 벽이 사라지게 된다. 욱제의 캐릭터는 1초에 인접한 한 칸 또는 대각선 방향으로 인접한 한 칸으로 이동하거나, 현재 위치에 서 있을 수 있다. 이동할 때는 빈 칸으로만 이동할 수 있다.

1초 동안 욱제의 캐릭터가 먼저 이동하고, 그 다음 벽이 이동한다. 벽이 캐릭터가 있는 칸으로 이동하면 더 이상 캐릭터는 이동할 수 없다.

욱제의 캐릭터가 가장 오른쪽 윗 칸으로 이동할 수 있는지 없는지 구해보자.

 

 

입력

8개 줄에 걸쳐서 체스판의 상태가 주어진다. '.'은 빈 칸, '#'는 벽이다. 가장 왼쪽 아랫칸은 항상 벽이 아니다.

 

 

출력

욱제의 캐릭터가 가장 오른쪽 윗 칸에 도착할 수 있으면 1, 없으면 0을 출력한다.

 

 

예제


코드

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;
 
public class Main_BJ_16954_움직이는미로탈출 {
    
    static class info{
        int x, y;
 
        public info(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
    static int N=8;
    static int startX = 7, startY = 0, endX=0, endY = 7;
    static Queue<info> person = new LinkedList<>();
    static char [][] map;
    static boolean [][] visited;
    static int [] dx = {0,-1,-1,0,1,1,1,0,-1};
    static int [] dy = {0,0,1,1,1,0,-1,-1,-1};
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        map = new char[N][N];
        
        for(int i=0;i<N;i++) {
            String str = br.readLine();
            for(int j=0;j<N;j++) {
                map[i][j] = str.charAt(j);
            }
        }
        
        if(bfs()) System.out.println(1);
        else System.out.println(0);
    }
    
    public static boolean bfs() {
        person.add(new info(startX, startY));
        
        while(!person.isEmpty()) {
            visited = new boolean[N][N];
            int size = person.size();
            
            for(int j=0;j<size;j++) {
                
                info in = person.poll();
                
                if(map[in.x][in.y]=='#'continue;
                
                for(int i=0;i<9;i++) {
                    
                    int nx = in.x+dx[i];
                    int ny = in.y+dy[i];
                    
                    if(range(nx,ny)) {
                        if(nx==endX && ny==endY) {
                            return true;
                        }
 
                        if(map[nx][ny]!='#' && !visited[nx][ny]) {
                            person.offer(new info(nx,ny));
                            visited[nx][ny] = true;
                        }    
                    }
                }
            }
            move();
        }
        
        return false;
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<N;
    }
    
    public static void move() {
        
        for (int i = N-1; i >= 0; i--) { 
            for (int j = 0; j < N; j++) { 
                if(i==0) map[i][j] = '.'
                else map[i][j] = map[i-1][j]; 
                } 
        }
    }
}
cs

 

 

-

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

백준 2239번 스토쿠 [JAVA]  (0) 2021.04.21
백준 1238번 파티 [JAVA]  (0) 2021.04.21
백준 11501번 주식 [JAVA]  (0) 2021.04.13
백준 13904번 과제 [JAVA]  (0) 2021.04.12
백준 3055번 탈출 [JAVA]  (0) 2021.04.12

문제

홍준이는 요즘 주식에 빠져있다. 그는 미래를 내다보는 눈이 뛰어나, 날 별로 주가를 예상하고 언제나 그게 맞아떨어진다. 매일 그는 아래 세 가지 중 한 행동을 한다.

  1. 주식 하나를 산다.
  2. 원하는 만큼 가지고 있는 주식을 판다.
  3. 아무것도 안한다.

홍준이는 미래를 예상하는 뛰어난 안목을 가졌지만, 어떻게 해야 자신이 최대 이익을 얻을 수 있는지 모른다. 따라서 당신에게 날 별로 주식의 가격을 알려주었을 때, 최대 이익이 얼마나 되는지 계산을 해달라고 부탁했다.

예를 들어 날 수가 3일이고 날 별로 주가가 10, 7, 6일 때, 주가가 계속 감소하므로 최대 이익은 0이 된다. 그러나 만약 날 별로 주가가 3, 5, 9일 때는 처음 두 날에 주식을 하나씩 사고, 마지막날 다 팔아 버리면 이익이 10이 된다.

 

 

입력

입력의 첫 줄에는 테스트케이스 수를 나타내는 자연수 T가 주어진다. 각 테스트케이스 별로 첫 줄에는 날의 수를 나타내는 자연수 N(2 ≤ N ≤ 1,000,000)이 주어지고, 둘째 줄에는 날 별 주가를 나타내는 N개의 자연수들이 공백으로 구분되어 순서대로 주어진다. 날 별 주가는 10,000이하다.

 

 

출력

각 테스트케이스 별로 최대 이익을 나타내는 정수 하나를 출력한다. 답은 부호있는 64bit 정수형으로 표현 가능하다.

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main_BJ_11399_ATM {
    
    
    static class money implements Comparable<money>{
        int line;
        int time;
 
        public money(int line,int time) {
            super();
            this.line = line;
            this.time = time;
        }
 
        @Override
        public int compareTo(money o) {
            int diff = this.time-o.time;
            return diff!=0?diff:this.line-o.line;
        }
        
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        int N = Integer.parseInt(br.readLine());
        
        money[] m = new money[N];
        
        st =new StringTokenizer(br.readLine()," ");
        for(int i=0;i<N;i++) {
            m[i]=new money(i,Integer.parseInt(st.nextToken()));
        }
        order(m);
 
    }
    
    public static void order(money[] m) {
        Arrays.sort(m);
        
        int total=m[0].time;
        int result=m[0].time;
    
        for(int i=1, size = m.length; i<size;i++ ) {
            result=result+m[i].time;
            total+=result;
        }
        System.out.println(total);
    }
 
}
cs

 

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

백준 1238번 파티 [JAVA]  (0) 2021.04.21
백준 16954번 움직이는 미로 탈출 [JAVA]  (0) 2021.04.21
백준 13904번 과제 [JAVA]  (0) 2021.04.12
백준 3055번 탈출 [JAVA]  (0) 2021.04.12
백준 14923번 미로 탈출 [JAVA]  (0) 2021.04.12

문제

웅찬이는 과제가 많다. 하루에 한 과제를 끝낼 수 있는데, 과제마다 마감일이 있으므로 모든 과제를 끝내지 못할 수도 있다. 과제마다 끝냈을 때 얻을 수 있는 점수가 있는데, 마감일이 지난 과제는 점수를 받을 수 없다.

웅찬이는 가장 점수를 많이 받을 수 있도록 과제를 수행하고 싶다. 웅찬이를 도와 얻을 수 있는 점수의 최댓값을 구하시오.

 

 

입력

첫 줄에 정수 N (1 ≤ N ≤ 1,000)이 주어진다.

다음 줄부터 N개의 줄에는 각각 두 정수 d (1 ≤ d ≤ 1,000)와 w (1 ≤ w ≤ 100)가 주어진다. d는 과제 마감일까지 남은 일수를 의미하며, w는 과제의 점수를 의미한다.

 

 

출력

얻을 수 있는 점수의 최댓값을 출력한다.

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
 
public class Main_BJ_13904_과제 {
    static class info implements Comparable<info>{
        int d, w;
 
        public info(int d, int w) {
            this.d = d;
            this.w = w;
        }
    
        @Override
        public int compareTo(info o) {
            return (this.w-o.w) * -1;
        }
        
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        ArrayList<info> list = new ArrayList<>();
        
        int N = Integer.parseInt(br.readLine());
        int [] homework = new int[1001];
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine()," ");
            int d = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            list.add(new info(d,w));
        }
        
        Collections.sort(list);
        
        for(int i=0;i<list.size();i++) {
            int d = list.get(i).d;
            int w = list.get(i).w;
            
            if(homework[d]==0) homework[d]= w;
            else {
                while(homework[d]!=0) d--;
                if(d!=0) homework[d] = w;
            }
        }
        int sum=0;
        for(int i=1;i<homework.length;i++) sum+=homework[i];
        
        System.out.println(sum);
        
    }
 
}
cs

 

풀이 방법

과제 점수의 최댓값을 구하는 문제였습니다. 먼저 하루에 한 과제를 끝낼 수 있고, 마감일이 지난 과제는 점수를 받을 수 없으므로 과제 점수를 오름차순으로 정렬해주었습니다. 그러고 난 뒤, 과제점수를 기준으로 만약 마감일인 인덱스가 0인 경우에는 과제를 해결할 수 있으므로 배열에 넣고, 인덱스가 0이 아닌 경우에는 그 날 해야 하는 과제가 있으므로 마감일 변수인 d를 --해줌으로써 과제를 마감일 전에 할 수 있도록 해주었습니다. 마지막으로 sum변수에 해당하는 과제 점수를 더해 출력해주었습니다.

문제

사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제일 친한 친구인 비버의 굴로 가능한 빨리 도망가 홍수를 피하려고 한다.

티떱숲의 지도는 R행 C열로 이루어져 있다. 비어있는 곳은 '.'로 표시되어 있고, 물이 차있는 지역은 '*', 돌은 'X'로 표시되어 있다. 비버의 굴은 'D'로, 고슴도치의 위치는 'S'로 나타내어져 있다.

매 분마다 고슴도치는 현재 있는 칸과 인접한 네 칸 중 하나로 이동할 수 있다. (위, 아래, 오른쪽, 왼쪽) 물도 매 분마다 비어있는 칸으로 확장한다. 물이 있는 칸과 인접해있는 비어있는 칸(적어도 한 변을 공유)은 물이 차게 된다. 물과 고슴도치는 돌을 통과할 수 없다. 또, 고슴도치는 물로 차있는 구역으로 이동할 수 없고, 물도 비버의 소굴로 이동할 수 없다.

티떱숲의 지도가 주어졌을 때, 고슴도치가 안전하게 비버의 굴로 이동하기 위해 필요한 최소 시간을 구하는 프로그램을 작성하시오.

고슴도치는 물이 찰 예정인 칸으로 이동할 수 없다. 즉, 다음 시간에 물이 찰 예정인 칸으로 고슴도치는 이동할 수 없다. 이동할 수 있으면 고슴도치가 물에 빠지기 때문이다. 

 

 

 

입력

첫째 줄에 50보다 작거나 같은 자연수 R과 C가 주어진다.

다음 R개 줄에는 티떱숲의 지도가 주어지며, 문제에서 설명한 문자만 주어진다. 'D'와 'S'는 하나씩만 주어진다.

 

 

 

출력

첫째 줄에 고슴도치가 비버의 굴로 이동할 수 있는 가장 빠른 시간을 출력한다. 만약, 안전하게 비버의 굴로 이동할 수 없다면, "KAKTUS"를 출력한다.

 

 

 

예제

 

 

코드

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_3055_탈출 {
    static int R,C, ans;
    static char [][] map;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    
    static Queue<int[]> point = new LinkedList<int[]>();
    static Queue<int[]> water = new LinkedList<int[]>();
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        StringTokenizer st = new StringTokenizer(br.readLine()," ");
        
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        
        map = new char[R][C];
        
        for(int i=0;i<R;i++) {
            String str = br.readLine();
            for(int j=0;j<C;j++) {
                map[i][j]= str.charAt(j);
                if(map[i][j]=='S') {
                    point.offer(new int[] {i,j}); 
                }
                else if(map[i][j]=='*') {
                    water.offer(new int[] {i,j});
                }
            }
        }
        
        System.out.println(bfs()? ans:"KAKTUS");
        
    }
    
    public static boolean bfs() {
        
        while(!point.isEmpty()) {
            ans++;
            int size = water.size();
            for(int i=0;i<size;i++) {
                int [] info = water.poll();
                
                for(int d=0;d<4;d++) {
                    int nx = info[0]+dx[d];
                    int ny = info[1]+dy[d];
                    
                    if(range(nx,ny) && (map[nx][ny]=='.' || (map[nx][ny]=='S'))) {
                        map[nx][ny]='*';
                        water.offer(new int[] {nx,ny});
                    }
                }
            }
            
            size = point.size();
            
            for(int i=0;i<size;i++) {
                int [] info = point.poll();
                
                for(int d=0;d<4;d++) {
                    int nx = info[0]+dx[d];
                    int ny = info[1]+dy[d];
                    
                    if(range(nx,ny)) {
                        
                        if(map[nx][ny]=='.') {
                            map[nx][ny]='S';
                            point.offer(new int[] {nx,ny});
                        }
                        else if(map[nx][ny]=='D') return true;
                        
                    }
                }
            }
        }
        return false;
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<R && y<C;
    }
 
}
cs

 

 

+ Recent posts