diff --git "a/BOJ/1000-5000\353\262\210/DH_2098.java" "b/BOJ/1000-5000\353\262\210/DH_2098.java" new file mode 100644 index 00000000..2af2a4d5 --- /dev/null +++ "b/BOJ/1000-5000\353\262\210/DH_2098.java" @@ -0,0 +1,54 @@ +import java.io.*; +import java.util.*; + +/* + * 외판원 순회 + * dp 배열을 -1로 초기화해야되는 이유 + * 한 지점에서 다른 지점들을 갈 수 없을 때, INF를 return 하게 되는데 + * 이 때, 방문을 한 후 INF인지 방문을 하지 못하는 경우인지 알 수 없게 되어 시간 초과가 발생함 + */ + +public class DH_2098 { + static int N; + static int[][] W, dp; + + static final int INF = Integer.MAX_VALUE >> 1; + + static int TSP(int now, int visitedCities) { + if(visitedCities == (1 << N) - 1) { + // 지금 노드에서 시작점(0)까지 갈 수 있는 경로가 없다면 INF 반환 + // 갈 수 있는 경로가 있다면 지금 노드에서 0까지 가는 값 반환 + return W[now][0] != 0 ? W[now][0]: INF; + } + + if(dp[now][visitedCities] != -1) return dp[now][visitedCities]; + dp[now][visitedCities] = INF; + + for(int next = 0; next < N; next++) { + int city = 1 << next; + // (visitedCites & city) != 0: 이미 간 곳 + // W[now][next] == 0: 지금 위치에서 탐색하고자 하는 지점까지 갈 수 있는 길이가 없는 경우 + if((visitedCities & city) != 0 || W[now][next] == 0) continue; + dp[now][visitedCities] = Math.min(dp[now][visitedCities], TSP(next, city | visitedCities) + W[now][next]); + } + + return dp[now][visitedCities]; + } + + public static void main(String[] args) throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + N = Integer.parseInt(br.readLine()); + W = new int[N][N]; + dp = new int[N][1 << N]; + + for(int r = 0; r < N; r++) { + st = new StringTokenizer(br.readLine()); + for(int c = 0; c < N; c++) W[r][c] = Integer.parseInt(st.nextToken()); + Arrays.fill(dp[r], -1); + } + + System.out.println(TSP(0, 1 << 0)); + } +} diff --git "a/BOJ/1000-5000\353\262\210/DH_2660.java" "b/BOJ/1000-5000\353\262\210/DH_2660.java" new file mode 100644 index 00000000..b4e90672 --- /dev/null +++ "b/BOJ/1000-5000\353\262\210/DH_2660.java" @@ -0,0 +1,78 @@ +import java.io.*; +import java.util.*; + +/* + * 회장뽑기 + */ + +public class DH_2660 { + static int N, maxDepth; + static ArrayList adj[]; + static ArrayDeque q; + static boolean[] v; + static int[] depth; // 각 회원마다 끝까지 탐색했을 때 depth를 저장할 변수 + static TreeSet set; // 회장이 될 수 있는 사람의 번호를 담음 + + public static void main(String[] args) throws Exception { + initInput(); + solution(); + + StringBuilder sb = new StringBuilder(); + + sb.append(maxDepth).append(" ").append(set.size()).append("\n"); + for(int i: set) sb.append(i).append(" "); + System.out.println(sb); + } + + static void solution() { + for(int i = 1; i < adj.length; i++) { + v = new boolean[N + 1]; + q.add(new int[] {i, 0}); // [0]: 학생 번호, [1]: depth 깊이 + v[i] = true; + + while(!q.isEmpty()) { + int[] current = q.poll(); + depth[i] = current[1]; + + for(int next: adj[current[0]]) { + if(v[next]) continue; + q.add(new int[] {next, current[1] + 1}); + v[next] = true; + } + } + + if(depth[i] < maxDepth) { // maxDepth 깊이가 작아야 점수가 작아지기 때문에 + maxDepth = depth[i]; + set.clear(); + } + + if(depth[i] == maxDepth) set.add(i); + } + } + + static void initInput() throws Exception { + System.setIn(new FileInputStream("../AlgorithmStudy/input/BOJ2660.txt")); + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + q = new ArrayDeque<>(); + set = new TreeSet(); + + maxDepth = Integer.MAX_VALUE; + N = Integer.parseInt(br.readLine()); + adj = new ArrayList[N + 1]; + for(int i = 0; i < adj.length; i++) adj[i] = new ArrayList(); + + depth = new int[N + 1]; + + String s; + while(!(s = br.readLine()).equals("-1 -1")) { + st = new StringTokenizer(s); + int a = Integer.parseInt(st.nextToken()); + int b = Integer.parseInt(st.nextToken()); + + adj[a].add(b); + adj[b].add(a); + } + } +} diff --git "a/BOJ/10001-15000\353\262\210/DH_13164.java" "b/BOJ/10001-15000\353\262\210/DH_13164.java" new file mode 100644 index 00000000..d0df2791 --- /dev/null +++ "b/BOJ/10001-15000\353\262\210/DH_13164.java" @@ -0,0 +1,32 @@ +import java.io.*; +import java.util.*; + +/* + * 행복 유치원 + */ + +public class DH_13164 { + public static void main(String[] args) throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st = new StringTokenizer(br.readLine()); + + int N = Integer.parseInt(st.nextToken()); // 원생의 수 + int K = Integer.parseInt(st.nextToken()); // 조의 개수 + + st = new StringTokenizer(br.readLine()); + + int[] diff = new int[N - 1]; + + int prev = Integer.parseInt(st.nextToken()); + for(int i = 0; i < diff.length; i++) { + int current = Integer.parseInt(st.nextToken()); + diff[i] = current - prev; + prev = current; + } + + Arrays.sort(diff); + int result = 0; + for(int i = 0; i < N - K; i++) result += diff[i]; + System.out.println(result); + } +} diff --git "a/BOJ/10001-15000\353\262\210/DH_14620.java" "b/BOJ/10001-15000\353\262\210/DH_14620.java" new file mode 100644 index 00000000..3a736698 --- /dev/null +++ "b/BOJ/10001-15000\353\262\210/DH_14620.java" @@ -0,0 +1,85 @@ +import java.io.*; +import java.util.*; + +/* + * 꽃길 + */ +public class DH_14620 { + static int N, result; + static int[][] map; + static boolean[][] v; + static int[] dr = {-1 ,1, 0, 0}, dc = {0, 0, -1, 1}; + + public static void main(String[] args) throws Exception { + initInput(); + func(0, 0, 0); + System.out.println(result); + } + + static void func(int depth, int idx, int cost) { + if(depth == 3) { + result = Math.min(result, cost); + return; + } + + for(int i = idx; i < N * N; i++) { + int r = i / N, c = i % N; + + if(!check(r, c)) continue; + + v[r][c] = true; + cost += map[r][c] + plant(r, c, true); + + func(depth + 1, i + 1, cost); + v[r][c] = false; + cost -= map[r][c] + plant(r, c, false); + } + } + + static int plant(int r, int c, boolean status) { + int cost = 0; + for(int d = 0; d < 4; d++) { + int nr = r + dr[d]; + int nc = c + dc[d]; + + v[nr][nc] = status; + cost += map[nr][nc]; + } + + return cost; + } + + static boolean check(int r, int c) { + for(int d = 0; d < 4; d++) { + int nr = r + dr[d]; + int nc = c + dc[d]; + + if(!isValid(nr, nc) || v[nr][nc]) return false; + } + + return true; + } + + static boolean isValid(int r, int c) { + return r >= 0 && r < N && c >= 0 && c < N; + } + + static void initInput() throws Exception { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + N = Integer.parseInt(br.readLine()); + map = new int[N][N]; + v = new boolean[N][N]; + + result = Integer.MAX_VALUE; + + for(int r = 0; r < N; r++) { + st = new StringTokenizer(br.readLine()); + for(int c = 0; c < N; c++) { + map[r][c] = Integer.parseInt(st.nextToken()); + } + } + + } +} diff --git "a/CodeTree/2017-2018\353\205\204/DH_\354\240\204\355\210\254\353\241\234\353\264\207.java" "b/CodeTree/2017-2018\353\205\204/DH_\354\240\204\355\210\254\353\241\234\353\264\207.java" new file mode 100644 index 00000000..f6847adc --- /dev/null +++ "b/CodeTree/2017-2018\353\205\204/DH_\354\240\204\355\210\254\353\241\234\353\264\207.java" @@ -0,0 +1,152 @@ +import java.io.*; +import java.util.*; + +public class DH_전투로봇 { + static class Point { + int r, c; + public Point(int r, int c) { + this.r = r; + this.c = c; + } + } + + static class qPoint implements Comparable { + Point p; + int d; + public qPoint(Point p, int d) { + this.p = p; + this.d = d; + } + + @Override + public int compareTo(qPoint o) { + if(this.d == o.d) { + if(this.p.r == o.p.r) return Integer.compare(this.p.c, o.p.c); // 열 오름차순 + return Integer.compare(this.p.r, o.p.r); // 행 오름차순s + } + return Integer.compare(this.d, o.d); // 거리 오름차순 + } + } + + static int[] dr = {-1, 1, 0, 0}, dc = {0, 0, -1, 1}; + static int N, dieMonsterCnt, totalTime; + static int[][] levelMap, monsterIdxMap; + static Point robot; + + public static void main(String[] args) throws Exception { + initInput(); + solution(); + } + + static void solution() { + + int time; + while((time = bfs()) != 0) { + totalTime += time; + } + System.out.println(totalTime); + } + + static int bfs() { + + PriorityQueue q = new PriorityQueue<>(); + boolean[][] v = new boolean[N][N]; + + q.add(new qPoint(robot, 0)); + v[robot.r][robot.c] = true; + int robotLevel = levelMap[robot.r][robot.c]; + levelMap[robot.r][robot.c] = 0; + + // 없앨 수 있는 몬스터 정보 구하기 + while(!q.isEmpty()) { + qPoint current = q.poll(); + + // 몬스터를 없앨 수 있다면 + if(canKillMonster(current.p, robotLevel)) { + // 몬스터 없앤 개수 늘리기 + dieMonsterCnt++; + // 없앤 몬스터의 개수와 로봇의 레벨이 같다면 + if(dieMonsterCnt == robotLevel) { + // 로봇의 레벨 늘려주기 + dieMonsterCnt = 0; + robotLevel++; + } + + // map에 있는 몬스터의 정보 없애주기 + levelMap[current.p.r][current.p.c] = 0; + monsterIdxMap[current.p.r][current.p.c] = 0; + + // 로봇 위치, map에 로봇 정보 갱신하기 + robot.r = current.p.r; + robot.c = current.p.c; + levelMap[current.p.r][current.p.c] = robotLevel; + + // 로봇이 이동한 위치 반환 + return current.d; + } + + for(int d = 0; d < 4; d++) { + int nr = current.p.r + dr[d]; + int nc = current.p.c + dc[d]; + + // 범위를 벗어나거나 || 이미 방문했던 곳이거나 || 자신의 레벨보다 큰 몬스터가 있거나 + if(!check(nr, nc) || v[nr][nc] || levelMap[nr][nc] > robotLevel) continue; + q.add(new qPoint(new Point(nr, nc), current.d + 1)); + v[nr][nc] = true; + } + } + + // 몬스터를 해치우지 못한 경우 + return 0; + } + + static boolean canKillMonster(Point current, int robotLevel) { + int monsterLevel = levelMap[current.r][current.c]; + return 0 < monsterLevel && monsterLevel < robotLevel; + } + + static boolean check(int r, int c) { + return 0 <= r && r < N && 0 <= c && c < N; + } + + static void initInput() throws Exception { + System.setIn(new FileInputStream("../AlgorithmStudy/input/전투로봇.txt")); + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StringTokenizer st; + + N = Integer.parseInt(br.readLine()); + levelMap = new int[N][N]; + monsterIdxMap = new int[N][N]; + + int idx = 1; + for(int r = 0; r < N; r++) { + st = new StringTokenizer(br.readLine()); + for(int c = 0; c < N; c++) { + levelMap[r][c] = Integer.parseInt(st.nextToken()); + if(levelMap[r][c] == 9) { + robot = new Point(r, c); + levelMap[r][c] = 2; // 전투로봇의 초기 레벨: 2 + } + else if(levelMap[r][c] != 0) { + monsterIdxMap[r][c] = idx; + } + } + } + +// printRobotInfo(); +// printlevelMapInfo(); +// printMostersInfo(); + } + + static void printRobotInfo() { + System.out.println("robotInfo: " + robot.toString() + ", level: " + levelMap[robot.r][robot.c]); + } + + static void printlevelMapInfo() { + for(int r = 0; r < N; r++) { + System.out.println(Arrays.toString(levelMap[r])); + } + + System.out.println(); + } +} diff --git a/Programmers/Level3/DH_118668.java b/Programmers/Level3/DH_118668.java new file mode 100644 index 00000000..956381fd --- /dev/null +++ b/Programmers/Level3/DH_118668.java @@ -0,0 +1,61 @@ +import java.util.*; + +public class DH_118668 { + static public int solution(int alp, int cop, int[][] problems) { + int answer = 0, maxAlpReq = 0, maxCopReq = 0; + + for(int i = 0; i < problems.length; i++) { + maxAlpReq = Math.max(problems[i][0], maxAlpReq); + maxCopReq = Math.max(problems[i][1], maxCopReq); + } + + // dp[r][c]: 알고력이 r이고, 코딩력이 c가 되기 위해서 걸리는 최소 시간 + int[][] dp = new int[maxAlpReq + 1][maxCopReq + 1]; + + for(int r = 0; r < dp.length; r++) Arrays.fill(dp[r], Integer.MAX_VALUE); + + // alp와 cop가 이미 최댓값을 넘었을 수도 있기 때문에 값 조정 + alp = Math.min(alp, maxAlpReq); + cop = Math.min(cop, maxCopReq); + + dp[alp][cop] = 0; + + for(int r = alp; r < dp.length; r++) { + for(int c = cop; c < dp[0].length; c++) { + // 알고리즘을 공부해서 알고력을 1 높이는 경우 + if(r + 1 < dp.length) dp[r + 1][c] = Math.min(dp[r + 1][c], dp[r][c] + 1); + + // 코딩 공부를 해서 코딩력을 1 높이는 경우 + if(c + 1 < dp[0].length) dp[r][c + 1] = Math.min(dp[r][c + 1], dp[r][c] + 1); + + // 풀 수 있는 문제를 하나 풀어 알고력과 코딩력을 높이는 경우 + for(int k = 0; k < problems.length; k++) { + int alpReq = problems[k][0]; // 문제를 풀기 위해 필요한 알고력 + int copReq = problems[k][1]; // 문제를 풀기 위해 필요한 코딩력 + int alpRwd = problems[k][2]; // 문제를 풀었을 때 증가하는 알고력 + int copRwd = problems[k][3]; // 문제를 풀었을 때 증가하는 코딩력 + int cost = problems[k][4]; //문제를 푸는데 드는 시간 + + if(r < alpReq || c < copReq) continue; // 현재 알고력이나 코딩력이 부족한 경우 + + // 범위를 벗어나는 경우 continue를 하면 오답! + // 범위를 벗어나면 무조건 문제를 풀 수 있는 것이기 때문에 maxAlpReq, maxCopReq가 된 것이라고 생각해야 됨 + // if(dp.length < r + alpRwd || maxCopReq < c + copRwd) continue; // 범위를 벗어가는 경우 + // dp[r + alpRwd][c + copRwd] = Math.min(dp[r + alpRwd][c + copRwd], dp[r][c] + cost); + int nextAlp = Math.min(maxAlpReq, r + alpRwd); + int nextCop = Math.min(maxCopReq, c + copRwd); + + dp[nextAlp][nextCop] = Math.min(dp[nextAlp][nextCop], dp[r][c] + cost); + } + } + } + + answer = dp[maxAlpReq][maxCopReq]; + return answer; + } + public static void main(String[] args) { + int alp = 10, cop = 10; + int[][] problems = {{10, 15, 2, 1, 2}, {20, 20, 3, 3, 4}}; + System.out.println(solution(alp, cop, problems)); + } +} diff --git a/Programmers/Level3/DH_64062.java b/Programmers/Level3/DH_64062.java new file mode 100644 index 00000000..5f7c5bcd --- /dev/null +++ b/Programmers/Level3/DH_64062.java @@ -0,0 +1,39 @@ + +/* + * 징검다리 건너기 + */ + +public class DH_64062 { + static int solution(int[] stones, int k) { + // 돌을 건넌 사람의 최대 수 구하기 - upper bound 구하기 + int s = 0, e = 200_000_001; + + while(s <= e) { + // 돌을 건넌 친구 수 + int m = (s + e) / 2; + + int cnt = 0; + + // 친구들이 모두 길을 건넜을 때 + // 값이 0이하가 되는 곳이 k개 이상이 된다면 못건너감 + boolean canGo = true; + for(int stone: stones) { + if(stone - m < 0) cnt++; + else cnt = 0; + + if(cnt >= k) canGo = false; + } + + if(canGo) s = m + 1; + else e = m - 1; + } + + return e; + } + + public static void main(String[] args) { + int[] stones = {2, 4, 5, 3, 2, 1, 4, 2, 5, 1}; + int k = 3; + System.out.println(solution(stones, k)); + } +} diff --git "a/SQL/09\354\243\274\354\260\250/DH_\354\236\205\354\226\221 \354\213\234\352\260\201 \352\265\254\355\225\230\352\270\260(2).sql" "b/SQL/09\354\243\274\354\260\250/DH_\354\236\205\354\226\221 \354\213\234\352\260\201 \352\265\254\355\225\230\352\270\260(2).sql" new file mode 100644 index 00000000..77746c54 --- /dev/null +++ "b/SQL/09\354\243\274\354\260\250/DH_\354\236\205\354\226\221 \354\213\234\352\260\201 \352\265\254\355\225\230\352\270\260(2).sql" @@ -0,0 +1,12 @@ +WITH RECURSIVE TMP AS ( + (SELECT 0 HOUR) + UNION ALL + (SELECT HOUR + 1 FROM TMP WHERE HOUR < 23) +) + +SELECT A.HOUR, IFNULL(B.COUNT, 0) `COUNT` +FROM TMP A LEFT JOIN ( + SELECT HOUR(DATETIME) `HOUR`, COUNT(HOUR(DATETIME)) `COUNT` + FROM ANIMAL_OUTS + GROUP BY HOUR(DATETIME) +) B ON A.HOUR = B.HOUR \ No newline at end of file diff --git "a/SQL/09\354\243\274\354\260\250/\354\230\244\355\224\204\353\235\274\354\235\270, \354\230\250\353\235\274\354\235\270 \355\214\220\353\247\244 \353\215\260\354\235\264\355\204\260 \355\206\265\355\225\251\355\225\230\352\270\260.sql" "b/SQL/09\354\243\274\354\260\250/\354\230\244\355\224\204\353\235\274\354\235\270, \354\230\250\353\235\274\354\235\270 \355\214\220\353\247\244 \353\215\260\354\235\264\355\204\260 \355\206\265\355\225\251\355\225\230\352\270\260.sql" new file mode 100644 index 00000000..715ae591 --- /dev/null +++ "b/SQL/09\354\243\274\354\260\250/\354\230\244\355\224\204\353\235\274\354\235\270, \354\230\250\353\235\274\354\235\270 \355\214\220\353\247\244 \353\215\260\354\235\264\355\204\260 \355\206\265\355\225\251\355\225\230\352\270\260.sql" @@ -0,0 +1,14 @@ +WITH TMP AS ( + SELECT SALES_DATE, PRODUCT_ID, NULL `USER_ID`, SALES_AMOUNT + FROM OFFLINE_SALE + WHERE SALES_DATE LIKE '2022-03%' + UNION ALL + SELECT SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT + FROM ONLINE_SALE + WHERE SALES_DATE LIKE '2022-03%' +) + +SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d') `SALES_DATE`, PRODUCT_ID, USER_ID, SALES_AMOUNT +FROM TMP +WHERE SALES_DATE LIKE '2022-03%' +ORDER BY SALES_DATE, PRODUCT_ID, USER_ID \ No newline at end of file