박정준@jungjun · Aug 17, 2026

정보량이 많은 시뮬레이션 문제를 구조화하는 연습법

아기 바다거북의 대모험: 해저 화산 지대

삼성 2026 상반기 오전 1번 문제

알고리즘 자체는 어렵지 않은데 문제 설명이 길고 조건이 많은 문제가 있다.
이런 문제는 BFS, DFS 같은 알고리즘보다 문제의 규칙을 코드 구조로 옮기는 능력이 더 중요하다.

핵심은 문제를 한 번에 이해하려 하지 않고, 다음 순서로 나누는 것이다.

등장 요소 파악 → 상태 정리 → 진행 순서 정리 → 조건을 코드로 변환


1. 처음부터 구현 방법을 생각하지 않는다

처음 문제를 읽을 때는 다음 질문만 확인한다.

  • 무엇이 등장하는가?

  • 각각 어떤 정보를 가지는가?

  • 시간이 지나면서 무엇이 변하는가?

  • 최종적으로 무엇을 출력하는가?

예를 들어 거북이 문제라면 등장 요소는 다음과 같다.

격자
거북이
화산
산호초
열기

이 단계에서는 BFS나 큐를 생각하지 않는다.
먼저 문제 속 세계가 무엇으로 구성되어 있는지를 정리해야 한다.


2. 정보를 정적 상태와 동적 상태로 분리한다

문제의 모든 정보가 매 턴 변하는 것은 아니다.

정적 정보

시뮬레이션 중 변하지 않는 값이다.

격자 크기
산호초 위치
화산 위치
화산의 분출 임계치

동적 정보

턴이 진행되면서 변하는 값이다.

거북이의 위치와 상태
화산의 현재 압력
이번 턴의 열기
화산의 분출 여부

이를 코드로 옮기면 상태가 자연스럽게 분리된다.

struct Turtle {
    int r, c;
    State state;
    int arriveTurn;
};

struct Volcano {
    int r, c;
    int threshold;
    int pressure;
};

한 변수에 여러 의미를 섞지 않는 것이 중요하다.

예를 들어 화산 문제에서는 다음 세 값을 반드시 분리해야 한다.

현재 압력
분출 임계치
외부 열기

값이 같은 숫자가 되더라도 의미는 서로 다르다.


3. “한 턴”의 흐름을 먼저 적는다

시뮬레이션 문제에서는 구현 전에 한 턴의 순서를 짧게 적어야 한다.

1. 거북이를 ID 순서대로 이동시킨다.
2. 모든 화산의 압력을 10 증가시킨다.
3. 분출과 연쇄 분출을 처리한다.
4. 거북이의 화석화를 판정한다.
5. 열기와 분출한 화산의 압력을 초기화한다.

이 순서는 그대로 메인 반복문의 뼈대가 된다.

for (int turn = 1; turn <= 100; turn++) {
    moveTurtles(turn);
    increasePressure();
    eruptVolcanoes();
    fossilizeTurtles();
    resetEnvironment();
}

처음부터 세부 구현을 작성하지 말고, 큰 흐름부터 만든다.


4. 시간과 순서를 나타내는 단어에 표시한다

긴 문제에서 가장 자주 놓치는 것은 알고리즘이 아니라 처리 시점이다.

다음 단어가 나오면 반드시 표시한다.

즉시
순서대로
모든 처리가 끝난 후
이번 턴에만
아직 처리되지 않은
반복한다
이후 턴부터

예를 들어:

앞선 거북이의 이동 결과는 즉시 다음 거북이에게 반영된다.

이 문장은 거북이 전체를 동시에 이동시키면 안 된다는 뜻이다.

for (int id = 1; id <= M; id++) {
    moveTurtle(id);

    // 이동 결과를 즉시 지도에 반영
}

반대로:

모든 분출이 종료된 후 거북이의 화석화를 판정한다.

이 문장은 화산 하나가 분출할 때마다 거북이를 검사하면 안 된다는 뜻이다.

processAllEruptions();
fossilizeTurtles();

5. 자연어 규칙을 조건과 행동으로 바꾼다

문제의 각 문장을 다음 형태로 변환한다.

조건 → 행동

예를 들어:

최단 경로가 존재한다
→ 우선순위에 따라 한 칸 이동한다.

안식처에 도착한다
→ 지도에서 제거하고 도착 턴을 기록한다.

압력 + 외부 열기가 임계치 이상이다
→ 화산이 분출한다.

거북이 칸의 총열기가 20 이상이다
→ 거북이를 화석 상태로 변경한다.

코드로 옮기면 대부분 if문이 된다.

if (pressure + heat[r][c] >= threshold) {
    erupt();
}

긴 문장을 그대로 기억하려 하지 말고, 짧은 조건식으로 변환한다.


6. 비슷해 보이는 상태를 반드시 구분한다

시뮬레이션 문제에서는 행동은 같지만 의미가 다른 상태가 자주 등장한다.

예를 들어 도착한 거북이와 화석이 된 거북이는 모두 더 이상 움직이지 않는다.

하지만 지도에서의 처리는 다르다.

도착한 거북이
→ 지도에서 제거된다.

화석이 된 거북이
→ 해당 칸에 남아 장애물이 된다.

따라서 단순히 alive라는 bool 하나로 처리하기 어렵다.

enum State {
    ACTIVE,
    ARRIVED,
    FOSSIL
};

상태를 나눌 때는 다음 질문을 사용한다.

이후 규칙에서 처리 방식이 달라지는가?

처리 방식이 다르면 별도의 상태로 나누는 것이 안전하다.


