diff --git "a/zinzoddari/7\354\243\274\354\260\250/Problem1966.md" "b/zinzoddari/7\354\243\274\354\260\250/Problem1966.md" new file mode 100644 index 0000000..8ef69b8 --- /dev/null +++ "b/zinzoddari/7\354\243\274\354\260\250/Problem1966.md" @@ -0,0 +1,85 @@ +```java +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.StringTokenizer; + +public class Problem1966 { + + private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); + private static StringBuilder stringBuilder = new StringBuilder(); + private static StringTokenizer stringTokenizer; + + private static int getValue() throws IOException { + if (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) { + stringTokenizer = new StringTokenizer(bufferedReader.readLine(), " "); + } + + return Integer.parseInt(stringTokenizer.nextToken()); + } + + public static void main(String[] args) throws IOException { + final int T = getValue(); + + for (int i = 0; i < T; i++) { + final int N = getValue(); + final int M = getValue(); + + Queue priority = new PriorityQueue<>(); + Queue queue = new LinkedList<>(); + + for (int j = 0; j < N; j++) { + final Document document = new Document(j, getValue()); + priority.offer(document); + queue.offer(document); + } + + int count = 0; + while (!queue.isEmpty()) { + final Document document = queue.poll(); + + if (priority.peek().getImportance() == document.getImportance()) { + count++; + priority.poll(); + } else { + queue.offer(document); + continue; + } + + if (document.getIndex() == M) { + stringBuilder.append(count).append("\n"); + break; + } + } + } + + System.out.println(stringBuilder.toString().trim()); + } + + static class Document implements Comparable { + int index; + int importance; + + public Document(int index, int importance) { + this.index = index; + this.importance = importance; + } + + @Override + public int compareTo(Document o) { + return o.importance - importance; + } + + public int getIndex() { + return index; + } + + public int getImportance() { + return importance; + } + } +} +``` \ No newline at end of file diff --git "a/zinzoddari/7\354\243\274\354\260\250/\354\213\234\353\256\254\353\240\210\354\235\264\354\205\230.md" "b/zinzoddari/7\354\243\274\354\260\250/\354\213\234\353\256\254\353\240\210\354\235\264\354\205\230.md" new file mode 100644 index 0000000..67c928f --- /dev/null +++ "b/zinzoddari/7\354\243\274\354\260\250/\354\213\234\353\256\254\353\240\210\354\235\264\354\205\230.md" @@ -0,0 +1,97 @@ +# 시뮬레이션이란? +문제에서 제시한 상황과 규칙, 조건을 그대로 구현하는 것을 의미합니다. + +## 특징 +- 수학적 최적화나 복잡한 알고리즘보다, **구현력**이 핵심입니다. +- 주어진 규칙을 정확히 이해하고, 순서대로 반영해야 합니다. +- 문제 크기가 작더라도, 조건이 다양해 구현이 길어질 수 있습니다. +- 디버깅 난이도가 높습니다. (규칙 누락, 순서 실수, 인덱스 오류 등) + +# 문제 접근 순서 +## 1. 문제 해석 +상황과 규칙, 입력/출력 형식에 대해서 먼저 파악합니다. +모호한 부분은 예제와 비교하며 해석합니다. + +## 2. 데이터 구조 설계 +격자(map), 큐, 스택, 리스트 등 상황에 맞는 구조를 선택합니다. + +## 3. 흐름 설계 +시뮬레이션 단계별로 수행할 작업을 나눕니다. +- 예: 이동 -> 충돌 판정 -> 상태 업데이트 -> 반복 + +## 4. 예외 처리 +경계값(Out of Bounds), 조건 미충족때의 동작, 규칙이 겹칠때의 우선 순위 등에 대한 예외 처리를 적용합니다. + +## 5. 구현 후 디버깅 +작은 입력 케이스로 단계별 값 출력하여 검증해봅니다. +문제에서 제공되는 예제 외로도 직접 엣지 케이스를 만들어 테스트합니다. + +# 구현 시 주의사항 +### 1. 명확한 상태 표현 +각 개체의 위치나, 방향, 상태를 변수나 구조체로 명확히 관리합니다. + +### 2. 반복문 종료 조건 +무한 루프를 방지하기 위해서는 명확한 반복문의 종료 조건이 필요합니다. + +### 3. 시간 복잡도 +시뮬레이션은 매 단계마다 전체 상태를 확인하는 경우가 많아, O(반복 횟수 × 상태 개수)가 기본입니다. 상태가 2차원 격자라면 O(T × N × M)이 되고, 각 상태에서 추가 탐색이 있으면 더 복잡해질 수 있습니다. + +상황에따라 최적화가 필요할 수 있습니다. + +### 4. 순서 의존성 +규칙 적용 순서가 결과에 직접 영향을 주게 됩니다. + +### 5. 깊은 복사, 얕은 복사 주의 +시뮬레이션 중 이전 상태를 보존해야 할 때에는 깊은 복사를 활용합니다. + +> 깊은 복사와 얕은 복사란? +> 깊은 복사의 경우 새로운 메모리 공간에 객체 데이터를 그대로 복사하게 됩니다. 이 덕분에 기존 객체에까지 영향이 끼치지 않게 됩니다. +> +> 얕은 복사의 경우, 객체의 주소만을 복사하게 됩니다. 복사한 값과 원본 값이 같은 값을 바라보게 되고, 한쪽은 수정하게 되면 다른 곳까지 영향이 가게 됩니다. + +# 자주 등장하는 패턴 +## 1. 격자 이동 +2D 배열에서 상하좌우/대각선 이동 방식 +- 방향 배열 (dx, dy) 활용 +- https://www.acmicpc.net/problem/3184 + +## 2. 회전/이동 규칙 +큐로 회전 시뮬레이션 +- 회전 시, 인덱스 모듈러 연산 +- https://www.acmicpc.net/problem/1021 +- https://www.acmicpc.net/problem/5430 + +## 3. 큐를 활용한 순차 처리 +BFS 형태의 시뮬레이션 +- 토마토 익히기, 불 번짐 등 +- https://www.acmicpc.net/problem/7576 +- https://www.acmicpc.net/problem/5427 + +## 4. 이벤트 기반 진행 +특정 시점에서 상태 변경 +- https://www.acmicpc.net/problem/1966 + +## 5. 여러 개체 동시 처리 +1단계에서 모두 이동 위치 결정 +이후 2단계에서 동시에 반영 +- https://www.acmicpc.net/problem/16918 +- https://www.acmicpc.net/problem/16234 + +## 6. 상태 스냅샷 유지 +매 턴마다 이전 상태 저장 후 비교 +- https://www.acmicpc.net/problem/3190 +- https://www.acmicpc.net/problem/20055 + +# 시간 복잡도 고려하기 +보통 문제에서 **N ≤ 100, T ≤ 1000** 정도면 단순 시뮬레이션 가능합니다. +하지만, N과 T 둘 다 크다면, 시뮬레이션 대신 수학적 규칙 도출이 필요할 수 있습니다. + +``` +O(T × N × M)   →  T: 반복 횟수, N×M: 상태 크기 +``` + +# 마지막 팁 +- 단계별로 구현하고 각 단계별 출력으로 로직을 검증합니다. +- 규칙이 복잡하다면, **플로우 차트**를 먼저 작성하여 흐름을 정리합니다. +- 문제 설명의 순서대로 구현하고, 규칙을 재해석 하지 않도록 주의합니다. +- 시뮬레이션의 문제는 **실수 줄이는 것이** 속도보다 중요합니다. \ No newline at end of file