seukseok의 개인 블로그

BOJ 풀이 노트: 그리디 수식 처리와 플로이드-워셜 점검

· tech

BOJ 1541, 1389 두 문제를 문제 핵심 요약, 접근 이유, 복잡도, 실수 포인트, 코드 핵심 라인과 함께 실전형으로 정리한 글.

오늘은 문자열 수식 그리디 1문제와 그래프 최단거리 1문제를 묶어서 풀었다.

둘 다 구현 자체는 길지 않지만, “왜 이 선택이 맞는지”를 분명히 잡아두면 재사용하기 좋다.

1) BOJ 1541 - 잃어버린 괄호

문제 핵심 요약

수식에 괄호를 적절히 쳐서 결과값을 최소로 만들어야 한다. 연산자는 +, -만 나오며 숫자는 자연수 형태다.

접근 아이디어(왜 이 방법인지)

핵심 관찰은 단 하나다. -가 나온 뒤의 모든 수는 최대한 빼는 게 이득이다.

예를 들어 55-50+4055-(50+40)로 묶을 때 최소가 된다. 즉,

  1. 수식을 숫자/연산자로 파싱하고
  2. - 전까지는 더하고
  3. - 이후는 전부 빼면 된다.

괄호를 실제로 만들 필요 없이, 상태 플래그(subtractMode)만으로 처리 가능하다.

시간/공간 복잡도

실수하기 쉬운 포인트

C++ 코드 설명(핵심 라인)

if (ops[i] == '-') subtractMode = true;

if (subtractMode) answer -= nums[i + 1];
else answer += nums[i + 1];
if (isdigit(ch)) {
    current = current * 10 + (ch - '0');
}

다른 풀이 가능성

- 기준으로 문자열을 먼저 split한 뒤, 각 덩어리 안의 + 합을 계산해 첫 덩어리는 더하고 나머지는 빼는 방식도 많이 쓴다. 개인적으로는 현재 풀이처럼 단일 스캔 + 상태 전환이 디버깅이 쉽다.


2) BOJ 1389 - 케빈 베이컨의 6단계 법칙

문제 핵심 요약

사람 간 친구 관계 그래프에서, 각 사람의 “다른 사람까지의 최단거리 합”을 계산한다. 그 합(케빈 베이컨 수)이 가장 작은 사람 번호를 출력하면 된다.

접근 아이디어(왜 이 방법인지)

노드 수(N)가 크지 않은 전형적인 케이스라, 모든 쌍 최단거리를 한 번에 구하는 플로이드-워셜이 구현/검증 측면에서 가장 안정적이다.

이후 각 i에 대해 sum(dist[i][j])를 구해 최소값을 고르면 된다. 동점이면 문제 조건상 작은 번호가 유리하므로, score < bestScore일 때만 갱신하면 된다.

시간/공간 복잡도

실수하기 쉬운 포인트

C++ 코드 설명(핵심 라인)

for (int k = 1; k <= N; ++k) {
    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= N; ++j) {
            if (dist[i][k] + dist[k][j] < dist[i][j]) {
                dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
}
if (score < bestScore) {
    bestScore = score;
    bestPerson = i;
}

다른 풀이 가능성

모든 시작점에서 BFS를 N번 돌리는 방식(O(N*(N+M)))도 가능하다. 이번 문제 크기에서는 둘 다 충분히 통과 가능하며, 구현 취향에 따라 BFS 다중 실행이 더 직관적일 수도 있다.


오늘 정리 포인트:

기본기 유형이라도 이런 문제를 짧게라도 기록해두면, 이후 구현 속도가 꽤 빨라진다.