From 1d775f28a7c8cf1b8260ba0012bcca55cda03178 Mon Sep 17 00:00:00 2001 From: "YeJun, Jung" <31740224+yejun614@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:23:55 +0900 Subject: [PATCH 1/5] feat: add temp files --- problems/SWEA/p1952/Solution.java | 139 +++++++++ problems/SWEA/p1952/answer.txt | 10 + problems/SWEA/p1952/input.txt | 21 ++ problems/SWEA/p1952/output.txt | 9 + problems/SWEA/p2806/Solution.java | 144 +++++++++ problems/SWEA/p5648/Solution.java | 477 ++++++++++++++++++++++++++++++ problems/SWEA/p5648/answer.txt | 2 + problems/SWEA/p5648/input.txt | 7 + problems/SWEA/p5648/output.txt | 1 + 9 files changed, 810 insertions(+) create mode 100644 problems/SWEA/p1952/Solution.java create mode 100644 problems/SWEA/p1952/answer.txt create mode 100644 problems/SWEA/p1952/input.txt create mode 100644 problems/SWEA/p1952/output.txt create mode 100644 problems/SWEA/p2806/Solution.java create mode 100644 problems/SWEA/p5648/Solution.java create mode 100644 problems/SWEA/p5648/answer.txt create mode 100644 problems/SWEA/p5648/input.txt create mode 100644 problems/SWEA/p5648/output.txt diff --git a/problems/SWEA/p1952/Solution.java b/problems/SWEA/p1952/Solution.java new file mode 100644 index 0000000..7a9f8dc --- /dev/null +++ b/problems/SWEA/p1952/Solution.java @@ -0,0 +1,139 @@ +package swea.p1952; + +import java.io.*; +import java.util.*; + +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // -------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = Integer.parseInt(reader.readLine().trim()); + + for (int testCase = 1; testCase <= testCount; testCase++) { + new Solution(testCase).run(); + } + } + + // -------------------------------------------------------- + + static final int TICKET_TYPE_LEN = 4; + static final int MONTH_LEN = 12; + + static final int ONE_DAY_TICKET = 0; + static final int ONE_MONTH_TICKET = 1; + static final int THREE_MONTH_TICKET = 2; + static final int ONE_YEAR_TICKET = 3; + + int testCase; + int bestPrice; + + boolean noPlan; + int[] priceArr; + int[] planArr; + + int[] oneDayTicketArr; + boolean[] monthTicketArr; + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + getLine(); + priceArr = new int[TICKET_TYPE_LEN]; + for (int index = 0; index < TICKET_TYPE_LEN; index++) { + priceArr[index] = Integer.parseInt(input.nextToken()); + } + + getLine(); + noPlan = true; + planArr = new int[MONTH_LEN]; + for (int index = 0; index < MONTH_LEN; index++) { + planArr[index] = Integer.parseInt(input.nextToken()); + if (planArr[index] != 0) noPlan = false; + } + } + + private void solve() { + // 만약 이용계획이 없는 경우 bestPrice는 0이 된다. + if (noPlan) { + bestPrice = 0; + return; + } + + bestPrice = priceArr[ONE_YEAR_TICKET]; // 1년 이용권 + + oneDayTicketArr = new int[MONTH_LEN]; + monthTicketArr = new boolean[MONTH_LEN]; + + searchBestPrice(0, 0); + } + + private void searchBestPrice(int month, int currentPrice) { + while ( (month < MONTH_LEN) && + (oneDayTicketArr[month] >= planArr[month]) + ) { + System.out.println("WOW"); + month++; + } + + // 기저조건 + if (month >= MONTH_LEN) { + if (currentPrice < bestPrice) bestPrice = currentPrice; + return; + } + + int price; + + // 1일 이용권 + price = currentPrice + priceArr[ONE_DAY_TICKET]; + if (price < bestPrice) { + oneDayTicketArr[month]++; + if (oneDayTicketArr[month] >= planArr[month]) { + searchBestPrice(month + 1, price); + } else { + searchBestPrice(month, price); + } + oneDayTicketArr[month]--; + } + + // 1달 이용권 + price = currentPrice + priceArr[ONE_MONTH_TICKET]; + if (price < bestPrice) { + monthTicketArr[month] = true; + searchBestPrice(month + 1, price); + monthTicketArr[month] = false; + } + + // 3달 이용권 + price = currentPrice + priceArr[THREE_MONTH_TICKET]; + if (price < bestPrice) { + for (int m = month; m < month + 2 && m < MONTH_LEN; m++) monthTicketArr[m] = true; + searchBestPrice(month + 3, price); + for (int m = month; m < month + 2 && m < MONTH_LEN; m++) monthTicketArr[m] = false; + } + } + + private void print() throws IOException { + writer.write("#" + testCase); + writer.write(" " + bestPrice); + writer.write("\n"); + writer.flush(); + } + + // -------------------------------------------------------- + + private void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } +} diff --git a/problems/SWEA/p1952/answer.txt b/problems/SWEA/p1952/answer.txt new file mode 100644 index 0000000..8e2c28a --- /dev/null +++ b/problems/SWEA/p1952/answer.txt @@ -0,0 +1,10 @@ +#1 110 +#2 100 +#3 400 +#4 530 +#5 430 +#6 1080 +#7 1840 +#8 800 +#9 1980 +#10 2260 diff --git a/problems/SWEA/p1952/input.txt b/problems/SWEA/p1952/input.txt new file mode 100644 index 0000000..2a44a02 --- /dev/null +++ b/problems/SWEA/p1952/input.txt @@ -0,0 +1,21 @@ +10 +10 40 100 300 +0 0 2 9 1 5 0 0 0 0 0 0 +10 100 50 300 +0 0 0 0 0 0 0 0 6 2 7 8 +10 70 180 400 +6 9 7 7 7 5 5 0 0 0 0 0 +10 70 200 550 +0 0 0 0 8 9 6 9 6 9 8 6 +10 80 200 550 +0 8 9 15 1 13 2 4 9 0 0 0 +10 130 360 1200 +0 0 0 15 14 11 15 13 12 15 10 15 +10 180 520 1900 +0 18 16 16 19 19 18 18 15 16 17 16 +10 100 200 1060 +12 9 11 13 11 8 6 12 8 7 15 6 +10 170 500 1980 +19 18 18 17 15 19 19 16 19 15 17 18 +10 200 580 2320 +12 28 24 24 29 25 23 26 26 28 27 22 diff --git a/problems/SWEA/p1952/output.txt b/problems/SWEA/p1952/output.txt new file mode 100644 index 0000000..7656bfa --- /dev/null +++ b/problems/SWEA/p1952/output.txt @@ -0,0 +1,9 @@ +#1 100 +#2 50 +#3 180 +#4 200 +#5 200 +#6 360 +#7 520 +#8 200 +#9 500 diff --git a/problems/SWEA/p2806/Solution.java b/problems/SWEA/p2806/Solution.java new file mode 100644 index 0000000..60a56f5 --- /dev/null +++ b/problems/SWEA/p2806/Solution.java @@ -0,0 +1,144 @@ +package swea.p2806; + +import java.io.*; +import java.util.*; + +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + + // -------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = Integer.parseInt(reader.readLine().trim()); + + for (int testCase = 1; testCase <= testCount; testCase++) { + new Solution(testCase).run(); + } + } + + // -------------------------------------------------------- + + final static int[] QUEEN_DIR_X = { 0, 1, 1, 1, 0, -1, -1, -1 }; + final static int[] QUEEN_DIR_Y = { -1, -1, 0, 1, 1, 1, 0, -1 }; + final static int QUEEN_DIR_LEN = 8; + + int testCase; + int answer; + + int N; + int[][] board; + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + N = Integer.parseInt(reader.readLine().trim()); + } + + private void solve() { + answer = 0; + board = new int[N][N]; + + search(N, 0); + } + + private void search(int nQueen, int y) { + // 기저조건 + if (nQueen == 0) { + answer++; + return; + } + + for (int cy = y; cy < N; cy++) { + for (int cx = 0; cx < N; cx++) { + if (!putQueen(cx, cy)) continue; + + search(nQueen - 1, cy + 1); + + removeQueen(cx, cy); + } + } + } + + private boolean putQueen(int x, int y) { + if (board[y][x] != 0) return false; + + boolean available = true; + int count = 0; + + for (int dir = 0; dir < QUEEN_DIR_LEN; dir++) { + int cx = x + QUEEN_DIR_X[dir]; + int cy = y + QUEEN_DIR_Y[dir]; + + while (isInsideBoard(cx, cy)) { + if (board[cy][cx] < 0) { + available = false; + break; + } + + board[cy][cx]++; + count++; + + cx += QUEEN_DIR_X[dir]; + cy += QUEEN_DIR_Y[dir]; + } + } + + // rollback + if (!available) { + for (int dir = 0; dir < QUEEN_DIR_LEN && count > 0; dir++) { + int cx = x + QUEEN_DIR_X[dir]; + int cy = y + QUEEN_DIR_Y[dir]; + + while (isInsideBoard(cx, cy)) { + board[cy][cx]--; + count--; + + cx += QUEEN_DIR_X[dir]; + cy += QUEEN_DIR_Y[dir]; + } + } + } + + board[y][x] = -1; + + return true; + } + + private void removeQueen(int x, int y) { + board[y][x] = 0; + + for (int dir = 0; dir < QUEEN_DIR_LEN; dir++) { + int cx = x + QUEEN_DIR_X[dir]; + int cy = y + QUEEN_DIR_Y[dir]; + + while (isInsideBoard(cx, cy)) { + board[cy][cx]--; + + cx += QUEEN_DIR_X[dir]; + cy += QUEEN_DIR_Y[dir]; + } + } + } + + private boolean isInsideBoard(int x, int y) { + return x >= 0 && x < N && y >= 0 && y < N; + } + + private void print() throws IOException { + writer.write("#" + testCase); + writer.write(" " + answer); + writer.write("\n"); + writer.flush(); + } + + // -------------------------------------------------------- +} diff --git a/problems/SWEA/p5648/Solution.java b/problems/SWEA/p5648/Solution.java new file mode 100644 index 0000000..297212a --- /dev/null +++ b/problems/SWEA/p5648/Solution.java @@ -0,0 +1,477 @@ +package swea.p5648; + +import java.io.*; +import java.util.*; + +public class Solution { + static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); + static StringTokenizer input; + + // -------------------------------------------------------- + + public static void main(String[] args) throws IOException { + final int testCount = Integer.parseInt(reader.readLine().trim()); + + for (int testCase = 1; testCase <= testCount; testCase++) { + new Solution(testCase).run(); + } + } + + // -------------------------------------------------------- + + int testCase; + int raisedEnergy; + + int atomCount; + List atomList; + + public Solution(int testCase) { + this.testCase = testCase; + } + + public void run() throws IOException { + input(); + solve(); + print(); + } + + private void input() throws IOException { + atomCount = Integer.parseInt(reader.readLine().trim()); + atomList = new ArrayList<>(atomCount); + + for (int count = 0; count < atomCount; count++) { + atomList.add(Atom.fromReader(reader)); + } + } + + private void solve() { +// System.out.println("--------------------------------------"); + raisedEnergy = 0; + +// runSimutation(); + updateAllCollisions(); + } + + private void updateAllCollisions() { + for (int A = 0; A < atomCount; A++) { + + Atom atomA = atomList.get(A); + + if (atomA.energy == 0) continue; + + List checkList = new ArrayList<>(atomCount); + + for (int B = 0; B < atomCount; B++) { + if (A == B) continue; + + Atom atomB = atomList.get(B); + if (atomB.energy == 0) continue; + +// if (atomA.isPredictedCollision(atomB)) { + if (getCollisionTimeIfPossible(atomA, atomB) != Double.MAX_VALUE) { +// System.out.printf("%d : %d\n", A, B); + checkList.add(atomB); + } + } + + if (checkList.size() == 0) continue; + + Collections.sort(checkList, (Atom sortA, Atom sortB) -> { +// double time1 = atomA.getCollisionTime(sortA); +// double time2 = atomA.getCollisionTime(sortB); + + double time1 = getCollisionTimeIfPossible(atomA, sortA); + double time2 = getCollisionTimeIfPossible(atomA, sortB); + + return Double.compare(time1, time2); + }); + + raisedEnergy += atomA.destroy(); + raisedEnergy += checkList.get(0).destroy(); + } + } + + private double getCollisionTimeIfPossible(Atom a, Atom b) { + int dx = b.x - a.x; + int dy = b.y - a.y; + + // 1. 마주보는 경우 (정수 시간 또는 .5초 시간) + if (a.x == b.x) { // 세로선상 + if (dy > 0 && a.dir == Atom.Direction.UP && b.dir == Atom.Direction.DOWN) return dy / 2.0; + if (dy < 0 && a.dir == Atom.Direction.DOWN && b.dir == Atom.Direction.UP) return Math.abs(dy) / 2.0; + } + if (a.y == b.y) { // 가로선상 + if (dx > 0 && a.dir == Atom.Direction.RIGHT && b.dir == Atom.Direction.LEFT) return dx / 2.0; + if (dx < 0 && a.dir == Atom.Direction.LEFT && b.dir == Atom.Direction.RIGHT) return Math.abs(dx) / 2.0; + } + + // 2. 직각 충돌 (반드시 dx == dy 여야 함) + if (Math.abs(dx) == Math.abs(dy)) { + double time = Math.abs(dx); + // A가 우측으로 갈 때 + if (a.dir == Atom.Direction.RIGHT) { + if (dx > 0 && ((dy > 0 && b.dir == Atom.Direction.DOWN) || (dy < 0 && b.dir == Atom.Direction.UP))) return time; + } + // A가 좌측으로 갈 때 + if (a.dir == Atom.Direction.LEFT) { + if (dx < 0 && ((dy > 0 && b.dir == Atom.Direction.DOWN) || (dy < 0 && b.dir == Atom.Direction.UP))) return time; + } + // A가 위로 갈 때 + if (a.dir == Atom.Direction.UP) { + if (dy > 0 && ((dx > 0 && b.dir == Atom.Direction.LEFT) || (dx < 0 && b.dir == Atom.Direction.RIGHT))) return time; + } + // A가 아래로 갈 때 + if (a.dir == Atom.Direction.DOWN) { + if (dy < 0 && ((dx > 0 && b.dir == Atom.Direction.LEFT) || (dx < 0 && b.dir == Atom.Direction.RIGHT))) return time; + } + } + + return Double.MAX_VALUE; // 충돌 불가 + } + + private void runSimutation() { + // 종료 조건: 원자들의 위치는 -1000 ~ 1000이기 때문에 2000번만 반복하고 종료하면 됨 + final int last = 4000; + + for (int count = 0; count < last; count++) { + if (nextStep2() == 0) break; + } + } + + // -3000 ~ 3000 범위를 커버하기 위한 6001 크기의 배열 + static int[][] map = new int[6001][6001]; + private final int OFFSET = 3000; + + private int nextStep2() { + int activeAtoms = 0; + + // 1. 모든 원자 이동 및 맵 기록 + for (Atom atom : atomList) { + if (atom.energy == 0) continue; + + atom.moveNext2(); + + // 이론적 최대 범위 (-3000 ~ 3000) 내에서 인덱싱 + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; + + // 만약 이 범위를 벗어난다면 그 원자는 영원히 누구와도 만날 수 없음 + if (mx < 0 || mx > 6000 || my < 0 || my > 6000) { + atom.energy = 0; + continue; + } + + activeAtoms++; + map[mx][my] += atom.energy; + } + + if (activeAtoms <= 1) { + clearMap(); + return 0; + } + + // 2. 충돌 판정 + for (Atom atom : atomList) { + if (atom.energy == 0) continue; + + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; + + if (map[mx][my] > atom.energy) { + raisedEnergy += atom.energy; + atom.energy = 0; + } + } + + // 3. 맵 청소 + clearMap(); + + return activeAtoms; + } + + private void clearMap() { + for (Atom atom : atomList) { + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; + if (mx >= 0 && mx <= 6000 && my >= 0 && my <= 6000) { + map[mx][my] = 0; + } + } + } + + private int nextStep() { + // 각 원자들의 이동 벡터를 [시작, 종료]로 기록 + // 서로 다른 벡터들의 [시작, 종료]가 겹치면 해당 원소는 에너지를 모두 발산하고 소멸 + + List vecList = new ArrayList<>(atomCount); + int vecLen = 0; + + for (int atomIndex = 0; atomIndex < atomCount; atomIndex++) { + Atom atom = atomList.get(atomIndex); + if (atom.energy == 0) continue; + + vecList.add(atom.moveNext()); +// System.out.println(atomIndex + " " + atom); + vecLen++; + } + + for (int A = 0; A < vecLen; A++) { + for (int B = 0; B < vecLen; B++) { + if (A == B) continue; + + Vec vecA = vecList.get(A); + Vec vecB = vecList.get(B); + + if (vecA.isCollision(vecB) || vecA.isEqualPos(vecB)) { + raisedEnergy += atomList.get(A).destroy(); + raisedEnergy += atomList.get(B).destroy(); +// System.out.printf("[collision] %d : %d -> %d\n", A, B, raisedEnergy); + } + } + } + + return vecLen; + } + + private void print() throws IOException { + writer.write("#" + testCase); + writer.write(" " + raisedEnergy); + writer.write("\n"); + writer.flush(); + } + + // -------------------------------------------------------- + + static class Atom { + enum Direction { + UP, + DOWN, + LEFT, + RIGHT + } + + static final int[] DIR_X = { 0, 0, -1, 1 }; + static final int[] DIR_Y = { 1, -1, 0, 0 }; + + int x; + int y; + Direction dir; + int energy; + + public Atom(int x, int y, Direction dir, int energy) { + this.x = x; + this.y = y; + this.dir = dir; + this.energy = energy; + } + + public static Atom fromReader(BufferedReader reader) throws IOException { + getLine(); + int x = Integer.parseInt(input.nextToken()) * 2; // WOW + int y = Integer.parseInt(input.nextToken()) * 2; // WOW + int dir = Integer.parseInt(input.nextToken()); + int energy = Integer.parseInt(input.nextToken()); + + Direction eDir = Direction.UP; + switch (dir) { + case 0: + eDir = Direction.UP; + break; + case 1: + eDir = Direction.DOWN; + break; + case 2: + eDir = Direction.LEFT; + break; + case 3: + eDir = Direction.RIGHT; + break; + } + + return new Atom(x, y, eDir, energy); + } + + public Vec moveNext() { + int nextX = x + DIR_X[dir.ordinal()]; + int nextY = y + DIR_Y[dir.ordinal()]; + + Vec vec = new Vec(x, y, nextX, nextY); + + x = nextX; + y = nextY; + + return vec; + } + + public void moveNext2() { + int nextX = x + DIR_X[dir.ordinal()]; + int nextY = y + DIR_Y[dir.ordinal()]; + + x = nextX; + y = nextY; + } + + public Atom moveNextAtom() { + int nextX = x + DIR_X[dir.ordinal()]; + int nextY = y + DIR_Y[dir.ordinal()]; + + return new Atom(nextX, nextY, dir, energy); + } + + public int destroy() { + int returnEnergy = energy; + energy = 0; + + return returnEnergy; + } + + public double getCollisionTime(Atom another) { + return getDistance(another); + } + + public boolean isPredictedCollision(Atom another) { + // x좌표가 같은데, 방향이 마주보는 경우 + // y좌표가 같은데, 방향이 마주보는 경우 + // abs(A.y - B.y) == abs(A.x - B.x) 인 경우 + + if (this.x == another.x && isSameOriginDirectionVertical(another)) { + return true; + } else if (this.y == another.y && isSameOriginDirectionHorizontal(another)) { + return true; + } else if (Math.abs(this.x - another.x) == Math.abs(this.y - another.y) && + isSameOriginDirectionCross(another) + ) { + return true; + } + + return false; + } + + public boolean isSameOriginDirectionCross(Atom another) { +// Atom next = moveNextAtom(); +// return next.getDistance(another) < this.getDistance(another); + + Atom atomA = this; + Atom atomB = another; + + if (atomA.dir == Direction.UP || atomA.dir == Direction.DOWN) { + Atom temp = atomA; + atomA = atomB; + atomB = temp; + } + + if (atomA.y < atomB.y) { + if (atomB.dir != Direction.DOWN) return false; + } else if (atomB.y < atomA.y) { + if (atomB.dir != Direction.UP) return false; + } + + if (atomA.x < atomB.x) { + if (atomA.dir != Direction.RIGHT) return false; + } else if (atomB.x < atomA.x) { + if (atomA.dir != Direction.LEFT) return false; + } + + return true; + } + + public boolean isSameOriginDirectionHorizontal(Atom another) { + boolean result = false; + + result |= (this.dir == Direction.LEFT && another.dir == Direction.RIGHT); + result |= (this.dir == Direction.RIGHT && another.dir == Direction.LEFT); + + return result; + } + + public boolean isSameOriginDirectionVertical(Atom another) { + boolean result = false; + + result |= (this.dir == Direction.UP && another.dir == Direction.DOWN); + result |= (this.dir == Direction.DOWN && another.dir == Direction.UP); + + return result; + } + + public int getDistance(Atom another) { + int result = 0; + + result += Math.max(this.x, another.x) - Math.min(this.x, another.x); + result += Math.max(this.y, another.y) - Math.min(this.y, another.y); + + return result; + } + + @Override + public String toString() { + return String.format("[x=%d, y=%d, dir=%d, energy=%d]", x, y, dir, energy); + } + } + + // -------------------------------------------------------- + + static class Vec { + int beginX; + int beginY; + int endX; + int endY; + + public Vec(int beginX, int beginY, int endX, int endY) { + this.beginX = beginX; + this.beginY = beginY; + this.endX = endX; + this.endY = endY; + } + + public boolean isCollision(Vec another) { + // AABB Collision Detection Algorithm + // (상하좌우로만 움직이기 때문에 AABB 활용 가능) + + boolean result = false; + + result |= another.beginX <= this.beginX && another.endX <= this.beginX; + result |= this.endX <= another.beginX && this.endX <= another.endX; + + result |= another.beginY <= this.beginY && another.endY <= this.beginY; + result |= this.endY <= another.beginY && this.endY <= another.endY; + +// System.out.printf("isCollision (%d:%d, %d:%d) - (%d:%d, %d:%d) %s\n", beginX, endX, beginY, endY, another.beginX, another.endX, another.beginY, another.endY, !result); + + return !result; + } + + public boolean isEqualPos(Vec another) { + return this.endX == another.endX && this.endY == another.endY; + } + } + + // -------------------------------------------------------- + + static class Pos { + double x; + double y; + + public Pos(double x, double y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + Pos another = (Pos)obj; + return this.x == another.x && this.y == another.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + } + + // -------------------------------------------------------- + + private static void getLine() throws IOException { + input = new StringTokenizer(reader.readLine().trim()); + } +} diff --git a/problems/SWEA/p5648/answer.txt b/problems/SWEA/p5648/answer.txt new file mode 100644 index 0000000..b69abc4 --- /dev/null +++ b/problems/SWEA/p5648/answer.txt @@ -0,0 +1,2 @@ +#1 24 +#2 0 \ No newline at end of file diff --git a/problems/SWEA/p5648/input.txt b/problems/SWEA/p5648/input.txt new file mode 100644 index 0000000..542efc0 --- /dev/null +++ b/problems/SWEA/p5648/input.txt @@ -0,0 +1,7 @@ +1 +5 +-2 0 3 3 +-1 0 3 2 +0 0 2 5 +1 0 2 4 +0 -1 0 6 diff --git a/problems/SWEA/p5648/output.txt b/problems/SWEA/p5648/output.txt new file mode 100644 index 0000000..97e50df --- /dev/null +++ b/problems/SWEA/p5648/output.txt @@ -0,0 +1 @@ +#1 14 From cc74590698236454497026f2e8949071873e8b94 Mon Sep 17 00:00:00 2001 From: "YeJun, Jung" Date: Wed, 11 Feb 2026 09:21:24 +0900 Subject: [PATCH 2/5] fix: swea p5648 solution --- problems/SWEA/p5648/Solution.java | 478 +++++++----------------------- 1 file changed, 112 insertions(+), 366 deletions(-) diff --git a/problems/SWEA/p5648/Solution.java b/problems/SWEA/p5648/Solution.java index 297212a..62a560e 100644 --- a/problems/SWEA/p5648/Solution.java +++ b/problems/SWEA/p5648/Solution.java @@ -1,8 +1,45 @@ -package swea.p5648; +/* + * (5648) [모의 SW 역량테스트] 원자 소멸 시뮬레이션 + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRFInKex8DFAUo&categoryId=AWXRFInKex8DFAUo&categoryType=CODE&problemTitle=5648&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ import java.io.*; import java.util.*; +/** + * SW Expert Academy - 5648. [모의 SW 역량테스트] 원자 소멸 시뮬레이션 + * @author YeJun, Jung + * + * @see #main(String[] args) + * 1. 테스트케이스를 입력받는다. + * 2. 솔루션을 실행한다. + * + * @see #input() + * 3. 원자 개수를 입력받는다. + * 4. 원자 목록을 보관할 리스트 atomList를 초기화한다. + * 5. 원자들을 입력받아 atomList에 저장한다. + * + * @see #solve() + * 6. 멤버변수를 초기화한다. + * 7. 시뮬레이션을 시작한다. + * + * @see #runSimuration() + * 8. 이론상 가능한 최대 횟수만큼 시뮬레이션을 실시하되, 모든 원자가 충돌하여 + * 시뮬레이션할 원자가 없는 경우에는 조기에 종료한다. + * + * @see #nextStep() + * 9. 리턴 변수를 초기화한다. + * 10. 아직 충돌하지 않은 원자들을 이동시키고, 그 위치를 기록한다. + * 10-1. 이론적으로 가능한 범위 안에서 원자 위치를 index로 변환한다. + * 10-2. 범위를 벗어난다면 해당 원소를 소멸 시킨다. + * 10-3. 이동 후 원자의 위치를 기록한다. + * 11. 모든 원자가 충돌하여 소멸한 경우 시뮬레이션을 중단한다. + * 12. 원자들 간의 충돌을 판단하여 원자를 소멸시키고, 발산한 에너지를 기록한다. + * 13. board 배열을 초기화한다. + * + * @see #print() + * + */ public class Solution { static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); @@ -11,20 +48,27 @@ public class Solution { // -------------------------------------------------------- public static void main(String[] args) throws IOException { + // 1. 테스트케이스를 입력받는다. final int testCount = Integer.parseInt(reader.readLine().trim()); for (int testCase = 1; testCase <= testCount; testCase++) { + // 2. 솔루션을 실행한다. new Solution(testCase).run(); } } // -------------------------------------------------------- + + private final int OFFSET = 2000; + private final int MAX_RANGE = OFFSET * 2; int testCase; - int raisedEnergy; + int raisedEnergy; // answer int atomCount; List atomList; + + int[][] board; public Solution(int testCase) { this.testCase = testCase; @@ -37,201 +81,94 @@ public void run() throws IOException { } private void input() throws IOException { + // 3. 원자 개수를 입력받는다. atomCount = Integer.parseInt(reader.readLine().trim()); + // 4. 원자 목록을 보관할 리스트 atomList를 초기화한다. atomList = new ArrayList<>(atomCount); + // 5. 원자들을 입력받아 atomList에 저장한다. for (int count = 0; count < atomCount; count++) { atomList.add(Atom.fromReader(reader)); } } private void solve() { -// System.out.println("--------------------------------------"); + // 6. 멤버변수를 초기화한다. raisedEnergy = 0; + board = new int[MAX_RANGE + 1][MAX_RANGE + 1]; -// runSimutation(); - updateAllCollisions(); + // 7. 시뮬레이션을 시작한다. + runSimuration(); } - private void updateAllCollisions() { - for (int A = 0; A < atomCount; A++) { - - Atom atomA = atomList.get(A); - - if (atomA.energy == 0) continue; - - List checkList = new ArrayList<>(atomCount); - - for (int B = 0; B < atomCount; B++) { - if (A == B) continue; - - Atom atomB = atomList.get(B); - if (atomB.energy == 0) continue; - -// if (atomA.isPredictedCollision(atomB)) { - if (getCollisionTimeIfPossible(atomA, atomB) != Double.MAX_VALUE) { -// System.out.printf("%d : %d\n", A, B); - checkList.add(atomB); - } - } - - if (checkList.size() == 0) continue; - - Collections.sort(checkList, (Atom sortA, Atom sortB) -> { -// double time1 = atomA.getCollisionTime(sortA); -// double time2 = atomA.getCollisionTime(sortB); - - double time1 = getCollisionTimeIfPossible(atomA, sortA); - double time2 = getCollisionTimeIfPossible(atomA, sortB); - - return Double.compare(time1, time2); - }); - - raisedEnergy += atomA.destroy(); - raisedEnergy += checkList.get(0).destroy(); - } - } - - private double getCollisionTimeIfPossible(Atom a, Atom b) { - int dx = b.x - a.x; - int dy = b.y - a.y; - - // 1. 마주보는 경우 (정수 시간 또는 .5초 시간) - if (a.x == b.x) { // 세로선상 - if (dy > 0 && a.dir == Atom.Direction.UP && b.dir == Atom.Direction.DOWN) return dy / 2.0; - if (dy < 0 && a.dir == Atom.Direction.DOWN && b.dir == Atom.Direction.UP) return Math.abs(dy) / 2.0; - } - if (a.y == b.y) { // 가로선상 - if (dx > 0 && a.dir == Atom.Direction.RIGHT && b.dir == Atom.Direction.LEFT) return dx / 2.0; - if (dx < 0 && a.dir == Atom.Direction.LEFT && b.dir == Atom.Direction.RIGHT) return Math.abs(dx) / 2.0; - } - - // 2. 직각 충돌 (반드시 dx == dy 여야 함) - if (Math.abs(dx) == Math.abs(dy)) { - double time = Math.abs(dx); - // A가 우측으로 갈 때 - if (a.dir == Atom.Direction.RIGHT) { - if (dx > 0 && ((dy > 0 && b.dir == Atom.Direction.DOWN) || (dy < 0 && b.dir == Atom.Direction.UP))) return time; - } - // A가 좌측으로 갈 때 - if (a.dir == Atom.Direction.LEFT) { - if (dx < 0 && ((dy > 0 && b.dir == Atom.Direction.DOWN) || (dy < 0 && b.dir == Atom.Direction.UP))) return time; - } - // A가 위로 갈 때 - if (a.dir == Atom.Direction.UP) { - if (dy > 0 && ((dx > 0 && b.dir == Atom.Direction.LEFT) || (dx < 0 && b.dir == Atom.Direction.RIGHT))) return time; - } - // A가 아래로 갈 때 - if (a.dir == Atom.Direction.DOWN) { - if (dy < 0 && ((dx > 0 && b.dir == Atom.Direction.LEFT) || (dx < 0 && b.dir == Atom.Direction.RIGHT))) return time; - } - } - - return Double.MAX_VALUE; // 충돌 불가 - } - - private void runSimutation() { - // 종료 조건: 원자들의 위치는 -1000 ~ 1000이기 때문에 2000번만 반복하고 종료하면 됨 + private void runSimuration() { + // 원자들의 초기위치는 -1000 ~ 1000인데, 0.5이동 때문에 초기위치에 x2되어 + // -2000 ~ 2000가 초기위치가 된다. + // 가장자리에 있는 원소들을 고려할때, 최대 4000번만 시뮬레이션하고 종료하면 된다. final int last = 4000; + // 8. 이론상 가능한 최대 횟수만큼 시뮬레이션을 실시하되, 모든 원자가 충돌하여 + // 시뮬레이션할 원자가 없는 경우에는 조기에 종료한다. for (int count = 0; count < last; count++) { - if (nextStep2() == 0) break; + if (nextStep() == 0) break; } } - - // -3000 ~ 3000 범위를 커버하기 위한 6001 크기의 배열 - static int[][] map = new int[6001][6001]; - private final int OFFSET = 3000; - private int nextStep2() { - int activeAtoms = 0; + private int nextStep() { + // 9. 리턴 변수를 초기화한다. + int activeAtoms = 0; - // 1. 모든 원자 이동 및 맵 기록 - for (Atom atom : atomList) { - if (atom.energy == 0) continue; + // 10. 아직 충돌하지 않은 원자들을 이동시키고, 그 위치를 기록한다. + for (Atom atom : atomList) { + if (atom.energy == 0) continue; - atom.moveNext2(); - - // 이론적 최대 범위 (-3000 ~ 3000) 내에서 인덱싱 - int mx = atom.x + OFFSET; - int my = atom.y + OFFSET; - - // 만약 이 범위를 벗어난다면 그 원자는 영원히 누구와도 만날 수 없음 - if (mx < 0 || mx > 6000 || my < 0 || my > 6000) { - atom.energy = 0; - continue; - } + atom.moveNext(); - activeAtoms++; - map[mx][my] += atom.energy; - } + // 10-1. 이론적으로 가능한 범위 안에서 원자 위치를 index로 변환한다. + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; - if (activeAtoms <= 1) { - clearMap(); - return 0; - } + // 10-2. 범위를 벗어난다면 해당 원소를 소멸 시킨다. + if (mx < 0 || mx > MAX_RANGE || my < 0 || my > MAX_RANGE) { + atom.energy = 0; + continue; + } - // 2. 충돌 판정 - for (Atom atom : atomList) { - if (atom.energy == 0) continue; + // 10-3. 이동 후 원자의 위치를 기록한다. + board[mx][my] += atom.energy; + activeAtoms++; + } - int mx = atom.x + OFFSET; - int my = atom.y + OFFSET; + // 11. 모든 원자가 충돌하여 소멸한 경우 시뮬레이션을 중단한다. + if (activeAtoms == 0) return 0; - if (map[mx][my] > atom.energy) { - raisedEnergy += atom.energy; - atom.energy = 0; - } - } - - // 3. 맵 청소 - clearMap(); + // 12. 원자들 간의 충돌을 판단하여 원자를 소멸시키고, 발산한 에너지를 기록한다. + for (Atom atom : atomList) { + if (atom.energy == 0) continue; - return activeAtoms; - } + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; - private void clearMap() { - for (Atom atom : atomList) { - int mx = atom.x + OFFSET; - int my = atom.y + OFFSET; - if (mx >= 0 && mx <= 6000 && my >= 0 && my <= 6000) { - map[mx][my] = 0; - } - } - } - - private int nextStep() { - // 각 원자들의 이동 벡터를 [시작, 종료]로 기록 - // 서로 다른 벡터들의 [시작, 종료]가 겹치면 해당 원소는 에너지를 모두 발산하고 소멸 - - List vecList = new ArrayList<>(atomCount); - int vecLen = 0; - - for (int atomIndex = 0; atomIndex < atomCount; atomIndex++) { - Atom atom = atomList.get(atomIndex); - if (atom.energy == 0) continue; - - vecList.add(atom.moveNext()); -// System.out.println(atomIndex + " " + atom); - vecLen++; + if (board[mx][my] > atom.energy) { + raisedEnergy += atom.energy; + atom.energy = 0; + } } - - for (int A = 0; A < vecLen; A++) { - for (int B = 0; B < vecLen; B++) { - if (A == B) continue; - - Vec vecA = vecList.get(A); - Vec vecB = vecList.get(B); - - if (vecA.isCollision(vecB) || vecA.isEqualPos(vecB)) { - raisedEnergy += atomList.get(A).destroy(); - raisedEnergy += atomList.get(B).destroy(); -// System.out.printf("[collision] %d : %d -> %d\n", A, B, raisedEnergy); - } + + // 13. board 배열을 초기화한다. + clearBoard(); + + return activeAtoms; + } + + private void clearBoard() { + for (Atom atom : atomList) { + int mx = atom.x + OFFSET; + int my = atom.y + OFFSET; + if (mx >= 0 && mx <= MAX_RANGE && my >= 0 && my <= MAX_RANGE) { + board[mx][my] = 0; } } - - return vecLen; } private void print() throws IOException { @@ -244,22 +181,15 @@ private void print() throws IOException { // -------------------------------------------------------- static class Atom { - enum Direction { - UP, - DOWN, - LEFT, - RIGHT - } - static final int[] DIR_X = { 0, 0, -1, 1 }; static final int[] DIR_Y = { 1, -1, 0, 0 }; int x; int y; - Direction dir; + int dir; int energy; - public Atom(int x, int y, Direction dir, int energy) { + public Atom(int x, int y, int dir, int energy) { this.x = x; this.y = y; this.dir = dir; @@ -268,205 +198,21 @@ public Atom(int x, int y, Direction dir, int energy) { public static Atom fromReader(BufferedReader reader) throws IOException { getLine(); - int x = Integer.parseInt(input.nextToken()) * 2; // WOW - int y = Integer.parseInt(input.nextToken()) * 2; // WOW + int x = Integer.parseInt(input.nextToken()) * 2; // 0.5 시간에 충돌을 처리하기 위해서 x2 한다. + int y = Integer.parseInt(input.nextToken()) * 2; // 0.5 시간에 충돌을 처리하기 위해서 x2 한다. int dir = Integer.parseInt(input.nextToken()); int energy = Integer.parseInt(input.nextToken()); - Direction eDir = Direction.UP; - switch (dir) { - case 0: - eDir = Direction.UP; - break; - case 1: - eDir = Direction.DOWN; - break; - case 2: - eDir = Direction.LEFT; - break; - case 3: - eDir = Direction.RIGHT; - break; - } - - return new Atom(x, y, eDir, energy); + return new Atom(x, y, dir, energy); } - - public Vec moveNext() { - int nextX = x + DIR_X[dir.ordinal()]; - int nextY = y + DIR_Y[dir.ordinal()]; - - Vec vec = new Vec(x, y, nextX, nextY); - - x = nextX; - y = nextY; - - return vec; - } - - public void moveNext2() { - int nextX = x + DIR_X[dir.ordinal()]; - int nextY = y + DIR_Y[dir.ordinal()]; + + public void moveNext() { + int nextX = x + DIR_X[dir]; + int nextY = y + DIR_Y[dir]; x = nextX; y = nextY; } - - public Atom moveNextAtom() { - int nextX = x + DIR_X[dir.ordinal()]; - int nextY = y + DIR_Y[dir.ordinal()]; - - return new Atom(nextX, nextY, dir, energy); - } - - public int destroy() { - int returnEnergy = energy; - energy = 0; - - return returnEnergy; - } - - public double getCollisionTime(Atom another) { - return getDistance(another); - } - - public boolean isPredictedCollision(Atom another) { - // x좌표가 같은데, 방향이 마주보는 경우 - // y좌표가 같은데, 방향이 마주보는 경우 - // abs(A.y - B.y) == abs(A.x - B.x) 인 경우 - - if (this.x == another.x && isSameOriginDirectionVertical(another)) { - return true; - } else if (this.y == another.y && isSameOriginDirectionHorizontal(another)) { - return true; - } else if (Math.abs(this.x - another.x) == Math.abs(this.y - another.y) && - isSameOriginDirectionCross(another) - ) { - return true; - } - - return false; - } - - public boolean isSameOriginDirectionCross(Atom another) { -// Atom next = moveNextAtom(); -// return next.getDistance(another) < this.getDistance(another); - - Atom atomA = this; - Atom atomB = another; - - if (atomA.dir == Direction.UP || atomA.dir == Direction.DOWN) { - Atom temp = atomA; - atomA = atomB; - atomB = temp; - } - - if (atomA.y < atomB.y) { - if (atomB.dir != Direction.DOWN) return false; - } else if (atomB.y < atomA.y) { - if (atomB.dir != Direction.UP) return false; - } - - if (atomA.x < atomB.x) { - if (atomA.dir != Direction.RIGHT) return false; - } else if (atomB.x < atomA.x) { - if (atomA.dir != Direction.LEFT) return false; - } - - return true; - } - - public boolean isSameOriginDirectionHorizontal(Atom another) { - boolean result = false; - - result |= (this.dir == Direction.LEFT && another.dir == Direction.RIGHT); - result |= (this.dir == Direction.RIGHT && another.dir == Direction.LEFT); - - return result; - } - - public boolean isSameOriginDirectionVertical(Atom another) { - boolean result = false; - - result |= (this.dir == Direction.UP && another.dir == Direction.DOWN); - result |= (this.dir == Direction.DOWN && another.dir == Direction.UP); - - return result; - } - - public int getDistance(Atom another) { - int result = 0; - - result += Math.max(this.x, another.x) - Math.min(this.x, another.x); - result += Math.max(this.y, another.y) - Math.min(this.y, another.y); - - return result; - } - - @Override - public String toString() { - return String.format("[x=%d, y=%d, dir=%d, energy=%d]", x, y, dir, energy); - } - } - - // -------------------------------------------------------- - - static class Vec { - int beginX; - int beginY; - int endX; - int endY; - - public Vec(int beginX, int beginY, int endX, int endY) { - this.beginX = beginX; - this.beginY = beginY; - this.endX = endX; - this.endY = endY; - } - - public boolean isCollision(Vec another) { - // AABB Collision Detection Algorithm - // (상하좌우로만 움직이기 때문에 AABB 활용 가능) - - boolean result = false; - - result |= another.beginX <= this.beginX && another.endX <= this.beginX; - result |= this.endX <= another.beginX && this.endX <= another.endX; - - result |= another.beginY <= this.beginY && another.endY <= this.beginY; - result |= this.endY <= another.beginY && this.endY <= another.endY; - -// System.out.printf("isCollision (%d:%d, %d:%d) - (%d:%d, %d:%d) %s\n", beginX, endX, beginY, endY, another.beginX, another.endX, another.beginY, another.endY, !result); - - return !result; - } - - public boolean isEqualPos(Vec another) { - return this.endX == another.endX && this.endY == another.endY; - } - } - - // -------------------------------------------------------- - - static class Pos { - double x; - double y; - - public Pos(double x, double y) { - this.x = x; - this.y = y; - } - - @Override - public boolean equals(Object obj) { - Pos another = (Pos)obj; - return this.x == another.x && this.y == another.y; - } - - @Override - public int hashCode() { - return Objects.hash(x, y); - } } // -------------------------------------------------------- From 3c175abec06fb1a436eb4efc650793c819348c3b Mon Sep 17 00:00:00 2001 From: "YeJun, Jung" Date: Wed, 11 Feb 2026 09:38:36 +0900 Subject: [PATCH 3/5] fix: swea p2806 solution --- problems/SWEA/p2806/Solution.java | 88 +++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/problems/SWEA/p2806/Solution.java b/problems/SWEA/p2806/Solution.java index 60a56f5..b0fd232 100644 --- a/problems/SWEA/p2806/Solution.java +++ b/problems/SWEA/p2806/Solution.java @@ -1,8 +1,59 @@ -package swea.p2806; +/* + * (2806) N-Queen + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV7GKs06AU0DFAXB&categoryId=AV7GKs06AU0DFAXB&categoryType=CODE&problemTitle=2806&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ import java.io.*; import java.util.*; +/** + * SW Expert Academy - 2806. N-Queen + * @author YeJun, Jung + * + * @see #main(String[] args) + * 1. 테스트케이스를 입력받는다. + * 2. 솔루션을 실행한다. + * + * @see #input() + * 3. 보드의 크기이자 퀸의 개수인 N을 입력받는다. + * + * @see #solve() + * 4. 멤버변수를 초기화한다. + * 5. 퀸을 배치할 수 있는 경우의 수에 대해서 탐색을 시작한다. + * + * @see #search(int nQueen, int y) + * 6. 기저조건을 검사한다. + * 6-1. 기저조건을 달성하면 answer을 +1 한다. + * 7. 현재 y위치에서 board의 마지막 위치까지 탐색한다. + * 7-1. 지금 위치에 퀸을 배치한다. + * 7-1-1. 지금 위치에 퀸을 배치할 수 없다면 다음 위치로 이동한다. + * 7-2. 다음 퀸 배치를 위한 탐색을 재귀함수로 진행한다. + * 7-3. 배치해 두었던 퀸을 삭제한다. + * + * @see #putQueen(int x, int y) + * 8. 주어진 위치(x, y)에 퀸을 배치한다. + * 8-1. 주어진 위치에 이미 퀸이 존재한다면 false(불가능)을 반환한다. + * 8-2. 변수를 초기화한다. + * 8-3. 퀸의 이동범위에 대해서... + * 8-3-1. 주어진 위치에 퀸을 배치했을때 이미 배치되어 있는 퀸을 잡을 수 있다면 + * 8-3-1-1. 퀸을 배치할 수 없다. + * 8-3-2. 퀸이 이동가능한 위치를 표시한다. + * 8-3-3. 계속해서 다음 퀸의 이동가능한 위치를 검토한다. + * 8-4. 만약, 이전에 배치된 퀸을 잡을 수 있는 위치에 있다면... + * 8-4-1. 지금까지 표시한 퀸의 이동가능한 위치들을 롤백한다. + * 8-4-2. false(불가능)을 반환한다. + * 8-5. 주어진 위치에 퀸을 배치한다. + * 8-6. true(배치 성공함)을 반환한다. + * + * @see #removeQueen(int x, int y) + * 9. 주어진 위치에 있는 퀸을 제거하고, 해당 퀸의 이동가능한 범위를 board에서 삭제한다. + * + * @see #isInsideBoard(int x, int y) + * 10. 주어진 위치가 board 범위 안에 있는지 검사한다. + * + * @see print() + * 11. answer를 화면에 출력한다. + */ public class Solution { static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); @@ -10,9 +61,11 @@ public class Solution { // -------------------------------------------------------- public static void main(String[] args) throws IOException { + // 1. 테스트케이스를 입력받는다. final int testCount = Integer.parseInt(reader.readLine().trim()); for (int testCase = 1; testCase <= testCount; testCase++) { + // 2. 솔루션을 실행한다. new Solution(testCase).run(); } } @@ -40,60 +93,80 @@ public void run() throws IOException { } private void input() throws IOException { + // 3. 보드의 크기이자 퀸의 개수인 N을 입력받는다. N = Integer.parseInt(reader.readLine().trim()); } private void solve() { + // 4. 멤버변수를 초기화한다. answer = 0; board = new int[N][N]; + // 5. 퀸을 배치할 수 있는 경우의 수에 대해서 탐색을 시작한다. search(N, 0); } private void search(int nQueen, int y) { - // 기저조건 + // 6. 기저조건을 검사한다. if (nQueen == 0) { + // 6-1. 기저조건을 달성하면 answer을 +1 한다. answer++; + return; } + // 7. 현재 y위치에서 board의 마지막 위치까지 탐색한다. for (int cy = y; cy < N; cy++) { for (int cx = 0; cx < N; cx++) { + // 7-1. 지금 위치에 퀸을 배치한다. + // 7-1-1. 지금 위치에 퀸을 배치할 수 없다면 다음 위치로 이동한다. if (!putQueen(cx, cy)) continue; + // 7-2. 다음 퀸 배치를 위한 탐색을 재귀함수로 진행한다. search(nQueen - 1, cy + 1); + // 7-3. 배치해 두었던 퀸을 삭제한다. removeQueen(cx, cy); } } } private boolean putQueen(int x, int y) { + // 8. 주어진 위치(x, y)에 퀸을 배치한다. + + // 8-1. 주어진 위치에 이미 퀸이 존재한다면 false(불가능)을 반환한다. if (board[y][x] != 0) return false; + // 8-2. 변수를 초기화한다. boolean available = true; int count = 0; + // 8-3. 퀸의 이동범위에 대해서... for (int dir = 0; dir < QUEEN_DIR_LEN; dir++) { int cx = x + QUEEN_DIR_X[dir]; int cy = y + QUEEN_DIR_Y[dir]; while (isInsideBoard(cx, cy)) { + // 8-3-1. 주어진 위치에 퀸을 배치했을때 이미 배치되어 있는 퀸을 잡을 수 있다면 if (board[cy][cx] < 0) { + // 8-3-1-1. 퀸을 배치할 수 없다. available = false; break; } + // 8-3-2. 퀸이 이동가능한 위치를 표시한다. board[cy][cx]++; count++; + // 8-3-3. 계속해서 다음 퀸의 이동가능한 위치를 검토한다. cx += QUEEN_DIR_X[dir]; cy += QUEEN_DIR_Y[dir]; } } - // rollback + // 8-4. 만약, 이전에 배치된 퀸을 잡을 수 있는 위치에 있다면... if (!available) { + // 8-4-1. 지금까지 표시한 퀸의 이동가능한 위치들을 롤백한다. for (int dir = 0; dir < QUEEN_DIR_LEN && count > 0; dir++) { int cx = x + QUEEN_DIR_X[dir]; int cy = y + QUEEN_DIR_Y[dir]; @@ -106,14 +179,21 @@ private boolean putQueen(int x, int y) { cy += QUEEN_DIR_Y[dir]; } } + + // 8-4-2. false(불가능)을 반환한다. + return false; } + // 8-5. 주어진 위치에 퀸을 배치한다. board[y][x] = -1; + // 8-6. true(배치 성공함)을 반환한다. return true; } private void removeQueen(int x, int y) { + // 9. 주어진 위치에 있는 퀸을 제거하고, 해당 퀸의 이동가능한 범위를 board에서 삭제한다. + board[y][x] = 0; for (int dir = 0; dir < QUEEN_DIR_LEN; dir++) { @@ -130,10 +210,12 @@ private void removeQueen(int x, int y) { } private boolean isInsideBoard(int x, int y) { + // 10. 주어진 위치가 board 범위 안에 있는지 검사한다. return x >= 0 && x < N && y >= 0 && y < N; } private void print() throws IOException { + // 11. answer를 화면에 출력한다. writer.write("#" + testCase); writer.write(" " + answer); writer.write("\n"); From f7caef84af20826a2d9fe1807587328f6ca81bc7 Mon Sep 17 00:00:00 2001 From: "YeJun, Jung" Date: Wed, 11 Feb 2026 11:35:02 +0900 Subject: [PATCH 4/5] docs: fix gitignore --- .gitignore | 3 +++ problems/SWEA/p5648/answer.txt | 2 -- problems/SWEA/p5648/input.txt | 7 ------- problems/SWEA/p5648/output.txt | 1 - 4 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 problems/SWEA/p5648/answer.txt delete mode 100644 problems/SWEA/p5648/input.txt delete mode 100644 problems/SWEA/p5648/output.txt diff --git a/.gitignore b/.gitignore index 2298b78..b43118e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Input, Output *.in *.out +input.txt +output.txt +answer.txt ### Eclipse ### .metadata diff --git a/problems/SWEA/p5648/answer.txt b/problems/SWEA/p5648/answer.txt deleted file mode 100644 index b69abc4..0000000 --- a/problems/SWEA/p5648/answer.txt +++ /dev/null @@ -1,2 +0,0 @@ -#1 24 -#2 0 \ No newline at end of file diff --git a/problems/SWEA/p5648/input.txt b/problems/SWEA/p5648/input.txt deleted file mode 100644 index 542efc0..0000000 --- a/problems/SWEA/p5648/input.txt +++ /dev/null @@ -1,7 +0,0 @@ -1 -5 --2 0 3 3 --1 0 3 2 -0 0 2 5 -1 0 2 4 -0 -1 0 6 diff --git a/problems/SWEA/p5648/output.txt b/problems/SWEA/p5648/output.txt deleted file mode 100644 index 97e50df..0000000 --- a/problems/SWEA/p5648/output.txt +++ /dev/null @@ -1 +0,0 @@ -#1 14 From f31f3011c9cd0a068ec11b87e8f50a77ce5c51df Mon Sep 17 00:00:00 2001 From: "YeJun, Jung" Date: Wed, 11 Feb 2026 11:35:13 +0900 Subject: [PATCH 5/5] fix: swea p1952 solution --- problems/SWEA/p1952/Solution.java | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/problems/SWEA/p1952/Solution.java b/problems/SWEA/p1952/Solution.java index 7a9f8dc..953b5cc 100644 --- a/problems/SWEA/p1952/Solution.java +++ b/problems/SWEA/p1952/Solution.java @@ -1,4 +1,7 @@ -package swea.p1952; +/* + * {풀이 하는 중} (1952) [모의 SW 역량테스트] 수영장 + * https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PpFQaAQMDFAUq&categoryId=AV5PpFQaAQMDFAUq&categoryType=CODE&problemTitle=1952&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 + */ import java.io.*; import java.util.*; @@ -75,23 +78,38 @@ private void solve() { oneDayTicketArr = new int[MONTH_LEN]; monthTicketArr = new boolean[MONTH_LEN]; - + + offset = bestPrice * 2; + cache = new boolean[13 * offset]; + searchBestPrice(0, 0); } + + int offset; + boolean[] cache; private void searchBestPrice(int month, int currentPrice) { + if (month > MONTH_LEN || currentPrice >= bestPrice) return; + + int cacheKey = month * offset + currentPrice; + // System.out.printf("searchBestPrice(%d, %d)\n", month, currentPrice); + if (cache[cacheKey]) return; + cache[cacheKey] = true; + while ( (month < MONTH_LEN) && - (oneDayTicketArr[month] >= planArr[month]) + (monthTicketArr[month] || oneDayTicketArr[month] >= planArr[month]) ) { - System.out.println("WOW"); month++; } // 기저조건 if (month >= MONTH_LEN) { if (currentPrice < bestPrice) bestPrice = currentPrice; + cache[cacheKey] = true; return; } + + // System.out.printf("[%d] searchBestPrice(%d, %d)\n", testCase, month, currentPrice); int price; @@ -122,6 +140,8 @@ private void searchBestPrice(int month, int currentPrice) { searchBestPrice(month + 3, price); for (int m = month; m < month + 2 && m < MONTH_LEN; m++) monthTicketArr[m] = false; } + + cache[cacheKey] = true; } private void print() throws IOException {