Skip to content
91 changes: 91 additions & 0 deletions BOJ/1000-5000번/JW_1194.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;

public class JW_1194 {

static int n, m;
static char[][] board;

static int[] dy = { 1, -1, 0, 0 };
static int[] dx = { 0, 0, 1, -1 };

public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
board = new char[n][m];
int sy = 0, sx = 0;
for (int i = 0; i < n; i++) {
String line = br.readLine();
for (int j = 0; j < m; j++) {
board[i][j] = line.charAt(j);
// 초기 위치 설정
if (board[i][j] == '0') {
sy = i;
sx = j;
}
}
}
// 열쇠 상태에 따라 방문 체크를 해주기 위해서 3차원 방문 체크 생성
boolean[][][] visited = new boolean[n][m][1 << 6];
Deque<int[]> dq = new ArrayDeque<>();
dq.offer(new int[] { sy, sx, 0, 0 });
visited[sy][sx][0] = true;

// BFS
while (!dq.isEmpty()) {
int[] cur = dq.poll();
// 현재 좌표, 열쇠 상태, 움직임 횟수
int y = cur[0], x = cur[1], keys = cur[2], moveCnt = cur[3];
// 종료 조건
if (board[y][x] == '1') {
System.out.println(moveCnt);
return;
}
for (int i = 0; i < 4; i++) {
int ny = y + dy[i], nx = x + dx[i];
int newKeys = keys;

// 이동 조건
if (!isValid(ny, nx) || board[ny][nx] == '#') {
continue;
}

// 열쇠일 경우
if (isKey(ny, nx))
// 해당 열쇠 추가
newKeys |= (1 << (board[ny][nx] - 'a'));

// 문일 경우, 열쇠가 없다면 이동 불가
else if (isDoor(ny, nx) && (keys & (1 << (board[ny][nx] - 'A'))) == 0)
continue;

// 현재 열쇠 상태에서 방문하지 않았다면 방문
if (!visited[ny][nx][newKeys]) {
dq.offer(new int[] { ny, nx, newKeys, moveCnt + 1 });
visited[ny][nx][newKeys] = true;
}
}
}
System.out.println(-1);
}

// 열쇠 체크
private static boolean isKey(int y, int x) {
return 'a' <= board[y][x] && board[y][x] <= 'f';
}

// 문 체크
private static boolean isDoor(int y, int x) {
return 'A' <= board[y][x] && board[y][x] <= 'F';
}

// 경계 체크
private static boolean isValid(int y, int x) {
return 0 <= y && y < n && 0 <= x && x < m;
}
}
31 changes: 31 additions & 0 deletions BOJ/1000-5000번/JW_1749.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
public class JW_1749 {

public static void main(String[] args) throws Exception {
int n = read(), m = read(), max = Integer.MIN_VALUE;
int[][] dp = new int[n + 1][m + 1];
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < m + 1; j++)
// (i, j)까지의 누적합
dp[i][j] = read() + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];
for (int i = 1; i < n + 1; i++)
for (int j = 1; j < m + 1; j++)
for (int k = 1; k < i + 1; k++)
for (int l = 1; l < j + 1; l++) {
// 부분 배열의 누적합 구하기
max = Math.max(max, dp[i][j] - dp[k - 1][j] - dp[i][l - 1] + dp[k - 1][l - 1]);
}
System.out.println(max);
}

private static int read() throws Exception {
int c, n = System.in.read() & 15;
boolean m = n == 13;
if (m)
n = System.in.read() & 15;
while ((c = System.in.read()) >= 48)
n = (n << 3) + (n << 1) + (c & 15);
if (c == 13)
System.in.read();
return m ? ~n + 1 : n;
}
}
37 changes: 37 additions & 0 deletions BOJ/5001-10000번/JW_8979.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import java.util.Arrays;

