diff --git "a/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/Main.java" "b/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/Main.java" new file mode 100644 index 0000000..4680299 --- /dev/null +++ "b/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/Main.java" @@ -0,0 +1,78 @@ +package boj.b1027.wldy4627; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.StringTokenizer; + +public class Main { + static int N; + static int[] buildings; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + N = Integer.parseInt(br.readLine()); + + buildings = new int[N+1]; + StringTokenizer st = new StringTokenizer(br.readLine()); + for (int i = 1; i <= N; i++) { + buildings[i] = Integer.parseInt(st.nextToken()); + } + + int maxCnt = 0; + for (int i = 1; i <= N; i++) { + if (i == 1) { + maxCnt = right(i); + } else if (i == N) { + maxCnt = Math.max(maxCnt, left(i)); + } else { + maxCnt = Math.max(maxCnt, left(i) + right(i)); + } + } + + System.out.println(maxCnt); + } + + static int left(int startIdx) { + int nowIdx = startIdx; + int cnt = 0; + double maxSlope = Double.MAX_VALUE; + while (true) { + // 다음 빌딩 탐색 + nowIdx--; + if (nowIdx <= 0) { + break; + } + + double nowSlope = (double)(buildings[nowIdx] - buildings[startIdx]) / (nowIdx - startIdx); + + if (nowSlope < maxSlope) { + maxSlope = nowSlope; + cnt++; + } + } + return cnt; + } + + static int right(int startIdx) { + int nowIdx = startIdx; + int cnt = 0; + double maxSlope = -Double.MAX_VALUE; + while (true) { + // 다음 빌딩 탐색 + nowIdx++; + if (nowIdx > N) { + break; + } + + double nowSlope = (double)(buildings[nowIdx] - buildings[startIdx]) / (nowIdx - startIdx); + + if (nowSlope > maxSlope) { + maxSlope = nowSlope; + cnt++; + } + } + return cnt; + } +} diff --git "a/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/README.md" "b/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/README.md" new file mode 100644 index 0000000..a120d2a --- /dev/null +++ "b/BOJ/[1027] \352\263\240\354\270\265 \352\261\264\353\254\274/wldy4627/README.md" @@ -0,0 +1,20 @@ +### 문제 이해 +- 세준시에서 가장 많은 고층 빌딩이 보이는 고층 빌딩을 찾으려고 함 +- 빌딩은 총 N개이고, 선분으로 나타냄 +- i번째 빌딩(1부터 시작)은 (i,0)부터 (i,높이)의 선분으로 나타낼 수 있음 +- A에서 B가 볼 수 있는 빌딩이 되려면, 두 지붕을 잇는 선분이 A와 B를 제외한 다른 고층 빌딩을 지나거나 접하지 않아야 함 +- 가장 많은 고층 빌딩이 보이는 빌딩을 구하고, 거기서 보이는 빌딩의 수를 출력하는 프로그램 +#### input & output +- input: + - 빌딩의 수 N + - 1번 빌딩부터 높이 +- output: 문제의 정답 +--- +### 고안 방식 +- 구현 +#### 최종 방식 +- 빌딩을 기준으로 왼쪽에서 볼 수 있는 것 + 오른쪽에서 볼 수 있는 것 +- 최대 기울기보다 크면 cnt++ +- 왼쪽 -> 음수 기준 +- 오른쪽 -> 양수 기준 +- 성능을 더 높일 수 있을 것 같은데... diff --git "a/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/Main.java" "b/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/Main.java" new file mode 100644 index 0000000..5e04ac5 --- /dev/null +++ "b/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/Main.java" @@ -0,0 +1,90 @@ +package boj.b2179.wldy4627; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; + +public class Main { + static class Word { + String str; + int idx; + + Word(String str, int idx) { + this.str = str; + this.idx = idx; + } + } + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + int N = Integer.parseInt(br.readLine()); + + String[] original = new String[N]; + Word[] words = new Word[N]; + for (int i = 0; i < N; i++) { + original[i] = br.readLine(); + words[i] = new Word(original[i], i); + } + + // 사전 순 정렬 + Arrays.sort(words, (a, b) -> a.str.compareTo(b.str)); + + int maxCnt = Integer.MIN_VALUE; + for (int i = 0; i < N - 1; i++) { + maxCnt = Math.max(maxCnt, commonPrefixLength(words[i].str, words[i + 1].str)); + } + + int bestA = Integer.MAX_VALUE; + int bestB = Integer.MAX_VALUE; + for (int i = 0; i < N - 1; i++) { + int nowCnt = commonPrefixLength(words[i].str, words[i + 1].str); + if (nowCnt != maxCnt) continue; + + String prefix = words[i].str.substring(0, maxCnt); + + // prefix가 동일한 다른 쌍이 있는지 확인 + int j = i; + int first = Integer.MAX_VALUE; + int second = Integer.MAX_VALUE; + + while (j < N && words[j].str.startsWith(prefix)) { + int idx = words[j].idx; + + if (idx < first) { + second = first; + first = idx; + } else if (idx < second) { + second = idx; + } + + j++; + } + + if (first < bestA || (first == bestA && second < bestB)) { + bestA = first; + bestB = second; + } + } + + System.out.println(original[bestA]); + System.out.println(original[bestB]); + } + + static int commonPrefixLength(String s1, String s2) { + int count = 0; + int len = Math.min(s1.length(), s2.length()); + + for (int i = 0; i < len; i++) { + if (s1.charAt(i) == s2.charAt(i)) { + count++; + } else { + break; + } + } + + return count; + } +} diff --git "a/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/README.md" "b/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/README.md" new file mode 100644 index 0000000..3282968 --- /dev/null +++ "b/BOJ/[2179] \353\271\204\354\212\267\355\225\234 \353\213\250\354\226\264/wldy4627/README.md" @@ -0,0 +1,17 @@ +### 문제 이해 +- N개의 영단어에서 가장 비슷한 두 단어를 구해내는 프로그램 +- 비슷한 정도: 두 단어의 접두사의 길이 +- 두 단어의 앞에서부터 M개의 글자들이 같으면서 M이 최대인 경우 +- 접두사의 길이가 최대인 경우가 여러 개일 때에는 입력되는 순서대로 제일 앞쪽에 있는 단어가 답 + - 그런 경우도 여러 개 있을 경우 T가 입력되는 순서대로 제일 앞쪽에 있는 단어인 경우 +#### input & output +- input: + - N + - 알파벳 소문자로 이루어진 길이 100자 이하의 서로 다른 영단어 +- output: S, T (서로 달라야 함) +--- +### 고안 방식 +- 구현 +#### 최종 방식 +- 정렬 -> 뒤에 것과 비교 +- M이 최대인 것을 구하고, 해당 Prefix를 가지는 단어들 중 적절한 S, T 찾기