7. 누적되는 값과 소비되는 값을 구분한다

특히 열기, 피해량, 점수, 비용처럼 여러 곳에서 더해지는 값은 주의해야 한다.

화산 문제의 예시는 다음과 같다.

현재 압력 = 30
외부 열기 = 15
임계치 = 45

분출 판정은:

30 + 15 >= 45

이다.

여기서 외부 열기 15는 분출 조건을 확인할 때 사용되지만 사라지지 않는다.
화산이 분출해 새로운 열기 45를 발생시키면:

기존 열기 15 + 새로운 열기 45 = 총열기 60

이 된다.

따라서 다음을 확인해야 한다.

이 값은 조건 확인에만 사용하는가?
사용한 뒤 사라지는가?
계속 누적되는가?
다른 상태값에 실제로 저장되는가?

8. 작은 예제를 직접 손으로 진행한다

코드를 작성하기 전에 작은 상황을 1~2턴만 직접 계산한다.

표를 사용하면 좋다.

턴

거북이 위치

화산 압력

누적 열기

결과

시작

(0, 0)

0

0

이동 전

1턴 이동 후

(0, 1)

0

0

이동

압력 증가 후

(0, 1)

10

0

미분출

턴 종료

(0, 1)

10

초기화

생존

직접 진행하다가 설명과 계산이 맞지 않으면, 코딩 전에 문제 이해가 잘못된 것이다.

특히 다음 상황은 반드시 손으로 확인하는 것이 좋다.

여러 객체가 같은 칸에 영향을 주는 경우
연쇄 반응이 발생하는 경우
상태가 변경되는 순간
턴이 끝날 때 초기화되는 값

9. 함수는 문제의 단계에 맞춰 나눈다

함수는 자료구조보다 문제의 규칙을 기준으로 나누는 것이 좋다.

moveTurtle()
increasePressure()
spreadHeat()
processEruptions()
fossilizeTurtles()
resetVolcanoes()

좋은 기준은 다음과 같다.

함수 이름 하나가 문제 설명의 한 문장과 대응되는가?

예를 들어:

void fossilizeTurtles();

은 다음 규칙과 바로 연결된다.

모든 분출이 끝난 후 열기가 20 이상인 거북이는 화석이 된다.

함수 하나에 여러 단계를 한꺼번에 넣으면 문제 설명과 코드를 비교하기 어려워진다.


10. 구현 순서도 작은 단위부터 진행한다

처음부터 전체 코드를 완성하려 하지 않는다.

추천 구현 순서

1. 구조체와 상태를 정의한다.
2. 입력을 저장한다.
3. 거북이 한 마리의 이동만 구현한다.
4. 화산 하나의 열기 전파만 구현한다.
5. 연쇄 분출을 구현한다.
6. 한 턴을 연결한다.
7. 최대 100턴 반복과 출력을 추가한다.

각 단계가 맞는지 확인한 뒤 다음 단계로 넘어간다.


11. 오답이 나면 코드보다 규칙을 먼저 확인한다

정보량이 많은 문제에서 오답이 발생하면 단순 구현 실수보다 규칙을 잘못 이해한 경우가 많다.

다음 순서로 점검한다.

1. 처리 순서가 맞는가?
2. 즉시 반영과 일괄 처리를 구분했는가?
3. 상태를 충분히 나누었는가?
4. 누적값을 잘못 초기화하지 않았는가?
5. 초기화 대상과 유지 대상을 구분했는가?
6. 같은 객체가 여러 번 처리되지 않는가?

코드 한 줄씩 보기 전에 문제 규칙과 함수의 대응 관계를 확인하는 것이 빠르다.


추천 연습 방법

문제를 풀 때 처음 15~20분은 코드를 작성하지 않는다.

다음 네 가지만 종이에 정리한다.

등장 객체
각 객체의 상태
한 턴의 처리 순서
조건 → 행동 목록

문제를 푼 뒤에는 정답 코드만 저장하지 말고, 자신이 헷갈렸던 규칙을 기록한다.

즉시 반영을 놓침
상태를 bool 하나로 표현하려 함
누적값과 판정값을 혼동함
초기화 시점을 잘못 이해함
순차 처리와 동시 처리를 혼동함

이 기록이 쌓이면 비슷한 문제에서 실수가 빠르게 줄어든다.


구현 전 체크리스트

  • 등장하는 객체를 모두 분리했는가?

  • 정적 정보와 동적 정보를 구분했는가?

  • 한 턴의 처리 순서를 적었는가?

  • 즉시, 모든 처리 후, 반복 같은 표현을 확인했는가?

  • 상태에 따라 이후 처리가 달라지는 경우를 구분했는가?

  • 누적되는 값과 조건 확인에만 사용되는 값을 구분했는가?

  • 초기화되는 값과 다음 턴까지 유지되는 값을 구분했는가?

  • 작은 예제를 직접 한두 턴 진행해 보았는가?

  • 각 함수가 문제의 한 규칙과 대응되는가?


핵심 정리

정보량이 많은 문제는 모든 내용을 머릿속에 유지하면서 풀려고 하면 어렵다.

문제를 다음 구조로 변환해야 한다.

명사 → 객체
객체의 정보 → 상태 변수
시간의 흐름 → 단계별 함수
규칙 문장 → 조건문
반복되는 반응 → 반복문 또는 큐

결국 이런 문제에서 필요한 능력은 빠르게 코딩하는 것이 아니라, 긴 자연어 설명을 작은 상태와 규칙으로 분해하는 능력이다.

댓글

아직 댓글이 없습니다.