public class JW_8879 {

public static void main(String[] args) throws Exception {
int n = read(), k = read();
int[][] arr = new int[n][4];
for (int i = 0; i < n; i++)
arr[i] = new int[] { read(), read(), read(), read() };
// 정렬
Arrays.sort(arr, (o1, o2) -> o2[1] != o1[1] ? o2[1] - o1[1] : o2[2] != o1[2] ? o2[2] - o1[2] : o2[3] - o1[3]);
int rank = 1;
for (int i = 0; i < n; i++) {
// 등수 증가 조건
if (i > 0 && !isSame(arr[i - 1], arr[i]))
rank = i + 1;
// 종료 조건
if (arr[i][0] == k)
break;
}
System.out.println(rank);
}

// 동일 점수 확인
private static boolean isSame(int[] A, int[] B) {
return A[1] == B[1] && A[2] == B[2] && A[3] == B[3];
}

private static int read() throws Exception {
int c, n = System.in.read() & 15;
while ((c = System.in.read()) >= 48)
n = (n << 3) + (n << 1) + (c & 15);
if (c == 13)
System.in.read();
return n;
}
}
91 changes: 91 additions & 0 deletions CodeTree/2019-2020년/JW_술래잡기_체스.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class JW_술래잡기_체스 {

static int[] dy = { 0, -1, -1, 0, 1, 1, 1, 0, -1 };
static int[] dx = { 0, 0, -1, -1, -1, 0, 1, 1, 1 };
static int max = 0;

public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int[][][] board = new int[4][4][2];
for (int i = 0; i < 4; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 4; j++) {
int p = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
board[i][j] = new int[] { p, d };
}
}
policeMove(0, 0, 0, board);
System.out.println(max);
}

// 경찰 이동(재귀)
private static void policeMove(int sum, int y, int x, int[][][] board) {
sum += board[y][x][0]; // 해당 좌표의 값을 합
max = Math.max(max, sum); // 최댓값 갱신
board[y][x][0] = 0; // 해당 좌표의 값을 초기화
int d = board[y][x][1]; // 해당 좌표의 방향
doDookMove(y, x, board); // 도둑 이동
// 경찰이 이동할 수 있는 방향을 모두 재귀적으로 탐색
for (int i = 1; i <= 3; i++) {
int ny = y + dy[d] * i, nx = x + dx[d] * i;
// 이동할 수 있다면
if (isValid(ny, nx) && board[ny][nx][0] != 0) {
int[][][] nextBoard = copyBoard(board);
policeMove(sum, ny, nx, nextBoard); // 재귀 호출
}
}
}

// 도둑 이동
private static void doDookMove(int py, int px, int[][][] board) {
// 순서에 따라서 이동
next: for (int p = 1; p <= 16; p++) {
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
// 순서에 맞는 좌표를 찾았다면
if (board[y][x][0] == p) {
int d = board[y][x][1];
int ny = y + dy[d], nx = x + dx[d];
// 이동할 수 있는 좌표가 등장할 때까지 회전
while (!isValid(ny, nx) || (ny == py && nx == px)) {
d++;
d %= 9;
if (d == 0)
d = 1;
ny = y + dy[d];
nx = x + dx[d];
}
swap(y, x, ny, nx, board); // 스왑
board[ny][nx][1] = d; // 새로운 방향으로 변경
continue next; // 발견했다면 다음 순서 진행
}
}
}

// 두 좌표에 있는 원소를 스왑해주는 함수
private static void swap(int y, int x, int ny, int nx, int[][][] board) {
int[] temp = board[y][x];
board[y][x] = board[ny][nx];
board[ny][nx] = temp;
}

// 기존의 배열을 복사하여 다음 배열을 만들어주는 함수
private static int[][][] copyBoard(int[][][] board) {
int[][][] nextBord = new int[4][4][2];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
nextBord[i][j] = board[i][j].clone();
return nextBord;
}

