diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..314044f --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Created by https://www.toptal.com/developers/gitignore/api/macos +# Edit at https://www.toptal.com/developers/gitignore?templates=macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +# End of https://www.toptal.com/developers/gitignore/api/macos \ No newline at end of file diff --git a/README.md b/README.md index 4a2355c..90d3799 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,8 @@ | 2550 | 백준 | [전구](https://www.acmicpc.net/problem/2550) | 골드 III | | 1520 | 백준 | [내리막 길](https://www.acmicpc.net/problem/1520) | 골드 III | | 1786 | 백준 | [찾기](https://www.acmicpc.net/problem/1786) | 플레 V | +<<<<<<< HEAD +======= @@ -191,6 +193,7 @@ | 1744 | 백준 | [수 묶기](https://www.acmicpc.net/problem/1744) | 골드 IV | | 17281 | 백준 | [⚾](https://www.acmicpc.net/problem/17281) | 골드 IV | | 16637 | 백준 | [괄호 추가하기](https://www.acmicpc.net/problem/16637) | 골드 III | +>>>>>>> aaaa1fa11e6dbe8a113a7bba199a43dae92fad38 diff --git a/week10/Baekjoon11055.java b/week10/Baekjoon11055.java index 150a6ca..0b98c53 100644 --- a/week10/Baekjoon11055.java +++ b/week10/Baekjoon11055.java @@ -1,7 +1,46 @@ +/* + * BOJ 11055번 : 가장 큰 증가하는 부분수열 + * 메모리 : 12,076kb + * 시간 : 88ms + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { +public class Baekjoon11055 { + static int N; + static int[] A; + static int[] dp; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + A = new int[N]; + dp = new int[N]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + dp[n] = A[n]; + } + + // dp[i] = A[i]을 마지막으로하는 부분수열 + // A[j]까지의 최대 부분수열 합 + A[i] + for(int i = 1; i < N; i++) { + for(int j = 0; j < i; j++) { + if(A[j] < A[i]) { + dp[i] = Math.max(dp[i], dp[j]+A[i]); + } + } + } + answer = Integer.MIN_VALUE; + for(int i = 0; i < N; i++) { + answer = Math.max(answer, dp[i]); + } + sb.append(answer); + System.out.print(sb); + br.close(); } -} +} \ No newline at end of file diff --git a/week10/Baekjoon11657.java b/week10/Baekjoon11657.java index ee7e1ab..ff10201 100644 --- a/week10/Baekjoon11657.java +++ b/week10/Baekjoon11657.java @@ -1,125 +1,78 @@ +/* + * BOJ 11657번 : 타임머신 + * 메모리 : 17,280kb + * 시간 : 220ms + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; + +public class Baekjoon11657 { + static int N, M; + static List edges; + static class Node { + int from, to, cost; + public Node(int from, int to, int cost) { + this.from = from; + this.to = to; + this.cost = cost; + } + } + static StringBuilder sb = new StringBuilder(); -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - 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()); - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { + edges = new ArrayList<>(); + + for(int m = 0; m < M; m++) { st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + int from = Integer.parseInt(st.nextToken()); + int to = Integer.parseInt(st.nextToken()); + int cost = Integer.parseInt(st.nextToken()); + edges.add(new Node(from, to, cost)); } + BallmanFord(1); // start - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); + System.out.print(sb); + br.close(); } - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { + + private static void BallmanFord(int start) { + // 1. 최간 거리 테이블 초기화 + long[] dist = new long[N+1]; + Arrays.fill(dist, Integer.MAX_VALUE); + dist[start] = 0; - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; + // 2. 전체 간선 하나씩 확인 (N-1번) + for(int i = 1; i < N; i++) { + for(Node edge : edges) { + // 출발 정점이 도달 가능한 경우, + // 각 간선을 거쳐 다른 노르로 가는 비용을 계산해 최단 거리 테이블 갱신 + if(dist[edge.from] != Integer.MAX_VALUE + && dist[edge.to] > dist[edge.from]+edge.cost) { + dist[edge.to] = dist[edge.from]+edge.cost; + } + } } - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } - - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; + // 3. 음수 사이클 존재 여부 확인 (1번만) + // 한번 더 돌려서 갱신되는 간선이 있으면 -> 음수 사이클! + for(Node edge : edges) { + if(dist[edge.from] != Integer.MAX_VALUE + && dist[edge.to] > dist[edge.from]+edge.cost) { + sb.append(-1); + return; + } } - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + // 4. 최종 결과 출력 + for(int n = 2; n <= N; n++) { + sb.append(dist[n]==Integer.MAX_VALUE ? -1 : dist[n]).append("\n"); } - } - - - -} +} \ No newline at end of file diff --git a/week10/Baekjoon1238.java b/week10/Baekjoon1238.java index ee7e1ab..896dd41 100644 --- a/week10/Baekjoon1238.java +++ b/week10/Baekjoon1238.java @@ -1,125 +1,113 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 +/* + * BOJ 1238번 : 파티 + * 메모리 : 211,144kb + * 시간 : 280ms * - * - * @author SSAFY - * + * 출발 + 도착 거리가 가장 오래 걸리는 학생의 소요시간 출력 */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - + +import java.io.*; +import java.util.*; + +public class Baekjoon1238 { + static int N, M, X; + static List[] edges; + static List[] edgesReverse; + static class Node { + int to, cost; + public Node(int to, int cost) { + this.to = to; + this.cost = cost; + } + } + static int[] dist; + static int[] distReverse; + static int maxTime; + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); + X = Integer.parseInt(st.nextToken()); - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { + edges = new ArrayList[N+1]; + for(int n = 0; n <= N; n++) { + edges[n] = new ArrayList(); + } + edgesReverse = new ArrayList[N+1]; + for(int n = 0; n <= N; n++) { + edgesReverse[n] = new ArrayList(); + } + + for(int m = 0; m < M; m++) { st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + int from = Integer.parseInt(st.nextToken()); + int to = Integer.parseInt(st.nextToken()); + int cost = Integer.parseInt(st.nextToken()); + edges[from].add(new Node(to, cost)); + edgesReverse[to].add(new Node(from, cost)); } + maxTime = Integer.MIN_VALUE; - visited = new boolean[N+2][M+2]; + // 각자 집에서 -> M번 마을로 갈 때 + DijkstraReverse(); + // M번 마을에서 -> 각자 집으로 돌아갈 때 + Dijkstra(); - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } + for(int n = 1; n <= N; n++) { + maxTime = Math.max(maxTime, distReverse[n]+dist[n]); } - System.out.println(max); + sb.append(maxTime); + System.out.print(sb); + br.close(); } - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { + + private static void DijkstraReverse() { + PriorityQueue pq = new PriorityQueue<>((o1,o2) -> o1.cost-o2.cost); + pq.offer(new Node(X, 0)); // to, cost - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } + distReverse = new int[N+1]; + Arrays.fill(distReverse, Integer.MAX_VALUE); + distReverse[X] = 0; - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); + while(!pq.isEmpty()) { + Node currNode = pq.poll(); + + for(int i = 0; i < edgesReverse[currNode.to].size(); i++) { + Node nextNode = edgesReverse[currNode.to].get(i); + + if(distReverse[nextNode.to] > currNode.cost+nextNode.cost) { + distReverse[nextNode.to] = currNode.cost+nextNode.cost; + pq.offer(new Node(nextNode.to, distReverse[nextNode.to])); + } + } } } - - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } + + private static void Dijkstra() { + PriorityQueue pq = new PriorityQueue<>((o1,o2) -> o1.cost-o2.cost); + pq.offer(new Node(X, 0)); // to, cost - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; + dist = new int[N+1]; + Arrays.fill(dist, Integer.MAX_VALUE); + dist[X] = 0; + + while(!pq.isEmpty()) { + Node currNode = pq.poll(); - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + for(int i = 0; i < edges[currNode.to].size(); i++) { + Node nextNode = edges[currNode.to].get(i); + + if(dist[nextNode.to] > currNode.cost+nextNode.cost) { + dist[nextNode.to] = currNode.cost+nextNode.cost; + pq.offer(new Node(nextNode.to, dist[nextNode.to])); + } + } } - } - - - } diff --git a/week10/Baekjoon13549.java b/week10/Baekjoon13549.java index 150a6ca..b93626c 100644 --- a/week10/Baekjoon13549.java +++ b/week10/Baekjoon13549.java @@ -1,7 +1,71 @@ +/* + * BOJ 13549번 : 숨바꼭질3 + * 메모리 : 24,900kb + * 시간 : 124ms + * + * 최소 시간 기록 배열 수정 -> 시간초과 해결 + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { +public class Baekjoon13549 { + static int N, K; + static int time = Integer.MAX_VALUE; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + K = Integer.parseInt(st.nextToken()); + + bfs(); + + sb.append(time); + System.out.println(sb); + br.close(); + } + + private static void bfs() { + Queue q = new ArrayDeque<>(); + int[] visited = new int[100001]; + Arrays.fill(visited, Integer.MAX_VALUE); + + q.offer(new int[] { N, 0 }); // 현재 위치, 시간 + visited[N] = 0; // 최소 시간 기록 + while(!q.isEmpty()) { + int[] curr = q.poll(); + int currPosition = curr[0]; + int currTime = curr[1]; + + // 동생이 있는 K 위치에 도착했을 때 + if(currPosition == K) { + time = Math.min(time, currTime); + continue; + } + + // 1. 걷는 경우 : 1초 후 X-1, X+1 위치로 이동 + // 2. 순간이동을 하는 경우 : 0초 후 2*X 위치로 이동 + int[] nextArr = new int[] { currPosition-1, currPosition+1, currPosition*2 }; + for(int i = 0; i < 3; i++) { + int next = nextArr[i]; + if(next < 0 || next > 100000) + continue; + + if(i < 2) { + if(visited[next] > currTime+1) { + visited[next] = currTime+1; + q.offer(new int[] { next, currTime+1 }); + } + } else { + if(visited[next] > currTime) { + visited[next] = currTime; + q.offer(new int[] { next, currTime }); + } + } + } + } } -} +} \ No newline at end of file diff --git a/week10/Baekjoon15486.java b/week10/Baekjoon15486.java index 150a6ca..3ab0d10 100644 --- a/week10/Baekjoon15486.java +++ b/week10/Baekjoon15486.java @@ -1,7 +1,41 @@ +/* + * BOJ 15486번 : 퇴사2 + * 메모리 : 308,420kb + * 시간 : 632ms + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { +public class Baekjoon15486 { + static int N; + static int[] T; + static int[] P; + static long[] dp; // 얻을 수 있는 최대 수익 저장 + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + T = new int[N]; // 걸리는 기간 + P = new int[N]; // 받을 수 있는 금액 + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + T[n] = Integer.parseInt(st.nextToken()); + P[n] = Integer.parseInt(st.nextToken()); + } + + dp = new long[N+1]; + for(int n = 0; n < N; n++) { + if(n+T[n] <= N) { // 현재 날짜에서 상담이 가능할 때 + dp[n+T[n]] = Math.max(dp[n+T[n]], dp[n]+P[n]); + } + // 상담을 선택하지 않고 다음 날짜로 넘어갈 때 (해당 날짜에 상담하지 않는 경우도 항상 고려해야 한다!!!) + dp[n+1] = Math.max(dp[n+1], dp[n]); + } + sb.append(dp[N]); + System.out.print(sb); + br.close(); } -} +} \ No newline at end of file diff --git a/week10/Baekjoon2607.java b/week10/Baekjoon2607.java index 150a6ca..3cafaf6 100644 --- a/week10/Baekjoon2607.java +++ b/week10/Baekjoon2607.java @@ -1,7 +1,58 @@ +/* + * BOJ 2607번 : 비슷한 단어 + * 메모리 : 11,472kb + * 시간 : 64ms + * + * 한 문자를 더하거나, 빼거나, 하나의 문자를 다른 문자로 바꾸어 + * 한 단어와 같은 구성을 가지면 비슷한 단어 + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { +public class Baekjoon2607 { + static int N; + static int[] alpha; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + alpha = new int[26]; + + String first = br.readLine(); + for(int n = 0; n < N-1; n++) { + for(int i = 0; i < first.length(); i++) { + alpha[first.charAt(i)-'A']++; + } + + int cnt = 0; // 비슷한 글자의 개수 + String line = br.readLine(); + for(int i = 0; i < line.length(); i++) { + if(alpha[line.charAt(i)-'A']>0) { + cnt++; + alpha[line.charAt(i)-'A']--; + } + } + + if(first.length()==line.length()+1 && line.length()==cnt) { + // 1. 문자 더해주는 경우 + answer++; + } else if(first.length()==line.length()-1 && line.length()-1==cnt) { + // 2. 문자 빼주는 경우 + answer++; + } else if(first.length()==line.length() && first.length()-1==cnt) { + // 3. 문자 하나만 바꾸는 경우 + answer++; + } else if(first.length()==line.length() && first.length() == cnt) { + // 4. 문자 동일한 경우 + answer++; + } + } + sb.append(answer); + System.out.print(sb); + br.close(); } -} +} \ No newline at end of file diff --git a/week10/Baekjoon9084.java b/week10/Baekjoon9084.java index ee7e1ab..6facc40 100644 --- a/week10/Baekjoon9084.java +++ b/week10/Baekjoon9084.java @@ -1,125 +1,47 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 +/* + * BOJ 9084번 : 동전 + * 메모리 : 11,764kb + * 시간 : 68ms * - * - * @author SSAFY - * + * 동전의 종류가 주어질 때 주어진 금액을 만드는 모든 방법을 세야한다. + * dp[만들고 싶은 금액] = dp[만들고 싶은 금액-coin] */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - - 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()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } +import java.io.*; +import java.util.*; - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { +public class Baekjoon9084 { + static int N; + static int[] coin; + static int M; + static int[] dp; // 만들 수 있는 경우의 수 저장 + static int answer; - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + int T = Integer.parseInt(br.readLine()); + for(int t = 1; t <= T; t++) { + N = Integer.parseInt(br.readLine()); + coin = new int[N+1]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 1; n <= N; n++) { + coin[n] = Integer.parseInt(st.nextToken()); + } + M = Integer.parseInt(br.readLine()); - int nr = r+dr[d]; - int nc = c+dc[d]; + dp = new int[M+1]; + dp[0] = 1; // 금액 0 일때, 아무것도 사용하지 않는 경우의 수 1 - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; + for(int n = 1; n <= N; n++) { + for(int m = coin[n]; m <= M; m++) { + dp[m] += dp[m-coin[n]]; + } + } - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + sb.append(dp[M]).append("\n"); } - + System.out.print(sb); + br.close(); } - - - -} +} \ No newline at end of file diff --git a/week11/Baekjoon14658.java b/week11/Baekjoon14658.java index ee7e1ab..d48a35e 100644 --- a/week11/Baekjoon14658.java +++ b/week11/Baekjoon14658.java @@ -1,125 +1,60 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY +/* + * BOJ 14658번 : 하늘에서 별똥별이 빗발친다 + * 메모리 : 12,100kb + * 시간 : 104ms * + * 최적해를 구하기 위해 -> x축 y축으로 나누기!!! */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - + +import java.io.*; +import java.util.*; + +public class Baekjoon14658 { + static int N, M, L, K; + static int[][] stars; + static int maxCount; + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { + L = Integer.parseInt(st.nextToken()); + K = Integer.parseInt(st.nextToken()); + + stars = new int[K][2]; + for(int k = 0; k < K; k++) { st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); - } + stars[k][0] = Integer.parseInt(st.nextToken()); + stars[k][1] = Integer.parseInt(st.nextToken()); - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + maxCount = 0; - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + for(int i = 0; i < K; i++) { + for(int j = 0; j < K; j++) { + int baseX = stars[i][0]; + int baseY = stars[j][1]; + + int count = 0; + + for(int k = 0; k < K; k++) { + int x = stars[k][0]; + int y = stars[k][1]; + + if(x >= baseX && y >= baseY && x <= baseX+L && y <= baseY+L) { + count++; + } + } + + maxCount = Math.max(maxCount, count); + } } - - } - - -} + sb.append(K-maxCount); + System.out.print(sb); + br.close(); + } +} \ No newline at end of file diff --git a/week11/Baekjoon1520.java b/week11/Baekjoon1520.java index ee7e1ab..965a214 100644 --- a/week11/Baekjoon1520.java +++ b/week11/Baekjoon1520.java @@ -1,125 +1,69 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY +/* + * BOJ 1520번 : 내리막길 + * 메모리 : 39,540번 + * 시간 : 276ms + * + * dfs로 모든 경로 재탐색하려고 했지만, + * 불필요한 백트래킹이 발생해서 StackOverflowError 발생 * + * dp 배열에 경로값 저장해서 메모이제이션 */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - + +import java.io.*; +import java.util.*; + +public class Baekjoon1520 { + static int M, N; + static int[][] map; + static int[][] dp; + static int H; + static int[] dx = new int[] { -1, 1, 0, 0 }; + static int[] dy = new int[] { 0, 0, -1, 1 }; + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { + N = Integer.parseInt(st.nextToken()); + map = new int[M][N]; + dp = new int[M][N]; + for(int m = 0; m < M; m++) { st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); + for(int n = 0; n < N; n++) { + map[m][n] = Integer.parseInt(st.nextToken()); + dp[m][n] = -1; } } - - System.out.println(max); + + H = dfs(0, 0); // x, y + + sb.append(H); + System.out.print(sb); + br.close(); } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; + private static int dfs(int x, int y) { + if(x==M-1 && y==N-1) { + return 1; // 도착지에 도착했으면 경로 1 } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); + + if(dp[x][y] != -1) { // 0이 아니라면 이전의 경로값 사용 + return dp[x][y]; } - } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + dp[x][y] = 0; // 초기화 - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + for(int d = 0; d < 4; d++) { + int nx = x + dx[d]; + int ny = y + dy[d]; + + if(nx < 0 || ny < 0 || nx >= M || ny >= N) continue; + if(map[x][y] > map[nx][ny]) { + dp[x][y] += dfs(nx, ny); + } } - - } - - -} + return dp[x][y]; + } +} \ No newline at end of file diff --git a/week11/Baekjoon1786.java b/week11/Baekjoon1786.java index ee7e1ab..5e9da8a 100644 --- a/week11/Baekjoon1786.java +++ b/week11/Baekjoon1786.java @@ -1,125 +1,67 @@ +/* + * BOJ 1786번 : 찾기 + * 메모리 : 67,340kb + * 시간 : 388ms + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; + +public class Baekjoon1786 { -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - 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()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); + StringBuilder sb = new StringBuilder(); + + char[] text = br.readLine().toCharArray(); + char[] pattern = br.readLine().toCharArray(); + int tLength = text.length; + int pLength = pattern.length; + + // 1. 부분 일치 테이블 만들기 + int[] pi = new int[pLength]; + + for(int i=1, j=0; i < pLength; i++) { + // 두 포인터의 위치에서 불일치가 발생하면 맞은 직전위치의 정보를 활용해서 불필요한 비교 줄임 + while(j>0 && pattern[i] != pattern[j]) { + j = pi[j-1]; } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); + + // 현재 i 위치의 부분문자열의 접미사와 접두사가 일치하는 패턴의 최장길이 저장 + if(pattern[i] == pattern[j]) { // j 위치까지 맞은 상황 + pi[i] = ++j; // j 위치까지 맞으면 j+1 길이만큼 맞은 것, 후에 j 이동 } } - - System.out.println(max); - } +// System.out.println(Arrays.toString(pi)); - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } + // 2. 패턴 찾기 + int cnt = 0; + ArrayList list = new ArrayList<>(); - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + for(int i=0, j=0; i < tLength; i++) { + while(j > 0 && text[i] != pattern[j]) { + j = pi[j-1]; + } - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; + if(text[i] == pattern[j]) { + if(j == pLength-1) { // 일치가 발생한 위치가 패턴의 끝이면 + cnt++; // 패턴 찾았으므로 카운트 증가 + list.add(i-j+1); // 시작 위치, 문제에서는 1부터 위치 카운트 + j = pi[j]; + } else { + j++; + } + } } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + + sb.append(cnt).append("\n"); + if(cnt > 0) { + for(int result : list) { + sb.append(result).append(" "); + } } - - } - - -} + System.out.print(sb); + br.close(); + } +} \ No newline at end of file diff --git a/week11/Baekjoon2467.java b/week11/Baekjoon2467.java index ee7e1ab..0305c22 100644 --- a/week11/Baekjoon2467.java +++ b/week11/Baekjoon2467.java @@ -1,125 +1,55 @@ +/* + * BOJ 2467번 : 용액 + * 메모리 : 31,564kb + * 시간 : 248ms + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - - public static void main(String[] args) throws IOException { +public class Baekjoon2467 { + static int N; + static int[] value; + + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + value = new int[N]; StringTokenizer st = new StringTokenizer(br.readLine()); - - N = Integer.parseInt(st.nextToken()); - M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } + for(int n = 0; n < N; n++) { + value[n] = Integer.parseInt(st.nextToken()); } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } + Arrays.sort(value); - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + int left = 0; + int right = N-1; + int minDiff = Integer.MAX_VALUE; - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + int answerLeft = 0; + int answerRight = 0; + + while(left < right) { + int sum = value[left] + value[right]; + int diff = Math.abs(sum); + + + if(minDiff > diff) { + minDiff = diff; + answerLeft = value[left]; + answerRight = value[right]; + } + + if(sum < 0) { + left++; + } else { + right--; + } } - - } - - -} + sb.append(answerLeft).append("\n").append(answerRight); + System.out.print(sb); + br.close(); + } +} \ No newline at end of file diff --git a/week11/Baekjoon2550.java b/week11/Baekjoon2550.java index ee7e1ab..ae58697 100644 --- a/week11/Baekjoon2550.java +++ b/week11/Baekjoon2550.java @@ -1,125 +1,99 @@ +/* + * BOJ 2550번 : 전구 + * 메모리 : 18,812kb + * 시간 : 176ms + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; + +public class Baekjoon2550 { + static int N; + static int[][] arr; + static int[] LIS; + static int[] POS; -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + + int[] A = new int[N]; + int[] B = new int[N]; + Map indexMap = new HashMap<>(); + + // A 입력 + A 전구 번호 -> 인덱스 매핑 StringTokenizer st = new StringTokenizer(br.readLine()); - - N = Integer.parseInt(st.nextToken()); - M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + for (int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + indexMap.put(A[n], n); } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } + // B 입력 + st = new StringTokenizer(br.readLine()); + for (int n = 0; n < N; n++) { + B[n] = Integer.parseInt(st.nextToken()); } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; + // arr[n][0] = B 전구 번호 + // arr[n][1] = A 기준 인덱스 + arr = new int[N][2]; + for(int n = 0; n < N; n++) { + arr[n][0] = B[n]; + arr[n][1] = indexMap.get(B[n]); } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); + + LIS = new int[N]; + POS = new int[N]; + LIS[0] = arr[0][1]; + POS[0] = 0; + int length = 1; + + for(int n = 1; n < N; n++) { + if(arr[n][1] > LIS[length-1]) { + LIS[length] = arr[n][1]; + POS[n] = length; + length++; + } else { + int pos = binarySearch(0, length-1, arr[n][1]); + LIS[pos] = arr[n][1]; + POS[n] = pos; + } } - } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + Set set = new HashSet<>(); + int idx = length-1; - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; + for(int n = N-1; n >= 0; n--) { + if(POS[n]==idx) { + set.add(arr[n][0]); // B 전구 번호 출력 + idx--; + } + if(idx < 0) break; } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + +// System.out.println(Arrays.toString(LIS)); +// System.out.println(Arrays.toString(POS)); + + List list = new ArrayList(set); + Collections.sort(list); + + sb.append(length).append("\n"); + for(int answer : list) { + sb.append(answer).append(" "); } - + System.out.print(sb); + br.close(); } - - -} + private static int binarySearch(int left, int right, int target) { + while(left < right) { + int mid = (left+right)/2; + if(LIS[mid] < target) { + left=mid+1; + } else { + right=mid; + } + } + return left; + } +} \ No newline at end of file diff --git a/week12/Baekjoon16637.java b/week12/Baekjoon16637.java index ee7e1ab..d947551 100644 --- a/week12/Baekjoon16637.java +++ b/week12/Baekjoon16637.java @@ -1,125 +1,84 @@ +/* +* BOJ 16637번 : 괄호 추가하기 +* 메모리 : 11,552kb +* 시간 : 68ms +* +* 숫자, 연산자 분리 +* 괄호 없이 연산 수행, 괄호 추가 후 연산 수행 +* N=19 -> 연산자 9개 +* 2^9 = 512 * 숫자 10개 = 5000번 완탐 가능!!! + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - - 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()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); - } +public class Baekjoon16637 { + static int N; + static int[] num; + static boolean[] visited; + static char[] oper; + static int maxAnswer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); // 수식의 길이 + + num = new int[N/2+1]; + visited = new boolean[N/2+1]; + oper = new char[N/2]; + + String input = br.readLine(); + num[0] = input.charAt(0) - '0'; + int numIdx = 1; + int operIdx = 0; + + for (int n = 1; n < input.length(); n++) { + if(n%2 == 1) { + oper[operIdx] = input.charAt(n); + operIdx++; + } else if(n%2 == 0){ + num[numIdx] = input.charAt(n) - '0'; + numIdx++; + } + } +// System.out.println(Arrays.toString(num)); +// System.out.println(Arrays.toString(oper)); + + maxAnswer = Integer.MIN_VALUE; + dfs(0, num[0]); + + sb.append(maxAnswer); + System.out.println(sb); + br.close(); + } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } + private static void dfs(int idx, int sum) { + // 모든 연산자를 다 처리했을 때 + if(idx >= oper.length) { + maxAnswer = Math.max(maxAnswer, sum); + return; + } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + // 괄호 없이 연산 수행 + int res1 = calc(sum, num[idx+1], oper[idx]); + dfs(idx+1, res1); - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - - } - - + // 괄호를 추가할 수 있는 경우 + if(idx+1 < oper.length) { + int inSum = calc(num[idx+1], num[idx+2], oper[idx+1]); // 괄호 안의 값 계산 + int res2 = calc(sum, inSum, oper[idx]); // 괄호 계산 결과 포함해서 전체 계산 + dfs(idx+2, res2); + } + } -} + private static int calc(int a, int b, int op) { + if(op == '+'){ + return a+b; + } else if(op == '-'){ + return a-b; + } else { + return a*b; + } + } +} \ No newline at end of file diff --git a/week12/Baekjoon17281.java b/week12/Baekjoon17281.java deleted file mode 100644 index ee7e1ab..0000000 --- a/week12/Baekjoon17281.java +++ /dev/null @@ -1,125 +0,0 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - - 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()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); - } - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } - - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - - } - - - -} diff --git a/week12/Baekjoon1744.java b/week12/Baekjoon1744.java index ee7e1ab..a573b49 100644 --- a/week12/Baekjoon1744.java +++ b/week12/Baekjoon1744.java @@ -1,125 +1,115 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 +/* + * BOJ 1744_수묶기 + * 메모리 : 11,644kb + * 시간 : 68ms * - * - * @author SSAFY - * + * 1. 음수 + * 1-1. 음수가 2개 이상이면 음수 2개 곱해서 더함 + * 1-2. 음수가 홀수이면 결과는 무조건 음수 + * 1-3. 음수가 홀수일 때 0이 있으면 0으로 음수 제거(음수를 없앨 수 있음), 0이 없으면 그냥 더하기 + * 2. 양수 + * 2-1. 양수 2개 곱해서 더함 + * 2-1. 양수 중 1이 있으면 곱하지 말고 더하기 (더하는게 더 이득) */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 + +import java.io.*; +import java.util.*; + +public class Baekjoon1744 { + static int N; + static Num[] num; + static List sumList; + static int maxSum; - 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()); + public static class Num implements Comparable{ + int num; + boolean check; - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + public Num(int num) { + this.num = num; + this.check = false; } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } - } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } + @Override + public int compareTo(Num o) { + return this.num-o.num; + } } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + num = new Num[N]; + sumList = new ArrayList<>(); + + for(int n = 0; n < N; n++) { + num[n] = new Num(Integer.parseInt(br.readLine())); + } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + Arrays.sort(num); - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - - } - - + // 1. 음수 처리 + // 1-1. 정렬된 리스트 앞쪽에서 음수 2개씩 짝지어서 곱함 + // 1-2. 짝이 없거나 다음 수가 0보다 크면 break + for(int n = 0; n < N; n += 2) { + if(n+1 < N) { + if(num[n].num <= 0 && num[n+1].num <= 0) { + num[n].check = true; + num[n+1].check = true; + sumList.add(num[n].num * num[n+1].num); + } else { + break; + } + } + } + // 1-3. 0이 있고, 짝이 없는 음수가 있을 경우 + boolean isZero = false; + for(int n = 0; n < N; n++) { + if(num[n].num==0) { + isZero = true; + break; + } + } + for(int n = 0; n < N; n++) { + if(num[n].num < 0 && !num[n].check) { + if(isZero) { + num[n].check = true; + break; // 음수 하나만 제거해주고 break + } + } + } + + // 2. 양수 처리 + // 2-1. 정렬된 리스트 뒤쪽에서 양수 2개씩 짝지어서 곱합 + // 2-2. 1은 곱해도 변화없음 (더해줘야 함) + for(int n = N-1; n >= 0; n -= 2) { + if(n-1 >= 0) { + if(num[n].num > 1 && num[n-1].num > 1) { + num[n].check = true; + num[n-1].check = true; + sumList.add(num[n].num * num[n-1].num); + } else { + break; + } + } + } + + // 안묶인 남은 숫자들은 그냥 더하기 + for(int i = 0; i < N ; i++){ + if(!num[i].check){ + sumList.add(num[i].num); + } + } + + maxSum = 0; + + for(int sum : sumList) { + maxSum += sum; + } + sb.append(maxSum); + System.out.print(sb); + br.close(); + } } diff --git a/week12/Baekjoon19539.java b/week12/Baekjoon19539.java index ee7e1ab..45031f3 100644 --- a/week12/Baekjoon19539.java +++ b/week12/Baekjoon19539.java @@ -1,125 +1,35 @@ +/* + * BOJ 19539번 : 사과나무 + * 메모리 : 22,760kb + * 시간 : 192ms + */ -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +import java.io.*; +import java.util.*; + +public class Baekjoon19539 { + static int N; -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + int one = 0, two = 0, sum = 0; StringTokenizer st = new StringTokenizer(br.readLine()); - - N = Integer.parseInt(st.nextToken()); - M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + for(int n = 0; n < N; n++) { + int num = Integer.parseInt(st.nextToken()); + sum += num; + one += num%2; + two += num/2; } - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } + if(sum%3 > 0 || one > two) { // 3으로 나누어 떨어져야 함, 1은 2보다 크면 안됨 + sb.append("NO"); + } else { // 1==2인 경우, 2가 1보다 큰 경우 만들 수 있음 + sb.append("YES"); } - System.out.println(max); + System.out.print(sb); + br.close(); } - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } - } - - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - - } - - - -} +} \ No newline at end of file diff --git a/week12/Baekjoon2589.java b/week12/Baekjoon2589.java index ee7e1ab..3bd4862 100644 --- a/week12/Baekjoon2589.java +++ b/week12/Baekjoon2589.java @@ -1,125 +1,120 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 +/* + * BOJ 2589번 : 보물섬 + * 메모리 : 219,000kb + * 시간 : 424ms * - * - * @author SSAFY - * + * 1. 모든 육지(L)를 시작점으로 bfs 실행 + * 2. 최대 거리 구하기 + * 3. 최대 거리에서 최간 거리(대각선 이동 포함) bfs 실행 + * 4. 최대 거리에서 가장 가까운 L 탐색 */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 + +import java.io.*; +import java.util.*; + +public class Baekjoon2589 { + static int N, M; + static char[][] map; + static int[] dx = new int[] { -1, 1, 0, 0, -1, 1, -1, 1 }; + static int[] dy = new int[] { 0, 0, -1, 1, -1, 1, 1, -1 }; + static int maxDist, minDist; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); + map = new char[N][M]; + + maxDist = Integer.MIN_VALUE; + List maxDistList = new ArrayList<>(); - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); + for (int n = 0; n < N; n++) { + String str = br.readLine(); + for (int m = 0; m < M; m++) { + map[n][m] = str.charAt(m); } } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); + for (int n = 0; n < N; n++) { + for (int m = 0; m < M; m++) { + if(map[n][m] == 'L') { + int dist = bfs(n, m); + if(dist > maxDist) { + maxDist = dist; + maxDistList.clear(); // 새로운 최장 거리 찾았으니까 클리어 + maxDistList.add(new int[] { n, m }); + } else if(dist == maxDist) { + maxDistList.add(new int[] { n, m }); + } + } } } - System.out.println(max); - } - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; + minDist = Integer.MAX_VALUE; + for(int[] list : maxDistList) { + minDist = Math.max(minDist, bfs2(list[0], list[1])); } - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } + sb.append(maxDist); + System.out.println(sb); + br.close(); } - - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } + + // 1. 모든 L에서 최장 거리 찾기(4방) + private static int bfs(int x, int y) { + boolean[][] visited = new boolean[N][M]; + Queue q = new ArrayDeque(); + q.add(new int[] { x, y, 0 }); + visited[x][y] = true; - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; + int maxDist = 0; + while(!q.isEmpty()) { + int[] curr = q.poll(); + int cx = curr[0]; + int cy = curr[1]; + int dist = curr[2]; - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; + maxDist = Math.max(maxDist, dist); - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + for(int d = 0; d < 4; d++) { + int nx = cx + dx[d]; + int ny = cy + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < N && ny < M && !visited[nx][ny] && map[nx][ny] == 'L') { + visited[nx][ny] = true; + q.offer(new int[] { nx, ny, dist+1 }); + } + } } + return maxDist; } - - -} + // 2. 최장 거리에서 최단 거리 찾기(8방) + private static int bfs2(int x, int y) { + boolean[][] visited = new boolean[N][M]; + Queue q = new ArrayDeque(); + q.add(new int[] { x, y, 0 }); + visited[x][y] = true; + + while(!q.isEmpty()) { + int[] curr = q.poll(); + int cx = curr[0]; + int cy = curr[1]; + int dist = curr[2]; + + for(int d = 0; d < 8; d++) { + int nx = cx + dx[d]; + int ny = cy + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < N && ny < M && !visited[nx][ny] && map[nx][ny] == 'L') { + visited[nx][ny] = true; + return dist+1; + } + } + } + + return Integer.MAX_VALUE; + } +} \ No newline at end of file diff --git a/week13/Baekjoon14725.java b/week13/Baekjoon14725.java new file mode 100644 index 0000000..e1ef8e4 --- /dev/null +++ b/week13/Baekjoon14725.java @@ -0,0 +1,63 @@ +/* + * BOJ 14725번 : 개미굴 + * 메모리 : 14,136kb + * 시간 : 120ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class BOJ14725_개미굴 { + static int N, K; + static Map index; + static Map[] trie; + static int nodeCount = 1; + static StringBuilder sb; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + index = new HashMap<>(); + trie = new HashMap[15000]; // N*K 최대 1000*15 + for(int i = 0; i < 15000; i++) { + trie[i] = new HashMap<>(); + } + + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + K = Integer.parseInt(st.nextToken()); + int curr = 0; // 루트부터 시작 + for(int k = 0; k < K; k++) { + String feed = st.nextToken(); + + if(!trie[curr].containsKey(feed)) { + trie[curr].put(feed, nodeCount++); + } + curr = trie[curr].get(feed); + } + } + + dfs(0, 0); // node, depth + + System.out.println(sb); + br.close(); + } + + private static void dfs(int node, int depth) { + List keyList = new ArrayList<>(trie[node].keySet()); + Collections.sort(keyList); + + for(String key : keyList) { + for(int i = 0; i < depth; i++) { + sb.append("--"); + } + sb.append(key).append("\n"); // 해당 키(먹이이름) + + // 키에 연결된 자식 노드로 재귀 호출 + dfs(trie[node].get(key), depth+1); + } + } +} diff --git a/week13/Baekjoon2179.java b/week13/Baekjoon2179.java new file mode 100644 index 0000000..482841d --- /dev/null +++ b/week13/Baekjoon2179.java @@ -0,0 +1,61 @@ +/* + * BOJ 2179번 : 비슷한 단어 + * 메모리 : 15,988kb + * 시간 : 1,204ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class BOJ2179_비슷한단어 { + static int N; + static String[] word; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + word = new String[N]; + for(int n = 0; n < N; n++) { + word[n] = br.readLine(); + } + + int word1Idx = 0; + int word2Idx = 0; + int max = Integer.MIN_VALUE; + + for(int i = 0; i < N; i++) { + for(int j = i+1; j < N; j++) { + int cnt = prefix(word[i], word[j]); + + if(cnt > max) { + word1Idx = i; + word2Idx = j; + max = cnt; + } + } + } + + sb.append(word[word1Idx]).append("\n"); + sb.append(word[word2Idx]).append("\n"); + System.out.print(sb); + br.close(); + } + + private static int prefix(String word1, String word2) { + int cnt = 0; + int length = Math.min(word1.length(), word2.length()); + + for(int k = 0; k < length; k++) { + if(word1.charAt(k) == word2.charAt(k)) { + cnt++; + } else { + break; + } + } + + return cnt; + } +} diff --git a/week13/Baekjoon22860.java b/week13/Baekjoon22860.java new file mode 100644 index 0000000..b81c60e --- /dev/null +++ b/week13/Baekjoon22860.java @@ -0,0 +1,89 @@ +/* + * BOJ 22860번 : 폴더정리(Small) + * 메모리 : 98,236kb + * 시간 : 764ms + * + * 1. 이름(폴더/파일)을 인덱싱헤서 저장 Map index + * 2. 폴더 간 연결 List[] folder + * 3. 폴더에 속한 파일 저장 Set[] folderfile; + * 4. dfs 탐색으로 파일 종류 수 / 전체 개수 계산 + * 4-1. 파일 이름은 Set에 추가 (종류 수) + * 4-2. 개수는 누적해서 리턴 (전체 개수) + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class BOJ22860_폴더정리 { + static int N, M; + static Map index; + static List[] folder; + static Set[] folderfile; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + index = new HashMap<>(); + folder = new ArrayList[N+M]; + folderfile = new HashSet[N+M]; + for(int n = 0; n < N+M; n++) { + folder[n] = new ArrayList<>(); + folderfile[n] = new HashSet<>(); + } + + int idx = 0; + for(int n = 0; n < N+M; n++) { + st = new StringTokenizer(br.readLine()); + String P = st.nextToken(); // 상위 폴더 이름 + String F = st.nextToken(); // 폴더 또는 파일 이름 + int C = Integer.parseInt(st.nextToken()); // 폴더(1), 파일(0) + + if(!index.containsKey(P)) { + index.put(P, idx++); + } + if(!index.containsKey(F)) { + index.put(F, idx++); + } + + if(C == 1) { + folder[index.get(P)].add(index.get(F)); // 폴더 연결 + } else { + folderfile[index.get(P)].add(F); // 폴더-파일 연결 + } + } + + int Q = Integer.parseInt(br.readLine()); + for(int q = 0; q < Q; q++) { + // 폴더 하위에 있는 파일의 종류, 파일의 총 개수 출력하기 + String[] path = br.readLine().split("/"); + String target = path[path.length-1]; + int start = index.get(target); + + Set file = new HashSet<>(); + int fileCnt = dfs(start, file); + sb.append(file.size()).append(" ").append(fileCnt).append("\n"); + } + System.out.print(sb); + br.close(); + } + + private static int dfs(int curr, Set file) { + int cnt = 0; + + for(String f : folderfile[curr]) { // 현재 폴더에 직접 속한 파일 + file.add(f); + cnt++; + } + + for(int next : folder[curr]) { // 현재 폴더의 하위 폴더 + cnt += dfs(next, file); + } + + return cnt; + } +} diff --git a/week13/Baekjoon2866.java b/week13/Baekjoon2866.java new file mode 100644 index 0000000..53396fc --- /dev/null +++ b/week13/Baekjoon2866.java @@ -0,0 +1,63 @@ +/* + * BOJ 2866번 : 문자열 잘라내기 + * 메모리 : 308,140kb + * 시간 : 1088ms + */ + +import java.io.*; +import java.util.*; + +public class BOJ2866_문자열잘라내기 { + static int R, C; + static char[][] arr; + static int cnt; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + R = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + arr = new char[R][C]; + cnt = 0; + for(int r = 0; r < R; r++) { + String line = br.readLine(); + for(int c = 0; c < C; c++) { + arr[r][c] = line.charAt(c); + } + } + + Set set = new HashSet<>(); // 문자열 중복 검사 + List list = new ArrayList<>(); // 최초로 만들어진 문자 리스트 + cnt = 0; + + for(int c = 0; c < C; c++) { + sb = new StringBuilder(); + for(int r = 0; r < R; r++) { + sb.append(arr[r][c]); // 세로로 문자열 만들기 + } + set.add(sb.toString()); + list.add(sb.toString()); + } + + if(set.size() != list.size()) { // 처음부터 다르다면(=중복이 있다면) 0 출력 + System.out.println(cnt); + return; + } + + for(int r = 1; r < R; r++) { + set = new HashSet<>(); + for(int c = 0; c < C; c++) { + set.add(list.get(c).substring(r, R)); // 하나씩 빼고 문자열에 추가 + if(c+1 != set.size()) { // 크기 다르다면(=중복이 있다면) cnt 출력 + System.out.println(cnt); + return; + } + } + cnt++; + } + + System.out.println(cnt); + br.close(); + } +} \ No newline at end of file diff --git a/week13/Baekjoon5052.java b/week13/Baekjoon5052.java new file mode 100644 index 0000000..809a1be --- /dev/null +++ b/week13/Baekjoon5052.java @@ -0,0 +1,72 @@ +/* + * BOJ 5052번 : 전화번호 목록 + * 메모리 : 137,884kb + * 시간 : 736ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class BOJ5052_전화번호목록 { + static int N; + static int[][] trie; + static boolean[] isEnd; + static int nodeCount; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + int T = Integer.parseInt(br.readLine()); + for(int t = 1; t <= T; t++) { + N = Integer.parseInt(br.readLine()); + trie = new int[N*10][10]; // 최대 노드 수(최악의 경우 번호 1개당 10개의 노드), 숫자(0~9) + isEnd = new boolean[N*10]; + nodeCount = 1; // 루트를 제외하고 1번부터 카운팅 + + String[] num = new String[N]; + for(int n = 0; n < N; n++) { + num[n] = br.readLine(); + } + + Arrays.sort(num); + + boolean isConsist = true; + for(String n : num) { + if(!insert(n)) { + isConsist = false; + break; + } + } + + if(isConsist) { + sb.append("YES\n"); + } else { + sb.append("NO\n"); + } + } + System.out.print(sb); + br.close(); + } + + private static boolean insert(String num) { + int node = 0; + for(int i = 0; i < num.length(); i++) { + int digit = num.charAt(i)-'0'; + + if(trie[node][digit] == 0) { + trie[node][digit] = nodeCount++; + } + node = trie[node][digit]; + + // 현재 지나온 경로 중 누군가가 끝나는 단어라면 -> 이 번호는 누군가의 접두사 + if(isEnd[node]) { + return false; + } + } + + isEnd[node] = true; // 현재 노드는 이 번호의 끝! 표시 + return true; + } +} diff --git a/week14/Baekjoon11437.java b/week14/Baekjoon11437.java new file mode 100644 index 0000000..b449c75 --- /dev/null +++ b/week14/Baekjoon11437.java @@ -0,0 +1,91 @@ +/* + * BOJ 11437 : LCA + * 메모리 : 42,632kb + * 시간 : 1,272ms + * + * 1. 모든 노드에 대한 깊이 계산 + * 2. 최소 공통 조상을 찾을 두 노드 확인 + * 3. 먼저 두 노드의 깊이가 동일하도록 거슬러 올리감 + * 4. 부모가 같아질 때까지 반복적으로 두 노드의 부모 방향으로 거슬러 올라감 + * 5. 모든 LCA(a, b) 연산에 대해 3~4번 과정 반복 + */ + +import java.io.*; +import java.util.*; + +public class BOJ11437_LCA { + static int N, M; + static int[] parent; + static int[] level; + static List[] tree; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + parent = new int[N+1]; + level = new int[N+1]; + tree = new ArrayList[N+1]; + for(int n = 1; n <= N; n++) { + tree[n] = new ArrayList<>(); + } + + for(int n = 1; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + tree[a].add(b); + tree[b].add(a); + } + + // 1번 노드부터 트리 만들기 + dfs(1, 0); // childNode, parentNode + + M = Integer.parseInt(br.readLine()); + for(int m = 0; m < M; m++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + sb.append(LCA(a, b)).append("\n"); + } + + System.out.println(sb); + br.close(); + } + + private static void dfs(int childNode, int parentNode) { + parent[childNode] = parentNode; + level[childNode] = level[parentNode]+1; + + for(int child : tree[childNode]) { + if(child == parentNode) continue; + dfs(child, childNode); + } + } + + private static int LCA(int a, int b) { + // a 가 더 깊은 노드가 되도록 (깊이 맞추기 위해서) + if(level[a] < level[b]) { + int temp = a; + a = b; + b = temp; + } + + // a, b 깊이 맞추기 + while(level[a] != level[b]) { + a = parent[a]; + } + + // a, b 공통 조상 찾기 + while(a != b) { + a = parent[a]; + b = parent[b]; + } + + return a; + } +} + + diff --git a/week14/Baekjoon15919.js b/week14/Baekjoon15919.js new file mode 100644 index 0000000..cd29d8a --- /dev/null +++ b/week14/Baekjoon15919.js @@ -0,0 +1,35 @@ +/* + * BOJ 15919 : 사자는 여행왕이야야 + * 메모리 : 11,560kb + * 시간 : 168ms + * dp[i] = i일에 여행을 시작했을 때, i일 이전까지의 최대 공백 + */ + +const fs = require("fs"); +const input = fs.readFileSync("input.txt").toString().trim().split("\n"); + +const N = Number(input[0]); +const M = Number(input[1]); +const plans = input.slice(2).map((line) => line.split(" ").map(Number)); + +plans.sort((a, b) => a[1] - b[1]); + +const dp = new Array(N + 1).fill(Infinity); +dp[0] = 0; + +for (let [start, end] of plans) { + for (let i = 0; i < start; i++) { + const diff = start - i - 1; // i+1일 ~ start-1일 전까지 공백 + const maxDiff = Math.max(dp[i], diff); + dp[end] = Math.min(dp[end], maxDiff); + } +} + +// 마지막 날 이후 남은 공백 고려 +let answer = Infinity; +for (let i = 0; i <= N; i++) { + const diff = N - i; // i일 이후로 여행 없는 공백 + answer = Math.min(answer, Math.max(dp[i], diff)); +} + +console.log(answer); diff --git a/week14/Baekjoon15922.js b/week14/Baekjoon15922.js new file mode 100644 index 0000000..4054dd3 --- /dev/null +++ b/week14/Baekjoon15922.js @@ -0,0 +1,37 @@ +/* + * BOJ 15922 : 아우으 우아으이야 + * 메모리 : 46,168kb + * 시간 : 324ms + */ + +const fs = require("fs"); +const input = fs.readFileSync("input.txt").toString().trim().split("\n"); +// const input = fs.readFileSync("/dev/stdin").toString().trim().split("\n"); + +const N = input[0]; +const line = input.slice(1).map((line) => line.split(" ").map(Number)); + +// 1. 시작점 기준으로 정렬 +line.sort((a, b) => a[0] - b[0]); + +let [start, end] = line[0]; +let total = 0; + +for (let i = 1; i < N; i++) { + const [nextStart, nextEnd] = line[i]; + + if (nextStart <= end) { + // 2. 겹치면, 현재 선분 확장장 + end = Math.max(end, nextEnd); + } else { + // 3. 안겹치면, 지금까지 길이 더하고 다음 선분 시작 + total += end - start; + start = nextStart; + end = nextEnd; + } +} + +// 마지막 선분도 누적 +total += end - start; + +console.log(total); diff --git a/week14/Baekjoon15927.js b/week14/Baekjoon15927.js new file mode 100644 index 0000000..356a9ce --- /dev/null +++ b/week14/Baekjoon15927.js @@ -0,0 +1,21 @@ +/* + * BOJ 15922 : 회문은 회문아니야 + * 메모리 : 41,028kb + * 시간 : 256ms + */ + +const fs = require("fs"); +const input = fs.readFileSync("input.txt").toString().trim(); + +const reversed = input.split("").reverse().join(""); + +if (input != reversed) { + console.log(input.length); +} else { + const same = input.split("").every((ch) => ch === input[0]); + if (same) { + console.log(-1); + } else { + console.log(input.length - 1); + } +} diff --git a/week14/Baekjoon28423.js b/week14/Baekjoon28423.js new file mode 100644 index 0000000..9fe7d51 --- /dev/null +++ b/week14/Baekjoon28423.js @@ -0,0 +1,46 @@ +/* + * BOJ 28423 : 게임 + * 메모리 : 20,672kb + * 시간 : 248ms + */ + +const fs = require("fs"); +const input = fs.readFileSync("../algorithm/input.txt").toString().trim().split(" "); + +const L = Number(input[0]); +const R = Number(input[1]); + +let result = 0; +for (let i = L; i <= R; i++) { + const G = g(i); + result += G; +} +console.log(result); + +function f(x) { + const str = x.toString(); + let sum = 0; + let mult = 1; + + for (let i = 0; i < str.length; i++) { + sum += Number(str[i]); + mult *= Number(str[i]); + } + + return Number(sum.toString() + mult.toString()); +} + +function g(x) { + const vistied = new Set(); + + while (true) { + const F = f(x); + + if (F === x) return 1; + if (F > 100000) return -1; + if (vistied.has(F)) return 0; + + vistied.add(F); + x = F; + } +} diff --git a/week15/Baekjoon10159.java b/week15/Baekjoon10159.java new file mode 100644 index 0000000..bd5525e --- /dev/null +++ b/week15/Baekjoon10159.java @@ -0,0 +1,67 @@ +/* + * BOJ 10159번 : 저울 + * 메모리 : 13,524kb + * 시간 : 96ms + * + * 1~N개의 물건, i번째 줄에는 물건 i와 비교 결과를 알 수 없는 물건의 개수 출력 + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class BOJ10159_저울 { + static int N, M; + static List> graph; + static List> reverseGraph; + static boolean[] visited; + static int[] result; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + M = Integer.parseInt(br.readLine()); + graph = new ArrayList>(); + reverseGraph = new ArrayList>(); + for(int n = 0; n < N+1; n++) { + graph.add(new ArrayList()); + reverseGraph.add(new ArrayList()); + } + result = new int[N+1]; + + for(int m = 0; m < M; m++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + graph.get(a).add(b); + reverseGraph.get(b).add(a); + } + + for (int n = 1; n < N+1; n++) { + visited = new boolean[N+1]; + int cnt1 = dfs(n, graph); + int cnt2 = dfs(n, reverseGraph); + result[n] = cnt1+cnt2-1; // 자기자신 제외 + } + + for(int n = 1; n < N+1; n++) { + sb.append(N-result[n]).append("\n"); + } + System.out.print(sb); + br.close(); + } + + private static int dfs(int idx, List> graph) { + visited[idx] = true; + + int cnt = 1; + for (int next : graph.get(idx)) { + if (!visited[next]) { + cnt += dfs(next, graph); + } + } + return cnt; + } +} diff --git a/week15/Baekjoon1253.js b/week15/Baekjoon1253.js new file mode 100644 index 0000000..5898c5a --- /dev/null +++ b/week15/Baekjoon1253.js @@ -0,0 +1,38 @@ +/* + * BOJ 1253번 : 좋다 + * 메모리 : 9740kb + * 시간 : 176ms + */ + +const fs = require("fs"); +const input = fs.readFileSync("input.txt").toString().trim().split("\n"); + +const N = parseInt(input[0]); +const arr = input[1].split(" ").map(Number); +const arrSort = arr.sort((a, b) => a - b); +let result = 0; + +for (let i = 0; i < N; i++) { + const target = arr[i]; + let left = 0; + let right = N - 1; + + while (left < right) { + if (arrSort[left] + arrSort[right] === target) { + if (left !== i && right !== i) { + result++; + break; + } else if (left === i) { + left++; + } else if (right === i) { + right--; + } + } else if (arrSort[left] + arrSort[right] < target) { + left++; + } else { + right--; + } + } +} + +console.log(result); diff --git a/week15/Baekjoon2138.java b/week15/Baekjoon2138.java new file mode 100644 index 0000000..61b9dc1 --- /dev/null +++ b/week15/Baekjoon2138.java @@ -0,0 +1,72 @@ +/* + * BOJ 2138번 : 전구와 스위치 + * 메모리 : 16,484kb + * 시간 : 120ms + * + * i번째 전구 바꾸려면, i-1 눌러야함 + * 0번째 전구는 앞이 없으니까 + * 0번째 누르는 경우, 안누르는 경우 생각해야 함 + */ + +import java.io.*; +import java.util.*; + +public class BOJ2138_전구와스위치 { + static int N; + static int[] currStatus; + static int[] makeStatus; + static int answer = Integer.MAX_VALUE; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + currStatus = new int[N]; + makeStatus = new int[N]; + + String currInput = br.readLine(); + String makeInput = br.readLine(); + for (int n = 0; n < N; n++) { + currStatus[n] = currInput.charAt(n)-'0'; + makeStatus[n] = makeInput.charAt(n)-'0'; + } + + solve(currStatus.clone(), 0); + + int[] firstOnStatus = currStatus.clone(); + light(firstOnStatus, 0); + solve(firstOnStatus, 1); + + sb.append(answer==Integer.MAX_VALUE ? -1 : answer); + System.out.print(sb); + br.close(); + } + + public static void solve(int[] status, int count) { + for(int n = 1; n < N; n++) { + if(status[n-1] != makeStatus[n-1]) { + light(status, n); + count++; + } + } + + if(isSame(status, makeStatus)) { + answer = Math.min(answer, count); + } + } + + public static void light(int[] status, int idx) { + if(idx-1 >= 0) status[idx-1] = status[idx-1]==0 ? 1 : 0; + status[idx] = status[idx]==0 ? 1 : 0; + if(idx+1 < N) status[idx+1] = status[idx+1]==0 ? 1 : 0; + } + + public static boolean isSame(int[] currStatus, int[] makeStatus) { + for(int n = 0; n < N; n++) { + if(currStatus[n] != makeStatus[n]) { + return false; + } + } + return true; + } +} diff --git a/week15/Baekjoon2638.js b/week15/Baekjoon2638.js new file mode 100644 index 0000000..b9f1944 --- /dev/null +++ b/week15/Baekjoon2638.js @@ -0,0 +1,82 @@ +/* + * BOJ 2638번 : 치즈 + * 메모리 : 19,180kb + * 시간 : 292ms + */ + +const fs = require("fs"); +const input = fs.readFileSync("input.txt").toString().trim().split("\n"); + +const [N, M] = input[0].split(" ").map(Number); +let arr = input.slice(1).map((line) => line.split(" ").map(Number)); + +const dx = [-1, 1, 0, 0]; +const dy = [0, 0, -1, 1]; + +let time = 0; + +while (true) { + const check = checkCheese(); + const melt = meltCheese(check); + if (!melt) break; + time++; +} + +function checkCheese() { + const visited = Array.from({ length: N }, () => Array(M).fill(false)); + const queue = [[0, 0]]; + visited[0][0] = true; + + while (queue.length) { + const [x, y] = queue.shift(); + + for (let d = 0; d < 4; d++) { + const nx = x + dx[d]; + const ny = y + dy[d]; + + if (nx >= 0 && nx < N && ny >= 0 && ny < M && !visited[nx][ny] && arr[nx][ny] === 0) { + visited[nx][ny] = true; + queue.push([nx, ny]); + } + } + } + + return visited; // 외부 공기인 영역 표시 +} + +function meltCheese(check) { + const disappear = Array.from({ length: N }, () => Array(M).fill(false)); + let melted = false; + + for (let n = 0; n < N; n++) { + for (let m = 0; m < M; m++) { + if (arr[n][m] === 1) { + let cnt = 0; + for (let d = 0; d < 4; d++) { + const nx = n + dx[d]; + const ny = m + dy[d]; + + if (nx >= 0 && nx < N && ny >= 0 && ny < M && check[nx][ny]) { + cnt++; + } + } + if (cnt >= 2) { + disappear[n][m] = true; + melted = true; + } + } + } + } + + for (let n = 0; n < N; n++) { + for (let m = 0; m < M; m++) { + if (disappear[n][m]) { + arr[n][m] = 0; + } + } + } + + return melted; +} + +console.log(time); diff --git "a/week16/Baekjoon_16562_\354\271\234\352\265\254\353\271\204.java" "b/week16/Baekjoon_16562_\354\271\234\352\265\254\353\271\204.java" new file mode 100644 index 0000000..44c88ce --- /dev/null +++ "b/week16/Baekjoon_16562_\354\271\234\352\265\254\353\271\204.java" @@ -0,0 +1,75 @@ +/* + * BOJ 16562번 : 친구비 + * 메모리 : 19,800kb + * 시간 : 180ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_16562_친구비 { + static int N, M, k; + static int[] friendsCost; + static int minCost; + static List[] friends; + static boolean[] visited; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + k = Integer.parseInt(st.nextToken()); + friendsCost = new int[N+1]; + st = new StringTokenizer(br.readLine()); + for(int n = 1; n <= N; n++) { + friendsCost[n] = Integer.parseInt(st.nextToken()); + } + friends = new ArrayList[N+1]; + for(int n = 1; n <= N; n++) { + friends[n] = new ArrayList<>(); + } + for(int m = 1; m <= M; m++) { + st = new StringTokenizer(br.readLine()); + int v = Integer.parseInt(st.nextToken()); + int w = Integer.parseInt(st.nextToken()); + friends[v].add(w); + friends[w].add(v); + } + + minCost = 0; + visited = new boolean[N+1]; + + for(int n = 1; n <= N; n++) { + if(!visited[n]) { + minCost += bfs(n); + } + } + + if(minCost > k) sb.append("Oh no"); + else sb.append(minCost); + System.out.println(sb); + br.close(); + } + + public static int bfs(int n) { + Queue q = new ArrayDeque<>(); + q.offer(n); + visited[n] = true; + int cost = friendsCost[n]; + + while(!q.isEmpty()) { + int curr = q.poll(); + for(int next : friends[curr]) { + if(!visited[next]) { + q.offer(next); + visited[next] = true; + cost = Math.min(cost, friendsCost[next]); + } + } + } + + return cost; + } +} diff --git "a/week16/Baekjoon_1916_\354\265\234\354\206\214\353\271\204\354\232\251\352\265\254\355\225\230\352\270\260.java" "b/week16/Baekjoon_1916_\354\265\234\354\206\214\353\271\204\354\232\251\352\265\254\355\225\230\352\270\260.java" new file mode 100644 index 0000000..f46c62e --- /dev/null +++ "b/week16/Baekjoon_1916_\354\265\234\354\206\214\353\271\204\354\232\251\352\265\254\355\225\230\352\270\260.java" @@ -0,0 +1,76 @@ +/* + * BOJ 1916번 : 최소비용 구하기 + * 메모리 : 51,844kb + * 시간 : 400ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1916_최소비용구하기 { + static int N, M; + static int S, E; + static int minCost; + static int[] dist; + static List[] buses; + static class Bus implements Comparable { + int end, cost; + public Bus(int end, int cost) { + this.end = end; + this.cost = cost; + } + @Override + public int compareTo(Bus o) { + return this.cost - o.cost; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + M = Integer.parseInt(br.readLine()); + buses = new ArrayList[N+1]; + for(int n = 1; n <= N; n++) { + buses[n] = new ArrayList<>(); + } + for(int m = 0; m < M; m++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int start = Integer.parseInt(st.nextToken()); + int end = Integer.parseInt(st.nextToken()); + int cost = Integer.parseInt(st.nextToken()); + buses[start].add(new Bus(end, cost)); + } + + StringTokenizer st = new StringTokenizer(br.readLine()); + S = Integer.parseInt(st.nextToken()); + E = Integer.parseInt(st.nextToken()); + + dist = new int[N+1]; + Arrays.fill(dist, Integer.MAX_VALUE); + dist[S] = 0; + + PriorityQueue pq = new PriorityQueue<>(); + pq.add(new Bus(S, 0)); + + while(!pq.isEmpty()) { + Bus bus = pq.poll(); + int curr = bus.end; + int cost = bus.cost; + + if(dist[curr] < cost) continue; + + for(Bus next : buses[curr]) { + if(dist[next.end] > dist[curr] + next.cost) { + dist[next.end] = dist[curr] + next.cost; + pq.offer(new Bus(next.end, dist[next.end])); + } + } + } + + minCost = dist[E]; + sb.append(minCost); + System.out.println(sb); + br.close(); + } +} diff --git "a/week16/Baekjoon_2096_\353\202\264\353\240\244\352\260\200\352\270\260.java" "b/week16/Baekjoon_2096_\353\202\264\353\240\244\352\260\200\352\270\260.java" new file mode 100644 index 0000000..f368124 --- /dev/null +++ "b/week16/Baekjoon_2096_\353\202\264\353\240\244\352\260\200\352\270\260.java" @@ -0,0 +1,52 @@ +/* + * BOJ2096번 : 내려가기 + * 메모리 : 54,320kb + * 시간 : 328ms + */ + +import java.io.*; +import java.util.*; + +public class BOJ2096_내려가기 { + static int N; + static int[][] arr; + static int[][] maxDp; + static int[][] minDp; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + arr = new int[N][3]; + maxDp = new int[N][3]; + minDp = new int[N][3]; + + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + for(int i = 0; i < 3; i++) { + arr[n][i] = Integer.parseInt(st.nextToken()); + } + } + + for(int i = 0; i < 3; i++) { + maxDp[0][i] = arr[0][i]; + minDp[0][i] = arr[0][i]; + } + + for(int n = 1; n < N; n++) { + maxDp[n][0] = Math.max(maxDp[n-1][0], maxDp[n-1][1]) + arr[n][0]; + maxDp[n][1] = Math.max(maxDp[n-1][0], Math.max(maxDp[n-1][1], maxDp[n-1][2])) + arr[n][1]; + maxDp[n][2] = Math.max(maxDp[n-1][1], maxDp[n-1][2]) + arr[n][2]; + + minDp[n][0] = Math.min(minDp[n-1][0], minDp[n-1][1]) + arr[n][0]; + minDp[n][1] = Math.min(minDp[n-1][0], Math.min(minDp[n-1][1], minDp[n-1][2])) + arr[n][1]; + minDp[n][2] = Math.min(minDp[n-1][1], minDp[n-1][2]) + arr[n][2]; + } + + sb.append(Math.max(maxDp[N-1][0], Math.max(maxDp[N-1][1], maxDp[N-1][2]))).append(" "); + sb.append(Math.min(minDp[N-1][0], Math.min(minDp[N-1][1], minDp[N-1][2]))); + + System.out.println(sb); + br.close(); + } +} diff --git "a/week16/Baekjoon_2573_\353\271\231\354\202\260.java" "b/week16/Baekjoon_2573_\353\271\231\354\202\260.java" new file mode 100644 index 0000000..87b8465 --- /dev/null +++ "b/week16/Baekjoon_2573_\353\271\231\354\202\260.java" @@ -0,0 +1,124 @@ +/* + * BOJ 2573번 : 빙산 + * 메모리 : 162,376kb + * 시간 : 500ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_2573_빙산 { + static int N, M; + static int[][] map; + static int[][] melt; + static boolean[][] visited; + static int year; + static int[] dx = new int[] { -1, 1, 0, 0 }; + static int[] dy = new int[] { 0, 0, -1, 1 }; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + map = new int[N][M]; + for(int n = 0; n < N; n++) { + st = new StringTokenizer(br.readLine()); + for(int m = 0; m < M; m++) { + map[n][m] = Integer.parseInt(st.nextToken()); + } + } + + while(true) { + int count = countIce(); + if(count >= 2) { + sb.append(year); + break; + } + if(count == 0) { + sb.append(0); + break; + } + + meltIce(); + year++; + } + + System.out.println(sb); + br.close(); + } + + // 1. 빙산 덩어리 개수 세기 + private static int countIce() { + boolean[][] visited = new boolean[N][M]; + int count = 0; + + for(int n = 0; n < N; n++) { + for(int m = 0; m < M; m++) { + if(map[n][m] > 0 && !visited[n][m]) { + bfs(n, m, visited); + count++; + } + } + } + + return count; + } + + // 2. 하나의 빙산 덩어리 탐색 + private static void bfs(int x, int y, boolean[][] visited) { + Queue q = new ArrayDeque(); + q.offer(new int[] { x, y }); + visited[x][y] = true; + + while(!q.isEmpty()) { + int[] curr = q.poll(); + int cx = curr[0]; + int cy = curr[1]; + + for(int d = 0; d < 4; d++) { + int nx = cx + dx[d]; + int ny = cy + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < N && ny < M && !visited[nx][ny] && map[nx][ny] > 0) { + visited[nx][ny] = true; + q.offer(new int[] { nx, ny }); + } + } + } + } + + // 3. 빙산 녹이기 + private static void meltIce() { + melt = new int[N][M]; // 녹을 양 저장 + + for(int n = 0; n < N; n++) { + for(int m = 0; m < M; m++) { + if(map[n][m] > 0) { // 빙산이 있는 칸 + int waterCount = 0; + for(int d = 0; d < 4; d++) { + int nx = n + dx[d]; + int ny = m + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < N && ny < M && map[nx][ny] == 0) { + waterCount++; // 주변이 물이면 카운트 증가 + } + } + melt[n][m] = waterCount; + } + } + } + + for(int n = 0; n < N; n++) { + for(int m = 0; m < M; m++) { + if(map[n][m] > 0) { + map[n][m] -= melt[n][m]; + if(map[n][m] < 0) + map[n][m] = 0; + } + } + } + } + +} diff --git "a/week16/Baekjoon_7662_\354\235\264\354\244\221\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220.java" "b/week16/Baekjoon_7662_\354\235\264\354\244\221\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220.java" new file mode 100644 index 0000000..2d8e6e8 --- /dev/null +++ "b/week16/Baekjoon_7662_\354\235\264\354\244\221\354\232\260\354\204\240\354\210\234\354\234\204\355\201\220.java" @@ -0,0 +1,59 @@ +/* + * BOJ 7662번 : 이중 우선순위 큐 + * 메모리 : 440,392kb + * 시간 : 2,412ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_7662_이중우선순위큐 { + static int T, K; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + T = Integer.parseInt(br.readLine()); + for(int t = 1; t <= T; t++) { + K = Integer.parseInt(br.readLine()); + // 숫자의 개수 저장 + TreeMap map = new TreeMap<>(); // O(logN) 정렬이 된다!!! + + for(int k = 0; k < K; k++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + String command = st.nextToken(); + int num = Integer.parseInt(st.nextToken()); + + switch(command) { + case "I" : + map.put(num, map.getOrDefault(num, 0)+1); // num이 존재하면 num 반환, 없다면 0 반환 + break; + case "D" : + if(!map.isEmpty()) { + int target = 0; + if(num == 1) { + target = map.lastKey(); + } else { + target = map.firstKey(); + } + + if(map.get(target)==1) { + map.remove(target); + } else { + map.put(target, map.get(target)-1); + } + } + break; + } + } + + if(map.isEmpty()) { + sb.append("EMPTY").append("\n"); + } else { + sb.append(map.lastKey()).append(" ").append(map.firstKey()).append("\n"); + } + } + System.out.print(sb); + br.close(); + } +} diff --git "a/week17/Baekjoon_1516_\352\262\214\354\236\204\352\260\234\353\260\234.java" "b/week17/Baekjoon_1516_\352\262\214\354\236\204\352\260\234\353\260\234.java" new file mode 100644 index 0000000..344bc02 --- /dev/null +++ "b/week17/Baekjoon_1516_\352\262\214\354\236\204\352\260\234\353\260\234.java" @@ -0,0 +1,61 @@ +/* + * BOJ 1516번 : 게임개발 + * 메모리 : 18,928kb + * 시간 : 156ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1516_게임개발 { + static int N; + static List[] preList; + static int[] buildTime; + static int[] dp; + static boolean[] visited; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + + preList = new ArrayList[N+1]; + buildTime = new int[N+1]; + dp = new int[N+1]; + visited = new boolean[N+1]; + + for(int n = 1; n <= N; n++) { + preList[n] = new ArrayList<>(); + } + + for(int n = 1; n <= N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + buildTime[n] = Integer.parseInt(st.nextToken()); + + while(true) { + int pre = Integer.parseInt(st.nextToken()); + if(pre == -1) break; + preList[n].add(pre); // n을 짓기 전에 pre를 지어야 함 + } + } + + for(int n = 1; n <= N; n++) { + sb.append(dfs(n)).append("\n"); + } + System.out.println(sb); + br.close(); + } + + public static int dfs(int n) { + if(visited[n]) return dp[n]; // 이미 계산한 경우 + visited[n] = true; + + int maxPreTime = 0; + for(int pre : preList[n]) { + maxPreTime = Math.max(maxPreTime, dfs(pre)); + } + + dp[n] = maxPreTime + buildTime[n]; + return dp[n]; + } +} diff --git "a/week17/Baekjoon_17182_\354\232\260\354\243\274\355\203\220\354\202\254\354\204\240.java" "b/week17/Baekjoon_17182_\354\232\260\354\243\274\355\203\220\354\202\254\354\204\240.java" new file mode 100644 index 0000000..20fb524 --- /dev/null +++ "b/week17/Baekjoon_17182_\354\232\260\354\243\274\355\203\220\354\202\254\354\204\240.java" @@ -0,0 +1,63 @@ +/* + * BOJ 17182번 : 우주 탐사선 + * 메모리 : 12,084kb + * 시간 : 100ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_17182_우주탐사선 { + static int N, K; + static int[][] time; + static boolean[] visited; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + K = Integer.parseInt(st.nextToken()); + time = new int[N][N]; + + for(int i = 0; i < N; i++) { + st = new StringTokenizer(br.readLine()); + for(int j = 0; j < N; j++) { + time[i][j] = Integer.parseInt(st.nextToken()); + } + } + + for(int i = 0; i < N; i++) { + for(int j = 0; j < N; j++) { + for(int k = 0; k < N; k++) { + time[i][j] = Math.min(time[i][j], time[i][k] + time[k][j]); + } + } + } + + visited = new boolean[N]; + visited[K] = true; + answer = Integer.MAX_VALUE; + dfs(K, 1, 0); // start, count, totalTime + + sb.append(answer); + System.out.println(sb); + br.close(); + } + + public static void dfs(int curr, int count, int totalTime) { + if(count == N) { + answer = Math.min(answer, totalTime); + return; + } + + for(int next = 0; next < N; next++) { + if(!visited[next]) { + visited[next] = true; + dfs(next, count+1, totalTime+time[curr][next]); + visited[next] = false; + } + } + } +} diff --git "a/week17/Baekjoon_21939_\353\254\270\354\240\234\354\266\224\354\262\234\354\213\234\354\212\244\355\205\234Version1.java" "b/week17/Baekjoon_21939_\353\254\270\354\240\234\354\266\224\354\262\234\354\213\234\354\212\244\355\205\234Version1.java" new file mode 100644 index 0000000..26d8966 --- /dev/null +++ "b/week17/Baekjoon_21939_\353\254\270\354\240\234\354\266\224\354\262\234\354\213\234\354\212\244\355\205\234Version1.java" @@ -0,0 +1,68 @@ +/* + * BOJ 21939번 : 문제 추천 시스템 Version 1 + * 메모리 : 52,688kb + * 시간 : 472ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_21939_문제추천시스템Version1 { + static TreeSet treeSet = new TreeSet(); + static Map levelMap = new HashMap<>(); + static class Node implements Comparable { + int num; + int level; + public Node(int num, int level) { + this.num = num; + this.level = level; + } + + @Override + public int compareTo(Node o) { + if(this.level == o.level) return this.num - o.num; + return this.level - o.level; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + int N = Integer.parseInt(br.readLine()); + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int P = Integer.parseInt(st.nextToken()); + int L = Integer.parseInt(st.nextToken()); + treeSet.add(new Node(P, L)); + levelMap.put(P, L); + } + + int M = Integer.parseInt(br.readLine()); + for(int m = 0; m < M; m++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + String cmd = st.nextToken(); + switch(cmd) { + case "add": + int P = Integer.parseInt(st.nextToken()); + int L = Integer.parseInt(st.nextToken()); + treeSet.add(new Node(P, L)); + levelMap.put(P, L); + break; + case "recommend": + int x = Integer.parseInt(st.nextToken()); + if(x == 1) sb.append(treeSet.last().num).append("\n"); + else sb.append(treeSet.first().num).append("\n"); + break; + case "solved": + int removeP = Integer.parseInt(st.nextToken()); + int removeL = levelMap.get(removeP); + treeSet.remove(new Node(removeP, removeL)); + levelMap.remove(removeP); + break; + } + } + + System.out.println(sb); + br.close(); + } +} diff --git "a/week17/Baekjoon_2357_\354\265\234\354\206\237\352\260\222\352\263\274\354\265\234\353\214\223\352\260\222.java" "b/week17/Baekjoon_2357_\354\265\234\354\206\237\352\260\222\352\263\274\354\265\234\353\214\223\352\260\222.java" new file mode 100644 index 0000000..1a49f05 --- /dev/null +++ "b/week17/Baekjoon_2357_\354\265\234\354\206\237\352\260\222\352\263\274\354\265\234\353\214\223\352\260\222.java" @@ -0,0 +1,118 @@ +/* + * BOJ 2357번 : 최소값과 최댓값 + * 메모리 : 62,348kb + * 시간 : 536ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_2357_최솟값과최댓값 { + static int N, M; + static int[] input; + static int[] minTree, maxTree; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + + input = new int[N]; + for(int n = 0; n < N; n++) { + input[n] = Integer.parseInt(br.readLine()); + } + + // 세그먼트 트리의 크기 = 2 * 2^k (k는 N 이상의 최소 2의 제곱수 + int treeSize = 1; + while(treeSize < N) treeSize *= 2; // 가장 가까운 2의 제곱수 + treeSize *= 2; // 전체 트리 배열 크기 설정 + + minTree = new int[treeSize]; + maxTree = new int[treeSize]; + + // 트리 생성 + buildMinTree(1, 0, N-1); // node, start, end + buildMaxTree(1, 0, N-1); // node, start, end + + for(int m = 0; m < M; m++) { + st = new StringTokenizer(br.readLine()); + int left = Integer.parseInt(st.nextToken())-1; + int right = Integer.parseInt(st.nextToken())-1; + + // 해당 구간의 최소값, 최대값 찾기 + int minValue = queryMin(1, 0, N-1, left, right); // node, start, end, left, right + int maxValue = queryMax(1, 0, N-1, left, right); // node, start, end, left, right + + sb.append(minValue).append(" ").append(maxValue).append("\n"); + } + + System.out.println(sb); + br.close(); + } + + static void buildMinTree(int node, int start, int end) { + if(start == end) { + // 1. 리프 노드일 경우 + minTree[node] = input[start]; + } else { + int mid = (start + end) / 2; + // 2. 왼쪽 자식 트리 생성 + buildMinTree(node*2, start, mid); + // 3. 오른쪽 자식 트리 생성 + buildMinTree(node*2+1, mid+1, end); + // 4. 현재 노드에 왼쪽과 오른쪽 중 최소값 저장 + minTree[node] = Math.min(minTree[node*2], minTree[node*2+1]); + } + } + + static void buildMaxTree(int node, int start, int end) { + if(start == end) { + // 1. 리프 노드일 경우 + maxTree[node] = input[start]; + } else { + int mid = (start + end) / 2; + // 2. 왼쪽 자식 트리 생성 + buildMaxTree(node*2, start, mid); + // 3. 오른쪽 자식 트리 생성 + buildMaxTree(node*2+1, mid+1, end); + // 4. 현재 노드에 왼쪽과 오른쪽 중 최대값 저장 + maxTree[node] = Math.max(maxTree[node*2], maxTree[node*2+1]); + } + } + + static int queryMin(int node, int start, int end, int left, int right) { + if(right < start || end < left) { + // 현재 노드의 구간이 [left, right] 와 겹치지 않으면 큰 값 리턴 + return Integer.MAX_VALUE; + } + if(left <= start && end <= right) { + // 현재 노드의 구간이 [left, right] 에 완전히 포함되면 값 리턴 + return minTree[node]; + } + + // 일부만 겹칠 경우 왼쪽, 오른쪽 자식 쿼리 후 최소값 선택 + int mid = (start + end) / 2; + int leftMin = queryMin(node*2, start, mid, left, right); + int rightMin = queryMin(node*2+1, mid+1, end, left, right); + return Math.min(leftMin, rightMin); + } + + static int queryMax(int node, int start, int end, int left, int right) { + if(right < start || end < left) { + // 현재 노드의 구간이 [left, right] 와 겹치지 않으면 작은 값 리턴 + return Integer.MIN_VALUE; + } + if(left <= start && end <= right) { + // 현재 노드의 구간이 [left, right] 에 완전히 포함되면 값 리턴 + return maxTree[node]; + } + + // 일부만 겹칠 경우 왼쪽, 오른쪽 자식 쿼리 후 최소값 선택 + int mid = (start + end) / 2; + int leftMax = queryMax(node*2, start, mid, left, right); + int rightMax = queryMax(node*2+1, mid+1, end, left, right); + return Math.max(leftMax, rightMax); + } +} diff --git "a/week17/Baekjoon_2812_\355\201\254\352\262\214\353\247\214\353\223\244\352\270\260.java" "b/week17/Baekjoon_2812_\355\201\254\352\262\214\353\247\214\353\223\244\352\270\260.java" new file mode 100644 index 0000000..a573249 --- /dev/null +++ "b/week17/Baekjoon_2812_\355\201\254\352\262\214\353\247\214\353\223\244\352\270\260.java" @@ -0,0 +1,42 @@ +/* + * BOJ 2812번 : 크게 만들기 + * 메모리 : 19,640kb + * 시간 : 176ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_2812_크게만들기 { + static int N, K; + static char[] arr; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + K = Integer.parseInt(st.nextToken()); + arr = new char[N]; + + String str = br.readLine(); + int top = -1; + int count = K; + + for(int n = 0; n < N; n++) { + char curr = str.charAt(n); + while(top >= 0 && count > 0 && arr[top] < curr) { + top--; + count--; + } + arr[++top] = curr; + } + + for(int i = 0; i <= top-count; i++) { + sb.append(arr[i]); + } + + System.out.println(sb); + br.close(); + } +} diff --git "a/week18/Baekjoon_17619_\352\260\234\352\265\254\353\246\254\354\240\220\355\224\204.java" "b/week18/Baekjoon_17619_\352\260\234\352\265\254\353\246\254\354\240\220\355\224\204.java" new file mode 100644 index 0000000..952f26e --- /dev/null +++ "b/week18/Baekjoon_17619_\352\260\234\352\265\254\353\246\254\354\240\220\355\224\204.java" @@ -0,0 +1,73 @@ +/* + * BOJ 17619번 : 개구리 점프 + * 메모리 : 91,204kb + * 시간 : 1,080ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_17619_개구리점프 { + static int N, Q; + static Tree[] trees; + static class Tree implements Comparable { + int idx, start, end, groupNum; + Tree(int idx, int start, int end) { + this.idx = idx; + this.start = start; + this.end = end; + } + + @Override + public int compareTo(Tree o) { + return this.start - o.start; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + Q = Integer.parseInt(st.nextToken()); + trees = new Tree[N]; + for(int n = 0; n < N; n++) { + st = new StringTokenizer(br.readLine()); + int x1 = Integer.parseInt(st.nextToken()); + int x2 = Integer.parseInt(st.nextToken()); + int y = Integer.parseInt(st.nextToken()); + trees[n] = new Tree(n+1, x1, x2); + } + + Arrays.sort(trees); + + int lastEnd = trees[0].start; + int group = 1; + + for(int n = 0; n < N; n++) { + if(lastEnd < trees[n].start) { + group++; + } + + lastEnd = Math.max(lastEnd, trees[n].end); + trees[n].groupNum = group; + } + + // Arrays.sort(trees, Comparator.comparingInt(o -> o.idx)); + Arrays.sort(trees, (a, b) -> Integer.compare(a.idx, b.idx)); + + for(int q = 0; q < Q; q++) { + st = new StringTokenizer(br.readLine()); + int q1 = Integer.parseInt(st.nextToken()); + int q2 = Integer.parseInt(st.nextToken()); + if(trees[q1-1].groupNum == trees[q2-1].groupNum) { + sb.append(1).append("\n"); + } else { + sb.append(0).append("\n"); + } + } + + System.out.println(sb); + br.close(); + } +} diff --git "a/week18/Baekjoon_2011_\354\225\224\355\230\270\354\275\224\353\223\234.java" "b/week18/Baekjoon_2011_\354\225\224\355\230\270\354\275\224\353\223\234.java" new file mode 100644 index 0000000..774f96f --- /dev/null +++ "b/week18/Baekjoon_2011_\354\225\224\355\230\270\354\275\224\353\223\234.java" @@ -0,0 +1,65 @@ +/* + * BOJ 2011번 : 암호코드 + * 메모리 : 12,600kb + * 시간 : 68ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_2011_암호코드 { + static String password; + static int count; + static int[] memo; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + password = br.readLine(); + memo = new int[password.length()]; + Arrays.fill(memo, -1); + + if(password.charAt(0) == '0') { + sb.append(0); + System.out.print(sb); + br.close(); + return; + } + + count = dfs(0); + sb.append(count); + System.out.print(sb); + br.close(); + } + + public static int dfs(int index) { + if(index == password.length()) { + return 1; + } + + if(memo[index] != -1) { + return memo[index]; + } + + int count = 0; + + // 1. 한자리 숫자 암호 + int one = password.charAt(index) - '0'; + if(one >= 1 && one <= 9) { + count += dfs(index+1); + count %= 1000000; + } + + // 2. 두자리 숫자 암호 + if(index+1 < password.length()) { + int two = Integer.parseInt(password.substring(index, index+2)); + if(two >= 10 && two <= 26) { + count += dfs(index+2); + count %= 1000000; + } + } + + memo[index] = count; + return count; + } +} diff --git "a/week18/Baekjoon_20159_\353\217\231\354\236\221\352\267\270\353\247\214\353\260\221\354\236\245\353\271\274\352\270\260\353\203\220.java" "b/week18/Baekjoon_20159_\353\217\231\354\236\221\352\267\270\353\247\214\353\260\221\354\236\245\353\271\274\352\270\260\353\203\220.java" new file mode 100644 index 0000000..6765fb0 --- /dev/null +++ "b/week18/Baekjoon_20159_\353\217\231\354\236\221\352\267\270\353\247\214\353\260\221\354\236\245\353\271\274\352\270\260\353\203\220.java" @@ -0,0 +1,47 @@ +/* + * BOJ 20159번 : 동작 그만. 밑장 빼기냐? + * 메모리 : 23,040kb + * 시간 : 212ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_20159_동작그만밑장빼기냐 { + static int N; + static int[] player1; + static int[] player2; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + player1 = new int[N/2+1]; + player2 = new int[N/2+1]; + + // 카드 입력 누적함 + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 1; n <= N/2; n++) { + player1[n] = player1[n-1] + Integer.parseInt(st.nextToken()); + player2[n] = player2[n-1] + Integer.parseInt(st.nextToken()); + } + + int answer = player1[N/2]; + int sum = 0; + for(int n = 0; n < N; n++) { + // 정훈이 차례에서 밑장 빼기 + if (n % 2 == 0) { + sum = player1[n / 2] + (player2[N / 2] - player2[n / 2]); + } + // 상대방 차례에서 밑장 빼기 + else { + sum = player1[n / 2 + 1] + (player2[N / 2 - 1] - player2[n / 2]); + } + answer = Math.max(answer, sum); + } + + sb.append(answer); + System.out.print(sb); + br.close(); + } +} diff --git "a/week18/Baekjoon_2170_\354\204\240\352\270\213\352\270\260.java" "b/week18/Baekjoon_2170_\354\204\240\352\270\213\352\270\260.java" new file mode 100644 index 0000000..c649a50 --- /dev/null +++ "b/week18/Baekjoon_2170_\354\204\240\352\270\213\352\270\260.java" @@ -0,0 +1,64 @@ +/* + * BOJ 2170번 : 선 긋기 + * 메모리 : 325,556kb + * 시간 : 1,196ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_2170_선긋기 { + static int N; + static class Line implements Comparable { + int start, end; + + public Line(int start, int end) { + this.start = start; + this.end = end; + } + + @Override + public int compareTo(Line o) { + return this.start - o.start; + } + } + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + + List lines = new ArrayList<>(); + + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int start = Integer.parseInt(st.nextToken()); + int end = Integer.parseInt(st.nextToken()); + lines.add(new Line(start, end)); + } + + Collections.sort(lines); + + int answer = 0; + int start = lines.get(0).start; + int end = lines.get(0).end; + + for(int n = 1; n < lines.size(); n++) { + Line curr = lines.get(n); + + if(curr.start > end) { + answer += end-start; + start = curr.start; + end = curr.end; + } else { + end = Math.max(end, curr.end); + } + } + + answer += end-start; + sb.append(answer); + System.out.println(sb); + br.close(); + } +} diff --git "a/week18/Baekjoon_9466_\355\205\200\355\224\204\353\241\234\354\240\235\355\212\270.java" "b/week18/Baekjoon_9466_\355\205\200\355\224\204\353\241\234\354\240\235\355\212\270.java" new file mode 100644 index 0000000..fe2e97e --- /dev/null +++ "b/week18/Baekjoon_9466_\355\205\200\355\224\204\353\241\234\354\240\235\355\212\270.java" @@ -0,0 +1,65 @@ +/* + * BOJ 9466번 : 텀 프로젝트 + * 메모리 : 302,760kb + * 시간 : 1,104ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_9466_텀프로젝트 { + static int T, N; + static int[] students; + static boolean[] visited, team; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + T = Integer.parseInt(br.readLine()); + for(int t = 1; t <= T; t++) { + N = Integer.parseInt(br.readLine()); + StringTokenizer st = new StringTokenizer(br.readLine()); + students = new int[N+1]; + visited = new boolean[N+1]; + team = new boolean[N+1]; + answer = N; + + for(int n = 1; n <= N; n++) { + students[n] = Integer.parseInt(st.nextToken()); + if(students[n] == n) { + team[n] = true; + visited[n] = true; + answer--; + } + } + + for(int n = 1; n <= N; n++) { + if(!team[n]) { + dfs(n); + } + } + + sb.append(answer).append("\n"); + } + System.out.println(sb); + br.close(); + } + + public static void dfs(int student) { + if(team[student]) { + return; + } + + if(visited[student]) { + answer--; + team[student] = true; + } + + visited[student] = true; + dfs(students[student]); + visited[student] = false; + + team[student] = true; + } +} diff --git "a/week19/Baekjoon_1083_\354\206\214\355\212\270.java" "b/week19/Baekjoon_1083_\354\206\214\355\212\270.java" new file mode 100644 index 0000000..9ec1ac0 --- /dev/null +++ "b/week19/Baekjoon_1083_\354\206\214\355\212\270.java" @@ -0,0 +1,58 @@ +/* + * BOJ 1083번 : 소트 + * 메모리 : 11596kb + * 시간 : 68ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1083_소트 { + static int N, S; + static int[] A; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + A = new int[N]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + } + S = Integer.parseInt(br.readLine()); + + // 정렬 + for(int i = 0; i < N && S > 0; i++) { + // 최대 교환 가능 범위 내에서 가장 큰 값 찾기 + int maxIdx = i; + for(int j = i+1; j < N && j <= i+S; j++) { + if(A[maxIdx] < A[j]) { + maxIdx = j; // 가장 큰 수의 인덱스 + } + } + + // 큰 수를 앞으로 땡겨오는데 필요한 swap 횟수만큼 빼기 + S -= (maxIdx-i); + + // 가장 큰 값이 현재 위치에 오도록 swap + // 오른쪽에서 왼쪽으로 swap + for(int k = maxIdx; k > i; k--) { + swap(A, k, k-1); + } + } + + for(int n = 0; n < N; n++) { + sb.append(A[n]).append(" "); + } + + System.out.println(sb); + br.close(); + } + + public static void swap(int[] A, int x, int y) { + int temp = A[x]; + A[x] = A[y]; + A[y] = temp; + } +} diff --git "a/week19/Baekjoon_14442_\353\262\275\353\266\200\354\210\230\352\263\240\354\235\264\353\217\231\355\225\230\352\270\2602.java" "b/week19/Baekjoon_14442_\353\262\275\353\266\200\354\210\230\352\263\240\354\235\264\353\217\231\355\225\230\352\270\2602.java" new file mode 100644 index 0000000..1a87476 --- /dev/null +++ "b/week19/Baekjoon_14442_\353\262\275\353\266\200\354\210\230\352\263\240\354\235\264\353\217\231\355\225\230\352\270\2602.java" @@ -0,0 +1,82 @@ +/* + * BOJ 14442번 : 벽 부수고 이동하기 2 + * 메모리 : 336,504kb + * 시간 : 1,760ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_14442_벽부수고이동하기2 { + static int N, M, K; + static int[][] map; + static int[] dx = { -1, 1, 0, 0 }; + static int[] dy = { 0, 0, -1, 1 }; + static boolean[][][] visited; + static int answer = Integer.MAX_VALUE; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + 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+1][M+1]; + visited = new boolean[N+1][M+1][K+1]; + for(int n = 1; n <= N; n++) { + String line = br.readLine(); + for(int m = 1; m <= M; m++) { + map[n][m] = line.charAt(m-1)-'0'; + } + } + + bfs(); + + if(answer == Integer.MAX_VALUE) { + sb.append(-1); + } else { + sb.append(answer); + } + + System.out.println(sb); + br.close(); + } + + public static void bfs() { + Queue q = new ArrayDeque<>(); + q.add(new int[] { 1, 1, 0 }); // x, y, 부순 벽 수 + visited[1][1][0] = true; + int distance = 1; + + while(!q.isEmpty()) { + int size = q.size(); + for(int s = 0; s < size; s++) { + int[] curr = q.poll(); + + if(curr[0] == N && curr[1] == M) { + answer = distance; + return; + } + + for(int d = 0; d < 4; d++) { + int nx = curr[0]+dx[d]; + int ny = curr[1]+dy[d]; + + if(nx < 1 || ny < 1 || nx > N || ny > M) continue; + + if(map[nx][ny] == 0 && !visited[nx][ny][curr[2]]) { + visited[nx][ny][curr[2]] = true; + q.add(new int[] { nx, ny, curr[2] }); + } + + if(curr[2] < K && map[nx][ny] == 1 && !visited[nx][ny][curr[2]+1]){ + visited[nx][ny][curr[2]+1] = true; + q.add(new int[] { nx, ny, curr[2]+1 }); + } + } + } + distance++; + } + } +} diff --git "a/week19/Baekjoon_1939_\354\244\221\353\237\211\354\240\234\355\225\234.java" "b/week19/Baekjoon_1939_\354\244\221\353\237\211\354\240\234\355\225\234.java" new file mode 100644 index 0000000..f7b8b20 --- /dev/null +++ "b/week19/Baekjoon_1939_\354\244\221\353\237\211\354\240\234\355\225\234.java" @@ -0,0 +1,97 @@ +/* + * BOJ 1939번 : 중량제한 + * 메모리 : 59,436kb + * 시간 : 456ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1939_중량제한 { + static int N, M, A, B, C; + static int start, end; + static boolean[] visited; + static List[] graph; + static class Edge { + int to; + int weight; + + Edge(int to, int weight) { + this.to = to; + this.weight = weight; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + + graph = new ArrayList[N+1]; + for(int n = 1; n <= N; n++) { + graph[n] = new ArrayList<>(); + } + + int maxWeight = 0; + + for(int m = 0; m < M; m++) { + st = new StringTokenizer(br.readLine()); + A = Integer.parseInt(st.nextToken()); + B = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + + graph[A].add(new Edge(B, C)); + graph[B].add(new Edge(A, C)); + + maxWeight = Math.max(maxWeight, C); + } + + st = new StringTokenizer(br.readLine()); + start = Integer.parseInt(st.nextToken()); + end = Integer.parseInt(st.nextToken()); + + int left = 1; + int right = maxWeight; + int answer = 0; + + while(left <= right) { + int mid = (left+right)/2; + visited = new boolean[N+1]; + if(bfs(mid)) { + answer = mid; + left = mid+1; + } else { + right = mid-1; + } + } + + sb.append(answer); + System.out.println(sb); + } + + // 현재 중량으로 이동 가능한지 확인 + public static boolean bfs(int weight) { + Queue q = new ArrayDeque<>(); + q.add(start); + visited[start] = true; + + while(!q.isEmpty()) { + int curr = q.poll(); + + if(curr==end) { + return true; + } + + for(Edge next : graph[curr]) { + if(!visited[next.to] && next.weight >= weight) { + visited[next.to] = true; + q.add(next.to); + } + } + } + + return false; + } +} diff --git "a/week20/Baekjoon_1464_\353\222\244\354\247\221\352\270\2603.java" "b/week20/Baekjoon_1464_\353\222\244\354\247\221\352\270\2603.java" new file mode 100644 index 0000000..d65bdb3 --- /dev/null +++ "b/week20/Baekjoon_1464_\353\222\244\354\247\221\352\270\2603.java" @@ -0,0 +1,30 @@ +/* + * BOJ 1464번 : 뒤집기 3 + * 메모리 : 11,524kb + * 시간 : 68ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1464_뒤집기3 { + static String S = ""; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + S = br.readLine(); + sb.append(S.charAt(0)); + + for(int s = 1; s < S.length(); s++) { + if(S.charAt(s) <= sb.charAt(0)) { + sb.insert(0, S.charAt(s)); + } else { + sb.append(S.charAt(s)); + } + } + + System.out.println(sb); + br.close(); + } +} diff --git "a/week20/Baekjoon_1477_\355\234\264\352\262\214\354\206\214\354\204\270\354\232\260\352\270\260.java" "b/week20/Baekjoon_1477_\355\234\264\352\262\214\354\206\214\354\204\270\354\232\260\352\270\260.java" new file mode 100644 index 0000000..6b94119 --- /dev/null +++ "b/week20/Baekjoon_1477_\355\234\264\352\262\214\354\206\214\354\204\270\354\232\260\352\270\260.java" @@ -0,0 +1,55 @@ +/* + * BOJ 1477번 : 휴게소 세우기 + * 메모리 : 11,624kb + * 시간 : 80ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_1477_휴게소세우기 { + static int N, M, L; + static int[] arr; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + L = Integer.parseInt(st.nextToken()); + + arr = new int[N+2]; + st = new StringTokenizer(br.readLine()); + for(int n = 1; n <= N; n++) { + arr[n] = Integer.parseInt(st.nextToken()); + } + arr[N+1] = L; + + Arrays.sort(arr); + + int left = 1; + int right = L; + while(left <= right) { + int mid = (left+right)/2; + int count = 0; + + for(int n = 1; n <= N+1; n++){ + int distance = arr[n] - arr[n-1]; + count += (distance-1)/mid; + } + + if(count > M) { + left = mid+1; + } else { + answer = mid; + right = mid-1; + } + } + + sb.append(answer); + System.out.println(sb); + br.close(); + } +} diff --git "a/week20/Baekjoon_4179_\353\266\210.java" "b/week20/Baekjoon_4179_\353\266\210.java" new file mode 100644 index 0000000..420dcd0 --- /dev/null +++ "b/week20/Baekjoon_4179_\353\266\210.java" @@ -0,0 +1,104 @@ +/* + * BOJ 4179번 : 불 + * 메모리 : 55,572kb + * 시간 : 436ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon_4179_불 { + static int R, C; + static char[][] map; + static int[][] fire; + static int[][] jihun; + static boolean[][] fireVisited; + static boolean[][] jihunVisited; + static int minTime = Integer.MAX_VALUE; + static int[] dx = { 0, 0, -1, 1 }; + static int[] dy = { 1, -1, 0, 0 }; + static Queue fireQueue = new ArrayDeque<>(); + static Queue jihunQueue = new ArrayDeque<>(); + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + R = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + map = new char[R][C]; + fire = new int[R][C]; + jihun = new int[R][C]; + fireVisited = new boolean[R][C]; + jihunVisited = new boolean[R][C]; + for (int r = 0; r < R; r++) { + String line = br.readLine(); + for (int c = 0; c < C; c++) { + map[r][c] = line.charAt(c); + + if(map[r][c] == 'F') { + fireQueue.offer(new int[] { r, c }); + fireVisited[r][c] = true; + } + + if(map[r][c] == 'J') { + jihunQueue.offer(new int[] { r, c }); + jihunVisited[r][c] = true; + } + } + } + + fireBfs(); + jihunBfs(); + + if(minTime == Integer.MAX_VALUE) { + sb.append("IMPOSSIBLE"); + } else { + sb.append(minTime); + } + System.out.println(sb); + br.close(); + } + + public static void fireBfs() { + while(!fireQueue.isEmpty()) { + int[] curr = fireQueue.poll(); + + for(int d = 0; d < 4; d++) { + int nr = curr[0] + dx[d]; + int nc = curr[1] + dy[d]; + + if(nr < 0 || nc < 0 || nr >= R || nc >= C || map[nr][nc] == '#' || fireVisited[nr][nc]) continue; + + fireVisited[nr][nc] = true; + fire[nr][nc] = fire[curr[0]][curr[1]]+1; + fireQueue.offer(new int[] { nr, nc }); + } + } + } + + public static void jihunBfs() { + while(!jihunQueue.isEmpty()) { + int[] curr = jihunQueue.poll(); + + if(curr[0] == 0 || curr[1] == 0 || curr[0] == R-1 || curr[1] == C-1) { + minTime = Math.min(minTime, jihun[curr[0]][curr[1]]+1); + return; + } + + for(int d = 0; d < 4; d++) { + int nr = curr[0] + dx[d]; + int nc = curr[1] + dy[d]; + + if(nr < 0 || nc < 0 || nr >= R || nc >= C || map[nr][nc] == '#' || jihunVisited[nr][nc]) continue; + + // 불이 이미 온 경우 막기 + if(fire[nr][nc] <= jihun[curr[0]][curr[1]]+1 && fireVisited[nr][nc]) continue; + + jihunVisited[nr][nc] = true; + jihun[nr][nc] = jihun[curr[0]][curr[1]]+1; + jihunQueue.offer(new int[] { nr, nc }); + } + } + } +} diff --git a/week5/Baekjoon1038.java b/week5/Baekjoon1038.java index 150a6ca..0d089a7 100644 --- a/week5/Baekjoon1038.java +++ b/week5/Baekjoon1038.java @@ -1,7 +1,47 @@ +/* + * 백준 1038번 : 감소하는 수 + * 메모리 : 11,660kb + * 시간 : 72ms + */ -public class Main { +package algorithm; - public static void main(String[] args) { +import java.io.*; +import java.util.*; + +public class Baekjoon1038 { + static int N; + static List numList; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); // N번째 감소하는 수 + numList = new ArrayList(); + + if(N > 1022) { + System.out.println(-1); + return; + } + + for(int i = 0; i <= 9; i++) { + dfs(i); + } + + Collections.sort(numList); + sb.append(numList.get(N)); + System.out.println(sb); + br.close(); + } + + private static void dfs(long num) { + numList.add(num); + + long lastNum = num%10; + + for(long i = lastNum-1; i >= 0; i--) { + dfs(num*10 + i); + } } } diff --git a/week5/Baekjoon16953.java b/week5/Baekjoon16953.java index 150a6ca..d4ae176 100644 --- a/week5/Baekjoon16953.java +++ b/week5/Baekjoon16953.java @@ -1,7 +1,45 @@ +/* + * 백준 16953번 : A->B + * 메모리 : 11,532kb + * 시간 : 68ms + */ -public class Main { +package algorithm; - public static void main(String[] args) { +import java.io.*; +import java.util.*; + +public class Baekjoon16953 { + static int A, B; + static int minCnt; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + A = Integer.parseInt(st.nextToken()); + B = Integer.parseInt(st.nextToken()); + + minCnt = 1; + while(B>A){ + if(B%2 == 0) { + B /= 2; + } else if(B%10 == 1) { + B /= 10; + } else { // 끝자리가 1이 아닌 홀수일 때 탈출 + minCnt = -1; + break; + } + minCnt++; + } + + if(B==A) { + sb.append(minCnt); + } else { + sb.append(-1); + } + System.out.println(sb); + br.close(); } } diff --git a/week5/Baekjoon1715.java b/week5/Baekjoon1715.java index 150a6ca..70687f3 100644 --- a/week5/Baekjoon1715.java +++ b/week5/Baekjoon1715.java @@ -1,7 +1,44 @@ +/* + * 백준 1715번 : 카드 정렬하기 + * 메모리 : 25,092kb + * 시간 : 308ms + * + * 그리디 + * 가장 작은 두 묶음을 먼저 합쳐야 최소 비교 횟수가 나온다 + */ -public class Main { +package algorithm; - public static void main(String[] args) { +import java.io.*; +import java.util.*; + +public class Baekjoon1715 { + static int N; + static PriorityQueue pq; + static int minSum; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + pq = new PriorityQueue(); + minSum = 0; + for(int n = 0; n < N; n++) { + pq.offer(Integer.parseInt(br.readLine())); + } + + while(pq.size() > 1) { + int a = pq.poll(); + int b = pq.poll(); + + int sum = a+b; + minSum += sum; + + pq.offer(sum); + } + sb.append(minSum); + System.out.print(sb); + br.close(); } } diff --git a/week5/Baekjoon1931.java b/week5/Baekjoon1931.java index 150a6ca..8098fa3 100644 --- a/week5/Baekjoon1931.java +++ b/week5/Baekjoon1931.java @@ -1,7 +1,41 @@ +package algorithm; +import java.io.*; +import java.util.*; -public class Main { +public class Baekjoon1931 { + static int N; + static int[][] time; + static int cnt = 0; - public static void main(String[] args) { + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + time = new int[N][2]; + for(int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + time[n][0] = Integer.parseInt(st.nextToken()); + time[n][1] = Integer.parseInt(st.nextToken()); + } + + Arrays.sort(time, (o1, o2) -> { + if(o1[1]==o2[1]) + return o1[0]-o2[0]; + else + return o1[1]-o2[1]; + }); +// System.out.print(Arrays.deepToString(time)); + + int end = 0; + for(int n = 0; n < N; n++) { + if(time[n][0] >= end) { + cnt++; + end = time[n][1]; + } + } + + System.out.print(cnt); } -} + +} \ No newline at end of file diff --git a/week5/Baekjoon1987.java b/week5/Baekjoon1987.java index 150a6ca..a1ec6c7 100644 --- a/week5/Baekjoon1987.java +++ b/week5/Baekjoon1987.java @@ -1,7 +1,51 @@ +package algorithm; +import java.io.*; +import java.util.*; -public class Main { +public class Baekjoon1987 { + static int R, C; + static char[][] board; + static boolean[] alpha; + static int max; + static int[] dx = new int[] { -1, 1, 0, 0 }; + static int[] dy = new int[] { 0, 0, -1, 1 }; - public static void main(String[] args) { + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + R = Integer.parseInt(st.nextToken()); + C = Integer.parseInt(st.nextToken()); + board = new char[R][C]; + alpha = new boolean[26]; + for(int r = 0; r < R; r++) { + String str = br.readLine(); + for(int c = 0; c < C; c++) { + board[r][c] = str.charAt(c); + } + } + max = Integer.MIN_VALUE; +// System.out.println(board[0][0]-65); + dfs(0, 0, 1); + + sb.append(max); + System.out.print(sb); + br.close(); + } + + private static void dfs(int x, int y, int len) { + alpha[board[x][y]-65] = true; + max = Math.max(max, len); + + for(int d = 0; d < 4; d++) { + int nx = x + dx[d]; + int ny = y + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < R && ny < C && !alpha[board[nx][ny]-65]) { + dfs(nx, ny, len+1); + alpha[board[nx][ny]-65] = false; + } + } } } diff --git a/week5/Baekjoon22856.java b/week5/Baekjoon22856.java index 150a6ca..77268c4 100644 --- a/week5/Baekjoon22856.java +++ b/week5/Baekjoon22856.java @@ -1,7 +1,85 @@ +/* + * 백준 22856번 : 트리 순회 + * 메모리 : 63,744kb + * 시간 : 392ms + */ -public class Main { +package algorithm; - public static void main(String[] args) { +import java.io.*; +import java.util.*; + +public class Baekjoon22856 { + static int N; + static Node[] node; + static int cnt; + static int lastNode; + + static class Node { + int left, right; + public Node(int left, int right) { + this.left = left; + this.right = right; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + node = new Node[N+1]; + for (int i = 1; i <= N; i++) { + node[i] = new Node(-1, -1); + } + + for (int n = 0; n < N; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int c = Integer.parseInt(st.nextToken()); + node[a] = new Node(b, c); + } + + inOrder(1); + search(1); + + sb.append(cnt); + System.out.print(sb); + br.close(); + } + + // 마지막 노드 찾기 + private static void inOrder(int idx) { + if (node[idx].left != -1) { + inOrder(node[idx].left); + } + lastNode = idx; + if (node[idx].right != -1) { + inOrder(node[idx].right); + } + } + + // 이동 횟수 세기 + private static void search(int idx) { + if (node[idx].left != -1) { + cnt++; + search(node[idx].left); + if (node[idx].left == lastNode) { + System.out.println(cnt); + System.exit(0); + } + cnt++; + } + + if (node[idx].right != -1) { + cnt++; + search(node[idx].right); + if (node[idx].right == lastNode) { + System.out.println(cnt); + System.exit(0); + } + cnt++; + } } } diff --git a/week5/Baekjoon9663.java b/week5/Baekjoon9663.java index 150a6ca..651d59c 100644 --- a/week5/Baekjoon9663.java +++ b/week5/Baekjoon9663.java @@ -1,7 +1,65 @@ +package algorithm; +import java.io.*; +import java.util.*; -public class Main { +public class Baekjoon9663 { + static int N; + static int[][] board; + static int cnt; - public static void main(String[] args) { + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + board = new int[N][N]; + backTracking(0); + + sb.append(cnt); + System.out.print(sb); + br.close(); + } + + private static void backTracking(int idx) { + if (idx == N) { + cnt++; + return; + } + + for (int i = 0; i < N; i++) { + if(board[idx][i] != 0) { + continue; + } + + setQueen(idx, i, 1); // 선택, 배치 한 칸 +1 + backTracking(idx+1); + setQueen(idx, i, -1); // 선택안함, 배치 안 한 칸 -1 + } } -} + + private static void setQueen(int row, int col, int command) { + // 같은 열 체크 + for(int i = 0; i < N; i++) { + board[i][col] += command; + } + + // 대각선 방향 체크 + for(int i = 0; i < N; i++) { + if(row+i < N && col+i < N) { + board[row+i][col+i] += command; + } + if(row-i >= 0 && col+i < N) { + board[row-i][col+i] += command; + } + if(row+i < N && col-i >= 0) { + board[row+i][col-i] += command; + } + if(row-i >= 0 && col-i >= 0){ + board[row-i][col-i] += command; + } + } + + } + + +} \ No newline at end of file diff --git a/week6/Baekjoon10830.java b/week6/Baekjoon10830.java index 150a6ca..73f40ce 100644 --- a/week6/Baekjoon10830.java +++ b/week6/Baekjoon10830.java @@ -1,3 +1,79 @@ +<<<<<<< HEAD +/* + * BOJ 10830번 : 행렬 제곱 + * 메모리 : 11,560kb + * 시간 : 68ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon10830 { + static int N; + static long B; + static int[][] A; + static int[][] result; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + B = Long.parseLong(st.nextToken()); + A = new int[N][N]; + for (int i = 0; i < N; i++) { + st = new StringTokenizer(br.readLine()); + for (int j = 0; j < N; j++) { + A[i][j] = Integer.parseInt(st.nextToken()) % 1000; + } + } + + result = new int[N][N]; + for (int i = 0; i < N; i++) { // 단위 행렬로 초기화 + result[i][i] = 1; + } + + while (B > 0) { + // B가 홀수면 결과 배열에 A를 한번만 더 곱함 + // 2^5 = (2^2) * (2^2) * 2 + if(B%2 == 1) { + result = square(result, A); + } + + // B가 짝수면 반으로 나눠서 행렬 곱셈 수행 + // 2^10 = (2^5) * (2^5) + A = square(A, A); + B /= 2; + } + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + sb.append(result[i][j]).append(" "); + } + sb.append("\n"); + } + System.out.print(sb); + br.close(); + } + + private static int[][] square(int[][] matrix1, int[][] matrix2) { + int[][] temp = new int[N][N]; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + for (int k = 0; k < N; k++) { + temp[i][j] += matrix1[i][k] * matrix2[k][j]; + temp[i][j] %= 1000; + } + } + } + + return temp; + } +} +======= public class Main { @@ -5,3 +81,4 @@ public static void main(String[] args) { } } +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 diff --git a/week6/Baekjoon13171.java b/week6/Baekjoon13171.java index 150a6ca..0d2ba3f 100644 --- a/week6/Baekjoon13171.java +++ b/week6/Baekjoon13171.java @@ -1,7 +1,48 @@ +<<<<<<< HEAD +/* + * BOJ 13171번 : A + * 메모리 : 11,520kb + * 시간 : 68ms + */ + +package algorithm; +import java.io.*; +import java.util.*; + +public class Baekjoon13171 { + static long A, X; + static final int MOD = 1_000_000_007; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + A = Long.parseLong(br.readLine()); + X = Long.parseLong(br.readLine()); + + sb.append(pow(A%MOD, X)); + System.out.print(sb); + br.close(); + } + + private static long pow(long A, long X) { + if(X==0) { + return 1; + } + + long halfPow = pow(A, X/2); + long squared = (halfPow*halfPow) % MOD; + + if(X%2==0) { + return squared; + } else { + return (A*squared) % MOD; + } +======= public class Main { public static void main(String[] args) { +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 } } diff --git a/week6/Baekjoon17070.java b/week6/Baekjoon17070.java index 150a6ca..a6da9a2 100644 --- a/week6/Baekjoon17070.java +++ b/week6/Baekjoon17070.java @@ -1,7 +1,68 @@ +<<<<<<< HEAD +/* + * BOJ 17070번 : 파이프 옮기기 1 + * 메모리 : 13,736kb + * 시간 : 140ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon17070 { + static int N; + static int[][] map; + static int answer; + static int[] dx = new int[] { 1, 0, 1 }; // 우, 하, 우하대각선 + static int[] dy = new int[] { 0, 1, 1 }; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + map = new int[N+1][N+1]; + for(int r = 1; r <= N; r++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int c = 1; c <= N; c++) { + map[r][c] = Integer.parseInt(st.nextToken()); + } + } + + answer = 0; + dfs(1, 2, 0); + + sb.append(answer); + System.out.print(sb); + br.close(); + } + + private static void dfs(int x, int y, int dir) { + if(x == N && y == N) { + answer++; + return; + } + + // 가로 파이프 + if(dir != 1 && y+1 <= N && map[x][y+1] == 0) { + dfs(x, y+1, 0); + } + + // 세로 파이프 + if(dir != 0 && x+1 <= N && map[x+1][y] == 0) { + dfs(x+1, y, 1); + } + + // 대각선 파이프 + if(x+1 <= N && y+1 <= N && map[x+1][y+1] == 0 && map[x][y+1] == 0 && map[x+1][y] == 0) { + dfs(x+1, y+1, 2); + } +======= public class Main { public static void main(String[] args) { +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 } } diff --git a/week6/Baekjoon1967.java b/week6/Baekjoon1967.java index 150a6ca..ce12c6b 100644 --- a/week6/Baekjoon1967.java +++ b/week6/Baekjoon1967.java @@ -1,3 +1,83 @@ +<<<<<<< HEAD +/* + * BOJ 1967번 : 트리의 지름 + * 메모리 : 19,804kb + * 시간 : 168ms + * + * + * 1. 가장 거리가 먼 두 노드 사이가 지름이 된다. + * 2. 1번째 dfs : 루트에서 가장 거리가 먼 노드 찾기 + * 3. 2번째 dfs : 1번째 dfs로 찾은 노드에서 거리가 먼 노드 찾기 + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon1967 { + static int N; + static List[] tree; + static boolean[] visited; + static int maxDis, maxNode; + + static class Node { + int next; + int weight; + + public Node(int next, int weight) { + this.next = next; + this.weight = weight; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + tree = new ArrayList[N+1]; + for(int n = 1; n < N+1; n++) { + tree[n] = new ArrayList<>(); + } + for(int n = 1; n < N ; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int weight = Integer.parseInt(st.nextToken()); + tree[a].add(new Node( b, weight )); + tree[b].add(new Node( a, weight )); + } + + // 1번째 dfs : 가장 거리가 먼 노드 찾기 + visited = new boolean[N+1]; + maxDis = Integer.MIN_VALUE; + dfs(1, 0); // 시작점, 현재 거리 + + // 2번째 dfs : 찾은 노드에서 가장 거리가 먼 노드 찾기 + visited = new boolean[N+1]; + maxDis = Integer.MIN_VALUE; + dfs(maxNode, 0); // 시작점, 현재 거리 + + sb.append(maxDis); + System.out.println(sb); + br.close(); + } + + private static void dfs(int start, int dis) { + visited[start] = true; + if(dis > maxDis) { + maxDis = dis; + maxNode = start; + } + + for(Node n : tree[start]) { + if(!visited[n.next]) { + dfs(n.next, dis+n.weight); + } + } + } +} +======= public class Main { @@ -5,3 +85,4 @@ public static void main(String[] args) { } } +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 diff --git a/week6/Baekjoon1967_bfs.java b/week6/Baekjoon1967_bfs.java new file mode 100644 index 0000000..5010110 --- /dev/null +++ b/week6/Baekjoon1967_bfs.java @@ -0,0 +1,86 @@ +/* + * BOJ 1967번 : 트리의 지름 + * 메모리 : 20,312kb + * 시간 : 188ms + * + * + * 1. 가장 거리가 먼 두 노드 사이가 지름이 된다. + * 2. 1번째 dfs : 루트에서 가장 거리가 먼 노드 찾기 + * 3. 2번째 dfs : 1번째 dfs로 찾은 노드에서 거리가 먼 노드 찾기 + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon1967_bfs { + static int N; + static List[] tree; + static boolean[] visited; + static int maxDis, maxNode; + + static class Node { + int next; + int weight; + + public Node(int next, int weight) { + this.next = next; + this.weight = weight; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + tree = new ArrayList[N+1]; + for(int n = 1; n < N+1; n++) { + tree[n] = new ArrayList<>(); + } + for(int n = 1; n < N ; n++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int weight = Integer.parseInt(st.nextToken()); + tree[a].add(new Node( b, weight )); + tree[b].add(new Node( a, weight )); + } + + bfs(1); + + bfs(maxNode); + + sb.append(maxDis); + System.out.println(sb); + br.close(); + } + + private static void bfs(int start) { + visited = new boolean[N+1]; + Queue q = new ArrayDeque(); + q.offer(new int[] { start, 0 }); // 출발지, 시작점 + visited[start] = true; + + maxDis = Integer.MIN_VALUE; + maxNode = start; + + while(!q.isEmpty()) { + int[] curr = q.poll(); + int currNode = curr[0]; + int currDis = curr[1]; + + if(currDis > maxDis) { + maxDis = currDis; + maxNode = currNode; + } + + for(Node n : tree[currNode]) { + if(!visited[n.next]) { + visited[n.next] = true; + q.offer(new int[] { n.next, currDis+n.weight }); + } + } + } + } +} \ No newline at end of file diff --git a/week6/Baekjoon2206.java b/week6/Baekjoon2206.java index 150a6ca..38087ca 100644 --- a/week6/Baekjoon2206.java +++ b/week6/Baekjoon2206.java @@ -1,7 +1,93 @@ +<<<<<<< HEAD +/* + * BOJ 2206번 : 벽 부수고 이동하기 + * 메모리 : 107,248kb + * 시간 : 556ms + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon2206 { + static int N, M; + static int[][] map; + static boolean[][][] visited; + static int[] dx = new int[] { -1, 1, 0, 0 }; + static int[] dy = new int[] { 0, 0, -1, 1 }; + static int minDis; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + map = new int[N][M]; + visited = new boolean[N][M][2]; + for(int n = 0; n < N; n++) { + String str = br.readLine(); + for(int m = 0; m < M; m++) { + map[n][m] = str.charAt(m)-'0'; + } + } + + minDis = Integer.MAX_VALUE; + bfs(); + + if(minDis == Integer.MAX_VALUE) { + sb.append(-1); + } else { + sb.append(minDis); + } + System.out.print(sb); + br.close(); + } + + private static void bfs() { + Queue q = new ArrayDeque(); + q.offer(new int[] { 0, 0, 0, 1 }); + visited[0][0][0] = true; + + while(!q.isEmpty()) { + int[] curr = q.poll(); + int cx = curr[0]; + int cy = curr[1]; + int cBreak = curr[2]; + int cDis = curr[3]; + + if(cx == N-1 && cy == M-1) { + minDis = cDis; + return; + } + + for(int d = 0; d < 4; d++) { + int nx = cx + dx[d]; + int ny = cy + dy[d]; + + if(nx >= 0 && ny >= 0 && nx < N && ny < M + && map[nx][ny] == 0 && !visited[nx][ny][cBreak]) { + visited[nx][ny][cBreak] = true; + q.offer(new int[] { nx, ny, cBreak, cDis+1 }); + } + + if(nx >= 0 && ny >= 0 && nx < N && ny < M + && map[nx][ny] == 1 && cBreak == 0) { + if(!visited[nx][ny][cBreak+1]) { + visited[nx][ny][cBreak+1] = true; + q.offer(new int[] { nx, ny, cBreak+1, cDis+1 }); + } + } + } + } + } +======= public class Main { public static void main(String[] args) { } +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 } diff --git a/week6/Baekjoon2623.java b/week6/Baekjoon2623.java index 150a6ca..1443b13 100644 --- a/week6/Baekjoon2623.java +++ b/week6/Baekjoon2623.java @@ -1,7 +1,82 @@ +<<<<<<< HEAD +/* + * BOJ 2623번 : 음악 프로그램 + * 메모리 : 12,272kb + * 시간 : 80ms + * + * 위상정렬, 줄 세우기 유사 문제 + * 진입차수 배열 만들어서, 0이 되면 큐에 삽입 + */ + +package algorithm; + +import java.io.*; +import java.util.*; + +public class Baekjoon2623 { + static int N, M; + static List[] graph; + static int[] indegree; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + graph = new List[N+1]; + indegree = new int[N+1]; + for(int n = 1; n <= N; n++) { + graph[n] = new ArrayList(); + } + for(int m = 0; m < M; m++) { + st = new StringTokenizer(br.readLine()); + int singerNum = Integer.parseInt(st.nextToken()); + int singerCurr = Integer.parseInt(st.nextToken()); + for(int s = 0; s < singerNum-1; s++) { + int singerNext = Integer.parseInt(st.nextToken()); + graph[singerCurr].add(singerNext); + indegree[singerNext]++; + singerCurr = singerNext; + } + } + + Queue q = new ArrayDeque(); + + for(int n = 1; n <= N; n++) { + if(indegree[n] == 0) { + q.offer(n); + } + } + + int cnt = 0; + while(!q.isEmpty()) { + int curr = q.poll(); + sb.append(curr).append("\n"); + cnt++; + + for(int next : graph[curr]) { + indegree[next]--; + if(indegree[next] == 0) { + q.offer(next); + } + } + } + + if(cnt == N) { + System.out.print(sb); + } else { + System.out.print(0); + } + + br.close(); + } +======= public class Main { public static void main(String[] args) { } +>>>>>>> f8a4cc1b59636f9b772aeea870b91b29b6c5c533 } diff --git a/week7/Baekjoon11053_N2.java b/week7/Baekjoon11053_N2.java new file mode 100644 index 0000000..75c9d05 --- /dev/null +++ b/week7/Baekjoon11053_N2.java @@ -0,0 +1,44 @@ +/* + * dp O(N^2) + * 메모리 : 12,060kb + * 시간 : 84ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon11053_N2 { + static int N; + static int[] A; + static int[] dp; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + A = new int[N]; + dp = new int[N]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + dp[n] = 1; + } + + for(int i = 1; i < N; i++) { + for(int j = 0; j < i; j++) { + if(A[j] < A[i]) { + dp[i] = Math.max(dp[i], dp[j]+1); + } + } + } + + answer = 0; + for(int n = 0; n < N; n++) { + answer = Math.max(answer, dp[n]); + } + sb.append(answer); + System.out.print(sb); + br.close(); + } +} diff --git a/week7/Baekjoon11053_NlogN.java b/week7/Baekjoon11053_NlogN.java new file mode 100644 index 0000000..6da3a94 --- /dev/null +++ b/week7/Baekjoon11053_NlogN.java @@ -0,0 +1,55 @@ +/* + * 이분탐색 O(NlogN) + * 메모리 : 11,832kb + * 시간 : 72ms + */ + +import java.io.*; +import java.util.*; + +public class Baekjoon11053_NlogN { + static int N; + static int[] A; + static int[] LIS; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + A = new int[N]; + LIS = new int[N]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + } + + LIS[0] = A[0]; + int length = 1; + for(int n = 1; n < N; n++) { + if(A[n] > LIS[length-1]) { + LIS[length++] = A[n]; + } else { + int pos = binarySearch(0, length-1, A[n]); + LIS[pos] = A[n]; + } + } + + answer = length; + sb.append(answer); + System.out.print(sb); + br.close(); + } + + private static int binarySearch(int left, int right, int target) { + while(left < right) { + int mid = (left+right)/2; + if(LIS[mid] < target) { + left = mid+1; + } else { + right = mid; + } + } + return left; + } +} diff --git a/week7/Baekjoon1520.java b/week7/Baekjoon1520.java deleted file mode 100644 index 150a6ca..0000000 --- a/week7/Baekjoon1520.java +++ /dev/null @@ -1,7 +0,0 @@ - -public class Main { - - public static void main(String[] args) { - - } -} diff --git a/week7/Baekjoon1912.java b/week7/Baekjoon1912.java deleted file mode 100644 index 150a6ca..0000000 --- a/week7/Baekjoon1912.java +++ /dev/null @@ -1,7 +0,0 @@ - -public class Main { - - public static void main(String[] args) { - - } -} diff --git a/week8/Baekjoon14888.java b/week8/Baekjoon14888.java index 150a6ca..2d4c91a 100644 --- a/week8/Baekjoon14888.java +++ b/week8/Baekjoon14888.java @@ -1,7 +1,69 @@ +/* + * BOJ 14888번 : 연산자 끼워넣기 + * 메모리 : 12,436kb + * 시간 : 72ms + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class Baekjoon14888 { + static int N; + static int[] A; + static int[] oper; + static int max, min; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + A = new int[N]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 0; n < N; n++) { + A[n] = Integer.parseInt(st.nextToken()); + } + oper = new int[4]; + st = new StringTokenizer(br.readLine()); + for(int i = 0; i < 4; i++) { + oper[i] = Integer.parseInt(st.nextToken()); + } + + max = Integer.MIN_VALUE; + min = Integer.MAX_VALUE; + + dfs(A[0], 1); + + sb.append(max).append("\n").append(min); + System.out.println(sb); + br.close(); + } + + public static void dfs(int num, int cnt) { + if(cnt == N) { + max = Math.max(max, num); + min = Math.min(min, num); + return; + } + + for(int i = 0; i < 4; i++) { + if(oper[i] > 0) { + oper[i]--; + switch (i) { + case 0: + dfs(num+A[cnt], cnt+1); + break; + case 1: + dfs(num-A[cnt], cnt+1); + break; + case 2: + dfs(num*A[cnt], cnt+1); + break; + case 3 : + dfs(num/A[cnt], cnt+1); + break; + } + } + oper[i]++; + } } -} +} \ No newline at end of file diff --git a/week8/Baekjoon16234.java b/week8/Baekjoon16234.java index 150a6ca..c2e125e 100644 --- a/week8/Baekjoon16234.java +++ b/week8/Baekjoon16234.java @@ -1,7 +1,99 @@ +/* + * BOJ 16234번 : 인구 이동 + * 메모리 : 294,252kb + * 시간 : 624ms + * + * 1. 국경선 열 수 있는지 판단 + * 2. 열린 나라들끼리 인구 이동 -> 평균값으로 인구 재분배 + * 3. 더 이상 이동할 수 없을 때까지 반복 -> 반복횟수 출력 + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class Baekjoon16234 { + static int N, L, R; + static int[][] person; + static boolean[][] visited; + static int answer; + static int[] dx = {-1, 1, 0, 0}; + static int[] dy = {0, 0, -1, 1}; + static int sum, cnt; // 연합 나라 계산 + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + L = Integer.parseInt(st.nextToken()); + R = Integer.parseInt(st.nextToken()); + person = new int[N][N]; + for(int i = 0; i < N; i++) { + st = new StringTokenizer(br.readLine()); + for(int j = 0; j < N; j++) { + person[i][j] = Integer.parseInt(st.nextToken()); + } + } + + answer = 0; + while(true){ + visited = new boolean[N][N]; + boolean move = false; + + for(int i = 0; i < N; i++) { + for(int j = 0; j < N; j++) { + if(!visited[i][j]) { + sum = 0; + cnt = 0; + List list = new ArrayList<>(); // 이번 연합에서 방문한 나라 체크 + bfs(i, j, list); + if(cnt > 1) { // 연합 있었으면 + move = true; + for(int[] arr : list) { + person[arr[0]][arr[1]] = sum/cnt; + } + } + } + } + } + + if(!move) break; + answer++; + } + + sb.append(answer); + System.out.println(sb); + br.close(); + } + + public static void bfs(int x, int y, List list) { + Queue q = new ArrayDeque<>(); + q.offer(new int[]{ x, y }); + visited[x][y] = true; + list.add(new int[]{ x, y }); + sum += person[x][y]; + cnt++; + + while(!q.isEmpty()) { + int[] curr = q.poll(); + int cx = curr[0]; + int cy = curr[1]; + + for (int d = 0; d < 4; d++) { + int nx = cx + dx[d]; + int ny = cy + dy[d]; + + if(nx < 0 || ny < 0 || nx >= N || ny >= N || visited[nx][ny]) continue; + + int diff = Math.abs(person[nx][ny] - person[cx][cy]); + if (diff >= L && diff <= R) { + visited[nx][ny] = true; + list.add(new int[]{ nx, ny }); + sum += person[nx][ny]; + cnt++; + q.add(new int[]{ nx, ny }); + } + } + } } -} +} \ No newline at end of file diff --git a/week8/Baekjoon1956.java b/week8/Baekjoon1956.java index 150a6ca..7451f2e 100644 --- a/week8/Baekjoon1956.java +++ b/week8/Baekjoon1956.java @@ -1,7 +1,69 @@ +/* + * BOJ 1956번 : 운동 + * 메모리 : 58,252kb + * 시간 : 612ms + * + * 1~V개의 마을 + * 도로를 따라 운동경로 찾기, 운동 후에는 다시 시작점으로 돌아와야 함 + * -> 사이클을 이루는 도로의 합이 최소가 되도록 길이 합 출력 + * -> 못 맞으면 -1 출력 + * + * 모든 마을에서 모든 경로 확인 -> 플로이드 워셜 + */ -public class Main { +import java.io.*; +import java.util.*; + +public class Baekjoon1956 { + static int V, E; + static int[][] dis; + static int answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + V = Integer.parseInt(st.nextToken()); + E = Integer.parseInt(st.nextToken()); + dis = new int[V+1][V+1]; + for(int v = 1; v <= V; v++) { + Arrays.fill(dis[v], (int)1e9); + } + + for(int e = 0; e < E; e++) { + st = new StringTokenizer(br.readLine()); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + int d = Integer.parseInt(st.nextToken()); + dis[a][b] = Math.min(dis[a][b], d); + } + + for(int v = 1; v <= V; v++) { + for(int a = 1; a <= V; a++) { + for(int b = 1; b <= V; b++) { + if(dis[a][b] > dis[a][v]+dis[v][b]) { + dis[a][b] = dis[a][v]+dis[v][b]; + } + } + } + } + + answer = Integer.MAX_VALUE; + for(int a = 1; a <= V; a++) { + for(int b = 1; b <= V; b++) { + if(dis[a][b] != (int)1e9 && dis[b][a] != (int)1e9) + answer = Math.min(answer, dis[a][b]+dis[b][a]); + } + } + + if(answer == Integer.MAX_VALUE) { + System.out.print(-1); + br.close(); + return; + } + sb.append(answer); + System.out.print(sb); + br.close(); - public static void main(String[] args) { - } -} +} \ No newline at end of file diff --git a/week8/Baekjoon25624.java b/week8/Baekjoon25624.java index 150a6ca..a65d567 100644 --- a/week8/Baekjoon25624.java +++ b/week8/Baekjoon25624.java @@ -1,7 +1,79 @@ +/* + * BOJ 25624번 : SNUPTI + * 메모리 : 19,076kb + * 시간 : 168ms + * + * 각 자리(열) 알파벳 집합 찾기 + * 그 집합을 겹치지 않게 배정할 수 있으면 YES, 알파벳 집합 출력 + * 불가능하면 NO + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class Baekjoon25624 { + static int N, M; + static Set set; // 입력 문자열 중복 방지 + static int[] alpha; // 알파벳이 어느 자리(열)에 있는지 + static boolean result = true; + static PriorityQueue[] answer; // 알파벳 순으로 문자열 집합 출력 + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + set = new HashSet<>(); + alpha = new int[26]; + Arrays.fill(alpha, -1); + answer = new PriorityQueue[N]; + for(int n = 0; n < N; n++) { + answer[n] = new PriorityQueue<>(); + } + + for(int m = 0; m < M; m++) { + String str = br.readLine(); + if (set.contains(str)) { + result = false; + continue; + } else { + set.add(str); + } + + for(int n = 0; n < N; n++) { + char ch = str.charAt(n); + if(alpha[ch-'A'] == -1) { // 처음 등장한 알파벳 + alpha[ch-'A'] = n; // 자리(열) 위치 저장 + answer[n].add(ch); + } else if(alpha[ch-'A'] != n) { // 다른 자리(열) + result = false; + } + } + } + + // 불가능하면 NO + if(!result) { + System.out.println("NO"); + return; + } + + // 문자열 집합으로 만들 수 있는 경우의 수 계산 + int total = 1; + for(int n = 0; n < N; n++) { + total *= answer[n].size(); + } + + if(total != M){ + System.out.println("NO"); + } else { + System.out.println("YES"); + for(int n = 0; n < N; n++) { + while(!answer[n].isEmpty()) { + System.out.print(answer[n].poll()); + } + System.out.println(); + } + } } -} +} \ No newline at end of file diff --git a/week8/Baekjoon6603.java b/week8/Baekjoon6603.java index 150a6ca..4f8d546 100644 --- a/week8/Baekjoon6603.java +++ b/week8/Baekjoon6603.java @@ -1,7 +1,57 @@ +/* + * BOJ 6603번 : 로또 + * 메모리 : 11,740kb + * 시간 : 68ms + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class Baekjoon6603 { + static int K; + static int[] S; + static boolean[] visited; + static int[] answer; + static StringBuilder sb = new StringBuilder(); + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + while(true){ + StringTokenizer st = new StringTokenizer(br.readLine()); + K = Integer.parseInt(st.nextToken()); + if(K == 0) break; + S = new int[K]; + visited = new boolean[K]; + answer = new int[6]; + for(int k = 0; k < K; k++) { + S[k] = Integer.parseInt(st.nextToken()); + } + + Arrays.sort(S); + comb(0, 0); + sb.append("\n"); + } + System.out.println(sb); + br.close(); + } + + // K개에서 6개 뽑는 조합 + public static void comb(int cnt, int start) { + if(cnt == 6){ + for(int i = 0; i < 6; i++){ + sb.append(answer[i]).append(" "); + } + sb.append("\n"); + return; + } + + for(int i = start; i < K; i++) { + if(!visited[i]){ + visited[i] = true; + answer[cnt] = S[i]; + comb(cnt+1, i+1); + visited[i] = false; + } + } } -} +} \ No newline at end of file diff --git a/week9/Baekjoon1138.java b/week9/Baekjoon1138.java index 150a6ca..bedd9e8 100644 --- a/week9/Baekjoon1138.java +++ b/week9/Baekjoon1138.java @@ -1,7 +1,40 @@ +/* + * BOJ 1138번 : 한 줄로 서기 + * 메모리 : 11,596kb + * 시간 : 76ms + * + * 큰 사람부터 줄 세우기 + * input[n]은 자기보다 큰 사람이 몇 명? 이니까 + * input[n]번째 위치에 자기를 넣으면 됨 + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class Baekjoon1138 { + static int N; + static int[] input; + static List answer; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + input = new int[N+1]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int n = 1; n <= N; n++) { + input[n] = Integer.parseInt(st.nextToken()); + } + + answer = new ArrayList<>(); + for(int n = N; n >= 1; n--) { + answer.add(input[n], n); // index, value + } + + for(int a : answer) { + sb.append(a).append(" "); + } + System.out.println(sb); + br.close(); } -} +} \ No newline at end of file diff --git a/week9/Baekjoon13418.java b/week9/Baekjoon13418.java index ee7e1ab..7783115 100644 --- a/week9/Baekjoon13418.java +++ b/week9/Baekjoon13418.java @@ -1,125 +1,82 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY +/* + * BOJ 13418번 : 학교 탐방 하기 + * 메모리 : 224,996kb + * 시간 : 1,056ms * + * 오르막길 내리막길 헷갈리지 말자! */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - + + +import java.io.*; +import java.util.*; + +public class Baekjoon13418 { + static int N, M; + static List[] list; + static boolean[] visited; + static int maxRoad, minRoad; + static class Node { + int to, road; + public Node (int to, int road) { + this.to = to; + this.road = road; + } + } + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } + list = new ArrayList[N+1]; + for(int n = 0; n <= N; n++) { + list[n] = new ArrayList(); } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); - } + for(int m = 0; m <= M; m++) { + st = new StringTokenizer(br.readLine()); + int from = Integer.parseInt(st.nextToken()); + int to = Integer.parseInt(st.nextToken()); + int road = Integer.parseInt(st.nextToken()); + list[from].add(new Node(to, road)); + list[to].add(new Node(from, road)); } - - System.out.println(max); + + // 오르막길(0) + PriorityQueue minPQ = new PriorityQueue<>((o1,o2) -> o1.road-o2.road); + maxRoad = (int) Math.pow(prim(minPQ), 2); + + // 내리막길(1) + PriorityQueue maxPQ = new PriorityQueue<>((o1,o2) -> o2.road-o1.road); + minRoad = (int) Math.pow(prim(maxPQ), 2); + + sb.append(maxRoad-minRoad); + System.out.print(sb); + br.close(); } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); + private static int prim(PriorityQueue pq) { + int sum = 0; + visited = new boolean[N+1]; + visited[0] = true; + for(Node node : list[0]) { + pq.offer(new Node(node.to, node.road)); } - } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + while(!pq.isEmpty()) { + Node curr = pq.poll(); + if(!visited[curr.to]) { + visited[curr.to] = true; + sum += (curr.road==0) ? 1 : 0; // 오르막이면 피로도 증가 - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; + for(Node next : list[curr.to]) { + if(!visited[next.to]) { + pq.offer(new Node(next.to, next.road)); + } + } + } } - - } - - -} + return sum; + } +} \ No newline at end of file diff --git a/week9/Baekjoon14500.java b/week9/Baekjoon14500.java index ee7e1ab..2020f86 100644 --- a/week9/Baekjoon14500.java +++ b/week9/Baekjoon14500.java @@ -1,125 +1,107 @@ - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; - -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY +/* + * BOJ 14500번 : 테트로미노 + * 메모리 : 322,268kb + * 시간 : 356ms * + * 그냥 구현한다... 총 19가지 */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - + +import java.io.*; +import java.util.*; + +public class Baekjoon14500 { + static int N, M; + static int[][] map; + static int max; + public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - + StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(br.readLine()); - N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { + map = new int[N][M]; + for (int n = 0; n < N; n++) { st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); + for (int m = 0; m < M; m++) { + map[n][m] = Integer.parseInt(st.nextToken()); } } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); + + max = 0; + for (int n = 0; n < N; n++) { + for (int m = 0; m < M; m++) { + check(n, m); } } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); - } + sb.append(max); + System.out.print(sb); + br.close(); } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { - - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; - } - - //윗 방향을 제외한 3방향으로 이동하며 블록 선택 - for(int d=0; d<3; d++) { - - int nr = r+dr[d]; - int nc = c+dc[d]; - - //경계를 벗어나거나 이미 방문했다면 다음 방향 - if(nr>N || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - - } - - + static void check(int x, int y) { + // 1. ㅡ 가로 + if (y+3 < M) + max = Math.max(max, map[x][y]+map[x][y+1]+map[x][y+2]+map[x][y+3]); + + // ㅣ 세로 + if (x+3 < N) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+2][y]+map[x+3][y]); + + // 2. ㅁ + if (x+1 < N && y+1 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x][y+1]+map[x+1][y+1]); + + // 3. ㄴ + if (x+2 < N && y+1 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+2][y]+map[x+2][y+1]); + + if (x+2 < N && y-1 >= 0) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+2][y]+map[x+2][y-1]); -} + if (x+1 < N && y+2 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x][y+1]+map[x][y+2]); + + if (x+1 < N && y+2 < M) + max = Math.max(max, map[x][y]+map[x][y+1]+map[x][y+2]+map[x+1][y+2]); + + if (x+2 < N && y+1 < M) + max = Math.max(max, map[x][y]+map[x][y+1]+map[x+1][y+1]+map[x+2][y+1]); + + if (x+2 < N && y-1 >= 0) + max = Math.max(max, map[x][y]+map[x][y-1]+map[x+1][y-1]+map[x+2][y-1]); + + if (x+1 < N && y-2 >= 0) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+1][y-1]+map[x+1][y-2]); + + if (x+1 < N && y+2 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+1][y+1]+map[x+1][y+2]); + + // 4. ㄴㄱ + if (x+1 < N && y+2 < M) + max = Math.max(max, map[x][y]+map[x][y+1]+map[x+1][y+1]+map[x+1][y+2]); + + if (x+1 < N && y-2 >= 0) + max = Math.max(max, map[x][y]+map[x][y-1]+map[x+1][y-1]+map[x+1][y-2]); + + if (x+2 < N && y+1 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+1][y+1]+map[x+2][y+1]); + + if (x+2 < N && y-1 >= 0) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+1][y-1]+map[x+2][y-1]); + + // 5. ㅗ + if (x+1 < N && y+2 < M) + max = Math.max(max, map[x][y]+map[x][y+1]+map[x][y+2]+map[x+1][y+1]); + + if (x+1 < N && y-1 >= 0 && y+1 < M) + max = Math.max(max, map[x][y]+map[x+1][y-1]+map[x+1][y]+map[x+1][y+1]); + + if (x+2 < N && y+1 < M) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+2][y]+map[x+1][y+1]); + + if (x+2 < N && y-1 >= 0) + max = Math.max(max, map[x][y]+map[x+1][y]+map[x+2][y]+map[x+1][y-1]); + } +} \ No newline at end of file diff --git a/week9/Baekjoon1535.java b/week9/Baekjoon1535.java index 150a6ca..1ab56fb 100644 --- a/week9/Baekjoon1535.java +++ b/week9/Baekjoon1535.java @@ -1,7 +1,48 @@ +/* + * BOJ 1535번 : 안녕 + * 메모리 : 11,612kb + * 시간 : 72ms + */ + +import java.io.*; +import java.util.*; public class Main { + static int N; + static int[] blood; + static int[] happy; + static int[] dp; + static int maxHappy; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + int N = Integer.parseInt(br.readLine()); + blood = new int[N]; + happy = new int[N]; + dp = new int[100]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for (int i = 0; i < N; i++) { + blood[i] = Integer.parseInt(st.nextToken()); + } + st = new StringTokenizer(br.readLine()); + for (int i = 0; i < N; i++) { + happy[i] = Integer.parseInt(st.nextToken()); + } + + for (int i = 0; i < N; i++) { + for (int j = 99; j >= blood[i]; j--) { + dp[j] = Math.max(dp[j], dp[j - blood[i]] + happy[i]); + } + } + + maxHappy = 0; + for (int i = 0; i < 100; i++) { + maxHappy = Math.max(maxHappy, dp[i]); + } - public static void main(String[] args) { - + sb.append(maxHappy); + System.out.print(sb); + br.close(); } } diff --git a/week9/Baekjoon1647.java b/week9/Baekjoon1647.java index 150a6ca..f2a60f0 100644 --- a/week9/Baekjoon1647.java +++ b/week9/Baekjoon1647.java @@ -1,7 +1,70 @@ +/* + * BOJ 1647번 : 도시 분할 계획 + * 메모리 : 351,992kb + * 시간 : 1,792ms + * + * MST에서 가장 가중치가 높은 간선을 지워주면, + * 2개의 마을을 최소로 나눌 수 있다. + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class BOJ1647_도시분할계획 { + static int N, M; + static List[] list; + static boolean[] visited; + static int minSum; + static class Node { + int to, cost; + public Node(int to, int cost) { + this.to = to; + this.cost = cost; + } } -} + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(br.readLine()); + N = Integer.parseInt(st.nextToken()); + M = Integer.parseInt(st.nextToken()); + list = new ArrayList[N+1]; + visited = new boolean[N+1]; + for(int n = 1; n <= N; n++) { + list[n] = new ArrayList(); + } + for(int m = 0; m < M; m++) { + st = new StringTokenizer(br.readLine()); + int from = Integer.parseInt(st.nextToken()); + int to = Integer.parseInt(st.nextToken()); + int cost = Integer.parseInt(st.nextToken()); + list[from].add(new Node(to, cost)); + list[to].add(new Node(from, cost)); + } + + PriorityQueue pq = new PriorityQueue<>((o1,o2) -> o1.cost-o2.cost); + pq.add(new Node(1,0)); + + minSum = 0; + int maxCost = 0; + while(!pq.isEmpty()) { + Node curr = pq.poll(); + if(!visited[curr.to]) { + visited[curr.to] = true; + minSum += curr.cost; + maxCost = Math.max(maxCost, curr.cost); + + for(Node next : list[curr.to]) { + if(!visited[next.to]) { + pq.add(new Node(next.to, next.cost)); + } + } + } + } + + sb.append(minSum-maxCost); + System.out.print(sb); + br.close(); + } +} \ No newline at end of file diff --git a/week9/Baekjoon1976.java b/week9/Baekjoon1976.java index 150a6ca..930653d 100644 --- a/week9/Baekjoon1976.java +++ b/week9/Baekjoon1976.java @@ -1,7 +1,79 @@ +/* + * BOJ 1976번 : 여행가자 + * 메모리 : 15,848kb + * 시간 : 120ms + * + * 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인지? + * 도시들이 연결되어 있는지? 판단하기 + */ -public class Main { +import java.io.*; +import java.util.*; - public static void main(String[] args) { - +public class BOJ1976_여행가자 { + static int N, M; + static int[][] graph; + static int[] parent; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringBuilder sb = new StringBuilder(); + N = Integer.parseInt(br.readLine()); + M = Integer.parseInt(br.readLine()); + graph = new int[N+1][N+1]; + parent = new int[N+1]; + for(int n = 1; n <= N; n++) { + parent[n] = n; + } + + for(int i = 1; i <= N; i++) { + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int j = 1; j <= N; j++) { + graph[i][j] = Integer.parseInt(st.nextToken()); + } + } + for(int i = 1; i <= N; i++) { + for(int j = 1; j <= N; j++) { + if(graph[i][j] == 1) { // 연결 + union(i, j); + } + } + } + + int[] arr = new int[M]; + boolean answer = true; + StringTokenizer st = new StringTokenizer(br.readLine()); + for(int m = 0; m < M; m++) { + arr[m] = Integer.parseInt(st.nextToken()); + } + // 부모가 같아야 함 + int temp = find(arr[0]); + for(int i = 1; i < M; i++) { + if(find(arr[i]) != temp) { + answer = false; + break; + } + } + if(answer) { + sb.append("YES"); + } else { + sb.append("NO"); + } + System.out.print(sb); + br.close(); + } + + + private static void union(int x, int y) { + x = find(x); + y = find(y); + + if(x<=y) parent[y] = x; + else parent[x] = y; + } + + private static int find(int x) { + if(parent[x]==x) return x; + else return parent[x]=find(parent[x]); } } diff --git a/week9/Baekjoon4195.java b/week9/Baekjoon4195.java index ee7e1ab..bfa9f8a 100644 --- a/week9/Baekjoon4195.java +++ b/week9/Baekjoon4195.java @@ -1,125 +1,65 @@ +import java.io.*; +import java.util.*; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.StringTokenizer; +public class Baekjoon4195 { + static int F; + static Map map; + static int[] parent; + static int[] size; -/** - * - * 각 지점을 중심으로 dfs 아래, 왼쪽, 오른쪽 방향으로만 dfs 탐색 depth:4로 - * - 탐색 시 최대값을 발견한다면 갱신 - * 탐색한 지점은 방문 처리 - * - * - * - * 가운데 모양은 따로 탐색 필요 - * - * - * @author SSAFY - * - */ -public class Main_B_14500_테트로미노_연민호 { - - //하좌우상 - final static int[] dr = {1, 0, 0, -1}; - final static int[] dc = {0, -1, 1, 0}; - - - - static int N; //세로 크기 - static int M; //가로 크기 - - static int[][] map; //숫자판 정보 - - static boolean[][] visited; //방문체크 - - static int max; //최댓값 - 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()); - - //탐색의 편이를 위해 공백을 넣어놓음 - map = new int[N+2][M+2]; - for(int i=1; i<=N; i++) { - st = new StringTokenizer(br.readLine()); - for(int j=1; j<=M; j++) { - map[i][j] = Integer.parseInt(st.nextToken()); - } - } - - - visited = new boolean[N+2][M+2]; - - - for(int i=1; i<=N; i++) { - for(int j=1; j<=M; j++) { - visited[i][j] = true; - dfs(i,j, map[i][j], 1); - visited[i][j] = false; - - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - etc(i, j, map[i][j]); + StringBuilder sb = new StringBuilder(); + int T = Integer.parseInt(br.readLine()); + for (int t = 1; t <= T; t++) { + F = Integer.parseInt(br.readLine()); + + parent = new int[F*2]; + size = new int[F*2]; + for(int f = 0; f < F*2; f++) { + parent[f] = f; + size[f] = 1; } - } - - System.out.println(max); - } - //가운데 블록 기준 3개 블록이 붙어있는 테트로미노 탐색 - private static void etc(int r, int c, int sum) { - - //(r,c) 기준 4방의 값을 모두 더함 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - sum+= map[nr][nc]; - } - - //4방의 값을 하나씩 빼보면서 해당 값이 최댓값이라면 갱신 - for(int d=0; d<4; d++) { - int nr = r+dr[d]; - int nc = c+dc[d]; - max = Math.max(max, sum-map[nr][nc]); + map = new HashMap(); + int idx = 0; + for (int f = 0; f < F; f++) { + StringTokenizer st = new StringTokenizer(br.readLine(), " "); + String user1 = st.nextToken(); + String user2 = st.nextToken(); + if (!map.containsKey(user1)) { + map.put(user1, idx++); + } + if (!map.containsKey(user2)) { + map.put(user2, idx++); + } + + union(map.get(user1), map.get(user2)); + + int cnt = size[find(map.get(user1))]; + sb.append(cnt).append("\n"); + } } + System.out.print(sb); + br.close(); } - /** - * 블록하나를 선택하고 다음 블록 선택은 재귀호출로 넘김 - * @param r - * @param c - * @param sum //선택한 블록의 숫자 합 - * @param cnt //선택한 블록의 개수 - */ - private static void dfs(int r, int c, int sum, int cnt) { + private static void union(int x, int y) { + x = find(x); + y = find(y); - //step01. 4개의 블록 선택 완료 - if(cnt==4) { - //step 02. 선택한 블록 숫자의 합이 최댓값이라면 갱신 - max = Math.max(sum, max); - return; + if(x==y) return; + if(xN || nc<1 || nc>M || visited[nr][nc]) continue; - - visited[nr][nc] = true; - dfs(nr, nc, sum+map[nr][nc], cnt+1); - visited[nr][nc] = false; - } - } - - + private static int find (int x) { + if(parent[x]==x) return x; + return parent[x]=find(parent[x]); + } }