// 경계 체크 함수
private static boolean isValid(int y, int x) {
return 0 <= y && y < 4 && 0 <= x && x < 4;
}
}
62 changes: 62 additions & 0 deletions Programmers/Level2/JW_250135.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
class Solution {
public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
int answer = 0;
int now = h1 * 3600 + m1 * 60 + s1;
int end = h2 * 3600 + m2 * 60 + s2;
// 시작부터 겹치고 시작할 경우
if (now == 0 || now == 43200)
answer++;
while (now < end) {
double[] nowAngles = calculateAndgles(now);
double[] nextAngles = calculateAndgles(now + 1);
boolean isHourMatched = chkHour(nowAngles, nextAngles);
boolean isMinMatched = chkMin(nowAngles, nextAngles);
if (isHourMatched)
answer++;
if (isMinMatched)
answer++;
// 둘 다 겹칠 경우에는 한번만 체크
if (isHourMatched && isMinMatched)
if (nextAngles[0] == nextAngles[1])
answer--;
now++;
}
return answer;
}

private double[] calculateAndgles(int time) {
double[] angles = new double[3];
double h = time / 3600, m = time % 3600 / 60, s = time % 3600 % 60;
// 시침의 현재 각도
angles[0] = (h % 12) * (360d / 12) + m * (360d / 12 / 60) + s * (360d / 12 / 3600);
// 분침의 현재 각도
angles[1] = m * (360d / 60) + s * (360d / 60 / 60);
// 초침의 현재 각도
angles[2] = s * (360d / 60);
return angles;
}

// 시침 겹침 확인
private boolean chkHour(double[] now, double[] next) {
double nowSec = now[2], nextSec = next[2];
// 1초의 움직임 안에 시침이 포함되는가
if (nowSec < now[0] && next[0] <= nextSec)
return true;
// 59초의 값은 따로 계산 → 원형이기에 각도가 0으로 초기화되기 때문
if (nowSec == 354d && 354d < now[0])
return true;
return false;
}

// 분침 겹침 확인
private boolean chkMin(double[] now, double[] next) {
double nowSec = now[2], nextSec = next[2];
// 1초의 움직임 안에 시침이 포함되는가
if (nowSec < now[1] && next[1] <= nextSec)
return true;
// 59초의 값은 따로 계산 → 원형이기에 각도가 0으로 초기화되기 때문
if (nowSec == 354d && 354d < now[1])
return true;
return false;
}
}
38 changes: 38 additions & 0 deletions Programmers/Level3/JW_150367.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class JW_150367 {
public int[] solution(long[] numbers) {
int[] answer = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
String str = toBinaryString(numbers[i]);
// 표현 가능한 포화 이진 트리일 경우 '1'
answer[i] = chkInOrder(str, 0, str.length() - 1) ? 1 : 0;
}
return answer;
}

// 포화 이진 트리 -> 문자열 길이가 2^n - 1 꼴이 되어야 함
private String toBinaryString(long number) {
StringBuilder sb = new StringBuilder(Long.toBinaryString(number));
int n = 1;
while (sb.length() > (1 << n) - 1) {
n++;
}
// 빈 부분 채우기
sb.insert(0, "0".repeat((1 << n) - 1 - sb.length()));
return sb.toString();
}

// 중위 탐색을 진행하면서 불가능한 트리인지 확인
private boolean chkInOrder(String str, int l, int r) {
// 리프노드 일 경우는 True
if (l == r)
return true;
int rootIdx = (l + r) / 2;
// 루트 노드가 0'일 경우에는 자식에 '1'이 있으면 안됨
if (str.charAt(rootIdx) == '0')
for (int i = l; i <= r; i++)
if (str.charAt(i) == '1')
return false;
// 다음 중위 탐색
return chkInOrder(str, l, rootIdx - 1) && chkInOrder(str, rootIdx + 1, r);
}
}
28 changes: 28 additions & 0 deletions SQL/13주차/JW_Product_Price_at_a_Given_Date.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
WITH CTE AS (
SELECT
product_id
, new_price
FROM
products
WHERE
(product_id, change_date) IN
(
SELECT
product_id
, MAX(change_date)
FROM
Products
WHERE
change_date <= '2019-08-16'
GROUP BY
product_id
)
)

SELECT
DISTINCT(A.product_id)
, IFNULL(B.new_price, 10) `price`
FROM
products A
LEFT JOIN CTE B
ON A.product_id = B.product_id
Loading