본문 바로가기

분할정복·그리디·동적계획·백트래킹

큰 문제를 잘게 나누어 각각 푼 뒤 합칠 수도 있고, 지금 가장 좋아 보이는 선택을 이어 갈 수도 있다. 같은 부분문제가 반복되면 답을 저장할 수 있고, 가능한 선택을 따라가다가 틀리면 되돌아올 수도 있다. 이 네 생각이 각각 분할정복, 그리디, 동적계획, 백트래킹이다.

이어 읽을 선수 설명: 정당성은 불변조건과 종료를 한 줄로 잇는다, 순차·분기·반복·재귀. 각 설명의 전제를 확인한 뒤 아래의 단계 풀이와 자체 문제를 연결한다.

같은 문제도 구조를 어떻게 보느냐에 따라 풀이가 달라진다

큰 문제를 잘게 나누어 각각 푼 뒤 합칠 수도 있고, 지금 가장 좋아 보이는 선택을 이어 갈 수도 있다. 같은 부분문제가 반복되면 답을 저장할 수 있고, 가능한 선택을 따라가다가 틀리면 되돌아올 수도 있다. 이 네 생각이 각각 분할정복, 그리디, 동적계획, 백트래킹이다.

중요한 것은 알고리즘 이름을 문제에 붙이는 일이 아니다. 문제에 실제로 존재하는 구조를 확인하고, 그 구조가 정답과 비용을 보장하는 이유를 설명하는 일이다. 그리디가 빠르다는 이유만으로 쓰면 오답을 낼 수 있고, 동적계획이 정답을 보장해도 상태 수가 너무 크면 실행할 수 없다. 백트래킹은 가지치기가 약하면 모든 경우를 사실상 다 볼 수 있다.

알고리즘 설계전략의 정확한 뜻

알고리즘 설계전략은 문제의 부분구조와 선택관계를 이용하여 해법을 구성하고, 그 해법의 정당성과 비용을 함께 설명하는 재사용 가능한 사고방식이다. 하나의 전략이 하나의 코드 모양을 뜻하지는 않는다. 재귀로 썼다고 모두 분할정복은 아니며, 표를 썼다고 모두 동적계획도 아니다.

전략을 선택하려면 먼저 문제 명세에서 다음을 찾아야 한다.

  • 입력 크기와 값의 범위는 무엇인가?
  • 구해야 하는 것이 가능한 해 하나인지, 모든 해인지, 최적해인지 구분했는가?
  • 작은 문제의 답으로 큰 문제의 답을 만들 수 있는가?
  • 부분문제가 서로 독립적인가, 같은 부분문제가 반복되는가?
  • 지금의 선택이 이후 선택을 망치지 않는다는 성질을 증명할 수 있는가?
  • 후보를 일찍 버릴 수 있는 제약이나 상한·하한이 있는가?

이미 배운 기반을 짧게 연결한다

알고리즘은 유한한 단계로 입력을 출력으로 바꾸는 명확한 절차이고, 문제 명세는 입력·출력·제약·성공조건을 고정한다. 재귀는 더 작은 같은 형태의 문제와 종료사례로 풀이를 표현하며, 시간·공간 복잡도는 입력이 커질 때 필요한 연산과 저장공간의 증가를 본다. 이번 절은 이 정의를 토대로 부분문제 관계 → 선택전략 → 정당성 근거 → 시간·공간 비용 → 실패조건의 연결을 깊게 다룬다.

전략과 자료구조를 분리해서 보지 않는다

어떤 전략도 적절한 자료구조 없이 독립적으로 존재하지 않는다. 동적계획의 상태표, 그리디의 우선순위 큐, 백트래킹의 선택 스택도 모두 비용의 일부다. 같은 수학적 전략이라도 자료표현과 입력 범위가 달라지면 실제 시간·공간과 실패조건도 달라진다.

네 전략을 한눈에 잡는다

전략한 문장 직관반드시 확인할 성질대표 위험
분할정복독립적인 작은 문제로 나누고 답을 합친다분할 후 직접 풀 수 있고 결합이 가능함같은 부분문제 재계산, 결합비용 누락
그리디매 단계 가장 유리한 선택을 확정한다국소 선택이 전역 최적해를 잃지 않음증명 없는 직관으로 오답 생성
동적계획반복되는 부분문제의 답을 상태별로 한 번 저장한다재귀적 의존관계와 상태의 충분성, 최적화 문제라면 최적 부분구조상태폭발, 순서·초깃값 오류
백트래킹선택을 따라가되 불가능하면 즉시 되돌린다완전한 후보공간과 안전한 가지치기지수적 탐색, 잘못된 가지치기

네 전략은 배타적이지 않다. 분할정복을 재귀로 표현할 수 있고, 동적계획은 재귀 메모이제이션이나 반복형 표 채우기로 구현할 수 있다. 백트래킹도 깊이우선탐색과 재귀를 흔히 사용한다. 구분 기준은 문법이 아니라 부분문제와 선택을 어떤 원리로 줄이는가이다.

분할정복: 나누기·풀기·합치기

분할정복은 다음 세 단계로 진행한다.

  1. 분할: 크기 n인 문제를 더 작은 부분문제로 나눈다.
  2. 정복: 충분히 작은 종료사례는 직접 풀고, 나머지는 같은 방법으로 푼다.
  3. 결합: 부분문제의 답을 원래 문제의 답으로 합친다.

병합정렬은 배열을 반씩 나누어 각각 정렬한 뒤 두 정렬열을 합친다. 부분배열 정렬은 서로 독립적이고, 병합은 전체 원소 수에 비례한다. T(n)은 크기 n인 입력을 처리하는 연산량이며, 2T(n/2)는 절반 크기 두 문제를 푸는 비용, +O(n)은 그 두 결과를 합치는 비용을 뜻한다. 그래서 전형적인 비용은 T(n)=2T(n/2)+O(n), 전체 시간은 O(n log n)이다. 이진탐색도 정렬된 구간의 절반만 남기는 분할정복이지만, 버린 절반은 풀 필요가 없어 T(n)=T(n/2)+O(1)이고 O(log n)이다. 일반형 aT(n/b)+f(n)을 만나면 a는 풀 부분문제 수, b는 크기를 줄이는 비율, f(n)은 나누기·합치기의 추가 비용으로 읽는다.

분할정복이라고 항상 빠른 것은 아니다. 부분문제가 겹치는데 답을 저장하지 않으면 같은 계산을 반복하고, 분할은 쉽지만 결합이 비싸면 전체 비용을 지배한다. 재귀 깊이에 따른 스택 공간과 병렬 실행 시 작업 분할·결과 결합 비용도 포함해야 한다.

그리디: 가장 좋아 보이는 선택을 언제 확정할 수 있는가

그리디 알고리즘은 현재 상태에서 목적함수에 가장 유리해 보이는 후보를 선택하고, 그 선택을 되돌리지 않은 채 다음 단계로 간다. 일반적인 구성은 후보집합 → 선택규칙 → 가능성 검사 → 선택 확정 → 종료 검사다.

하지만 국소 최선이 전체 최선인지는 문제마다 다르다. 다음 둘을 설명할 수 있어야 한다.

  • 그리디 선택 성질: 어떤 최적해도 첫 그리디 선택을 포함하는 최적해로 바꿀 수 있다.
  • 최적 부분구조: 첫 선택 뒤 남은 문제의 최적해를 붙이면 전체 최적해가 된다.

예를 들어 한 회의실에서 겹치지 않는 회의를 가장 많이 고르는 문제는 종료시각이 가장 이른 회의를 고르는 규칙을 교환논증으로 증명할 수 있다. 어떤 최적해의 첫 회의를 더 일찍 끝나는 그리디 회의로 바꾸어도 뒤의 회의를 잃지 않기 때문이다. 반면 동전 {1, 3, 4}로 금액 6을 최소 개수로 만들 때 큰 동전부터 고르면 4+1+1 세 개지만 최적은 3+3 두 개다. 선택규칙이 그럴듯해도 증명이 없으면 정확한 알고리즘이 아니다.

교환논증은 임의의 최적해 일부를 그리디 선택으로 바꾸어도 해가 유효하고 품질이 나빠지지 않음을 보이는 방법이다. 절단 성질은 그래프처럼 후보를 두 집합으로 나눈 경계에서 특정 선택을 현재 부분해에 더해도 최적성을 보존하며, 그 선택을 포함하는 적어도 하나의 최적해가 존재함을 보이는 문제별 성질이다. 두 방법 모두 모든 그리디 문제에 자동 적용되는 공식이 아니라, 해당 선택규칙이 안전한 이유를 증명하는 도구다.

동적계획: 상태가 미래에 필요한 정보를 모두 담아야 한다

동적계획은 같은 부분문제의 답이 반복해서 필요할 때 그 답을 저장해 재계산을 없앤다. 최솟값·최댓값뿐 아니라 경우의 수를 세거나 가능한지를 판정하는 문제에도 쓴다. 모든 동적계획에 공통으로 필요한 것은 현재 상태가 더 작은 상태들에 의존하는 재귀적 관계, 그 의존을 먼저 계산할 수 있는 순서, 그리고 미래의 답을 구별할 만큼 충분한 상태다. 최적 부분구조나 최적성 원리는 그중 최적화 문제에서 각 상태의 최적해를 결합할 때 요구되는 조건이다. 단순히 배열을 채우는 기법이 아니라 다음 여섯 요소를 설계하는 일이다.

  1. 상태: 부분문제를 유일하게 구별하는 최소 정보
  2. 값의 의미: 그 상태에 저장된 수가 무엇을 뜻하는지
  3. 점화식: 더 작은 상태의 답으로 현재 값을 만드는 규칙
  4. 초깃값: 더 쪼갤 필요 없이 직접 아는 상태
  5. 계산순서: 필요한 이전 상태가 먼저 준비되는 순서
  6. 최종위치와 복원: 정답 값과 실제 선택을 어디서 꺼내는지

동전 {1, 3, 4}에서 금액 x를 만드는 최소 개수를 dp[x]라 두면 dp[x]=1+min(dp[x-1], dp[x-3], dp[x-4])로 표현할 수 있다. 존재하지 않는 음수 상태는 제외하고 dp[0]=0에서 작은 금액부터 채우면 dp[6]=2를 얻는다. 시간은 금액 B와 동전 종류 수 k에 대해 O(Bk), 공간은 O(B)다.

위에서 필요한 상태만 재귀적으로 계산해 저장하는 방식을 메모이제이션, 작은 상태부터 순서대로 채우는 방식을 표 채우기 또는 태뷸레이션이라 한다. 둘은 같은 점화식을 쓸 수 있지만 호출 스택, 실제 방문 상태, 순서 통제와 상수비용이 다르다.

최소 개수가 나오는 중간 계산은 다음과 같다. 각 후보는 마지막에 쓴 동전 한 개와 남은 금액의 최적 개수를 더한 값이며, —는 음수 금액이라 사용할 수 없다는 뜻이다.

금액 x마지막 1: 1+dp[x−1]마지막 3: 1+dp[x−3]마지막 4: 1+dp[x−4]최소 개수·선택 예
0———0·아무것도 선택 안 함
11——1·1
22——2·1+1
331—1·3
42211·4
52322·4+1
63232·3+3

금액 6에서는 마지막 3을 택한 후보가 1+dp[3]=2로 가장 작다. 선택한 동전 3을 빼고 금액 3의 선택 3을 다시 따라가면 실제 해 3+3을 복원한다.

min은 후보 중 가장 작은 값을 고르라는 뜻이며 dp의 대괄호 안 숫자는 금액, 저장값은 동전 개수다. 표에 이어 금액 7의 세 후보와 실제 동전 선택을 채워 보자. 마지막 1이면 1+dp[6]=3, 마지막 3이면 1+dp[4]=2, 마지막 4이면 1+dp[3]=2이므로 최소는 2개, 선택은 3+4다. 동률의 두 후보는 서로 다른 마지막 선택으로 같은 조합을 얻는다. 금액 7을 그대로 dp 값 7로 적었다면 상태를 구별하는 금액과 그 상태의 답인 개수를 혼동한 것이므로 표의 6 행에서 금액 6·개수 2를 다시 확인한다.

불가능한 상태와 서로 다른 미래를 구별한다

동전 종류에 1이 있어서 앞의 모든 금액은 만들 수 있었다. 동전을 {3,4}로 바꾸면 dp[1], dp[2], dp[5]는 불가능하다. 이 칸을 0으로 적으면 “그 금액을 동전 없이 만들었다”는 거짓 답이 된다. dp[0]=0만 직접 가능한 초기 상태로 두고 나머지는 무한대 표식으로 시작한다. dp[x-c]가 유한한 후보에서만 한 개를 더하며, 후보가 하나도 없으면 불가능 상태를 유지한다. 예컨대 dp[5]는 남은 금액 2 또는 1이 불가능해 그대로이고, dp[6]은 1+dp[3]=2가 가능하다.

무제한 동전과 한 번만 쓸 수 있는 과제도 다른 상태가 필요하다. 동전을 반복 사용할 때는 남은 금액이 같으면 다음에 쓸 동전도 같다. 반면 0/1 과제에서 “남은 예산 2”라는 정보만 보면 비용 2인 A를 이미 썼는지, 아직 선택할 수 있는지 알 수 없다. 그래서 dp[i][b]는 고려한 과제의 경계 i와 예산 b를 함께 넣는다. 1차원으로 압축해도 i에 해당하는 바깥 반복과 예산 순회 방향으로 그 경계를 지켜야 한다. 두 경우를 같은 상태로 합쳤을 때 가능한 다음 선택이 달라지는가를 묻는 것이 상태 충분성의 첫 검사다.

백트래킹: 선택트리를 완전하게 만들고 안전하게 잘라낸다

백트래킹은 해의 일부를 하나씩 만들며 선택트리를 깊이우선으로 탐색한다. 후보를 선택하고, 제약을 확인하고, 더 진행할 수 없으면 선택을 취소한 뒤 다음 후보를 시도한다.

부분 선택의 비용·효과를 함께 복구한다 · 상태 따라가기

A 비용 2·효과 3, B 비용 3·효과 4, C 비용 4·효과 6이며 같은 예산 5의 사례다. 모든 단계에서 선택 집합·비용·효과의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

부분 선택의 비용·효과를 함께 복구한다

상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.

부분 선택의 비용·효과를 함께 복구한다원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.empty → a: A 추가empty → b: B 추가empty → c: C 추가a → ab: B 추가a → ac: C 추가b → bc: C 추가ab → abc: C 추가ab → a: B 취소A 추가B 추가C 추가B 추가C 추가C 추가C 추가B 취소빈 목록: 비용 0 · 효과 0빈 목록비용 0 · 효과 0{A}: 비용 2 · 효과 3{A}비용 2 · 효과 3{B}: 비용 3 · 효과 4{B}비용 3 · 효과 4{C}: 비용 4 · 효과 6{C}비용 4 · 효과 6{A, B}: 비용 5 · 효과 7{A, B}비용 5 · 효과 7{A, C}: 비용 6 · 효과 9 예산 초과{A, C}비용 6 · 효과 9예산 초과{B, C}: 비용 7 · 효과 10 예산 초과{B, C}비용 7 · 효과 10예산 초과{A, B, C}: 비용 9 · 효과 13 예산 초과{A, B, C}비용 9 · 효과 13예산 초과
부분 선택의 비용·효과를 함께 복구한다원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.empty → a: A 추가empty → b: B 추가empty → c: C 추가a → ab: B 추가a → ac: C 추가b → bc: C 추가ab → abc: C 추가ab → a: B 취소A 추가B 추가C 추가B 추가C 추가C 추가C 추가B 취소빈 목록: 비용 0 · 효과 0빈 목록비용 0 · 효과 0{A}: 비용 2 · 효과 3{A}비용 2 · 효과 3{B}: 비용 3 · 효과 4{B}비용 3 · 효과 4{C}: 비용 4 · 효과 6{C}비용 4 · 효과 6{A, B}: 비용 5 · 효과 7{A, B}비용 5 · 효과 7{A, C}: 비용 6 · 효과 9 예산 초과{A, C}비용 6 · 효과 9예산 초과{B, C}: 비용 7 · 효과 10 예산 초과{B, C}비용 7 · 효과 10예산 초과{A, B, C}: 비용 9 · 효과 13 예산 초과{A, B, C}비용 9 · 효과 13예산 초과

원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.

이 예의 조건

  • 원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
관계도의 보충 설명
원그림의 모든 대상과 설명
대상원 설명
빈 목록비용 0 · 효과 0
{A}비용 2 · 효과 3
{B}비용 3 · 효과 4
{C}비용 4 · 효과 6
{A, B}비용 5 · 효과 7
{A, C}비용 6 · 효과 9 / 예산 초과
{B, C}비용 7 · 효과 10 / 예산 초과
{A, B, C}비용 9 · 효과 13 / 예산 초과
원그림의 모든 관계와 조건
연결원 라벨·방향
빈 목록 → {A}A 추가 / 정방향 / 실선
빈 목록 → {B}B 추가 / 정방향 / 실선
빈 목록 → {C}C 추가 / 정방향 / 실선
{A} → {A, B}B 추가 / 정방향 / 실선
{A} → {A, C}C 추가 / 정방향 / 실선
{B} → {B, C}C 추가 / 정방향 / 실선
{A, B} → {A, B, C}C 추가 / 정방향 / 실선
{A, B} → {A}B 취소 / 정방향 / 점선
예의 값과 변화
관찰·상황값·보충 정보변화·이유
예산 5 기준

A 비용 2·효과 3, B 비용 3·효과 4, C 비용 4·효과 6이며 같은 예산 5의 사례다.

  • 선택 집합: 선택 없음
  • 비용·효과: 비용 0·효과 0
  • 조합을 바꿀 때 선택과 두 합계를 함께 갱신한다.
A 선택

A를 선택한 상태에서 다음 B를 검사한다.

  • 선택 집합: 선택 A
  • 비용·효과: 비용 2·효과 3
  • 복구할 이전 상태는 A와 비용 2·효과 3이다.
B 추가

A에 B를 추가하면 비용 5·효과 7로 예산 안이다.

  • 선택 집합: 선택 A B
  • 비용·효과: 비용 5·효과 7
  • 비용 2+3=5를 확인한 허용 조합이다.
B 취소·A로 복구

다른 조합을 탐색하기 전에 B를 취소한다.

  • 선택 집합: 선택 A
  • 비용·효과: 비용 2·효과 3
  • 직전 AB의 비용 5·효과 7을 그대로 두지 않고 A의 값으로 되돌린다.
전체 탐색 결과

남은 조합까지 검사하면 C 단독 효과 6보다 AB 효과 7이 크다.

  • 선택 집합: 최적 A B
  • 비용·효과: 비용 5·효과 7
  • 실행 추적의 복구 상태와 전체 탐색 뒤의 최적 결과를 구별한다.

부분 선택의 비용·효과를 함께 복구한다 · 상태 따라가기

A 비용 2·효과 3, B 비용 3·효과 4, C 비용 4·효과 6이며 같은 예산 5의 사례다. 모든 단계에서 선택 집합·비용·효과의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

부분 선택의 비용·효과를 함께 복구한다

상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.

부분 선택의 비용·효과를 함께 복구한다원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.empty → a: A 추가empty → b: B 추가empty → c: C 추가a → ab: B 추가a → ac: C 추가b → bc: C 추가ab → abc: C 추가ab → a: B 취소A 추가B 추가C 추가B 추가C 추가C 추가C 추가B 취소빈 목록: 비용 0 · 효과 0빈 목록비용 0 · 효과 0{A}: 비용 2 · 효과 3{A}비용 2 · 효과 3{B}: 비용 3 · 효과 4{B}비용 3 · 효과 4{C}: 비용 4 · 효과 6{C}비용 4 · 효과 6{A, B}: 비용 5 · 효과 7{A, B}비용 5 · 효과 7{A, C}: 비용 6 · 효과 9 예산 초과{A, C}비용 6 · 효과 9예산 초과{B, C}: 비용 7 · 효과 10 예산 초과{B, C}비용 7 · 효과 10예산 초과{A, B, C}: 비용 9 · 효과 13 예산 초과{A, B, C}비용 9 · 효과 13예산 초과
부분 선택의 비용·효과를 함께 복구한다원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.empty → a: A 추가empty → b: B 추가empty → c: C 추가a → ab: B 추가a → ac: C 추가b → bc: C 추가ab → abc: C 추가ab → a: B 취소A 추가B 추가C 추가B 추가C 추가C 추가C 추가B 취소빈 목록: 비용 0 · 효과 0빈 목록비용 0 · 효과 0{A}: 비용 2 · 효과 3{A}비용 2 · 효과 3{B}: 비용 3 · 효과 4{B}비용 3 · 효과 4{C}: 비용 4 · 효과 6{C}비용 4 · 효과 6{A, B}: 비용 5 · 효과 7{A, B}비용 5 · 효과 7{A, C}: 비용 6 · 효과 9 예산 초과{A, C}비용 6 · 효과 9예산 초과{B, C}: 비용 7 · 효과 10 예산 초과{B, C}비용 7 · 효과 10예산 초과{A, B, C}: 비용 9 · 효과 13 예산 초과{A, B, C}비용 9 · 효과 13예산 초과

원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.

이 예의 조건

  • 원문의 예산 5와 A(비용 2·효과 3), B(3·4), C(4·6)를 사용한다. 항목 순서를 A,B,C로 고정하고 이후 항목만 추가하면 각 부분집합이 한 번씩 나온다. 빈 목록과 모든 유효 부분선택도 후보이며 최적은 {A,B}의 효과 7이다. 비용이 모두 양수이므로 이미 예산을 넘은 {A,C}, {B,C}, {A,B,C}의 후손은 안전하게 잘라낸다. 점선 B 취소는 목록·비용·효과를 {A},2,3으로 모두 되돌린다. 원문의 별도 최적화 상한 가지치기는 그 상한으로 더 나은 해가 불가능함을 증명해야 하며 예산 초과 판정과 다른 조건이다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.

관계도의 보충 설명

원그림의 모든 대상과 설명
대상원 설명
빈 목록비용 0 · 효과 0
{A}비용 2 · 효과 3
{B}비용 3 · 효과 4
{C}비용 4 · 효과 6
{A, B}비용 5 · 효과 7
{A, C}비용 6 · 효과 9 / 예산 초과
{B, C}비용 7 · 효과 10 / 예산 초과
{A, B, C}비용 9 · 효과 13 / 예산 초과
원그림의 모든 관계와 조건
연결원 라벨·방향
빈 목록 → {A}A 추가 / 정방향 / 실선
빈 목록 → {B}B 추가 / 정방향 / 실선
빈 목록 → {C}C 추가 / 정방향 / 실선
{A} → {A, B}B 추가 / 정방향 / 실선
{A} → {A, C}C 추가 / 정방향 / 실선
{B} → {B, C}C 추가 / 정방향 / 실선
{A, B} → {A, B, C}C 추가 / 정방향 / 실선
{A, B} → {A}B 취소 / 정방향 / 점선
예의 값과 변화
관찰·상황값·보충 정보변화·이유
예산 5 기준

A 비용 2·효과 3, B 비용 3·효과 4, C 비용 4·효과 6이며 같은 예산 5의 사례다.

  • 선택 집합: 선택 없음
  • 비용·효과: 비용 0·효과 0
  • 조합을 바꿀 때 선택과 두 합계를 함께 갱신한다.
A 선택

A를 선택한 상태에서 다음 B를 검사한다.

  • 선택 집합: 선택 A
  • 비용·효과: 비용 2·효과 3
  • 복구할 이전 상태는 A와 비용 2·효과 3이다.
B 추가

A에 B를 추가하면 비용 5·효과 7로 예산 안이다.

  • 선택 집합: 선택 A B
  • 비용·효과: 비용 5·효과 7
  • 비용 2+3=5를 확인한 허용 조합이다.
B 취소·A로 복구

다른 조합을 탐색하기 전에 B를 취소한다.

  • 선택 집합: 선택 A
  • 비용·효과: 비용 2·효과 3
  • 직전 AB의 비용 5·효과 7을 그대로 두지 않고 A의 값으로 되돌린다.
전체 탐색 결과

남은 조합까지 검사하면 C 단독 효과 6보다 AB 효과 7이 크다.

  • 선택 집합: 최적 A B
  • 비용·효과: 비용 5·효과 7
  • 실행 추적의 복구 상태와 전체 탐색 뒤의 최적 결과를 구별한다.

정확성을 지키려면 두 조건이 필요하다. 첫째, 생성규칙이 가능한 모든 완전해를 빠뜨리지 않아야 한다. 둘째, 가지치기는 그 가지에서 유효한 해나 더 나은 최적해가 절대로 나오지 않는다는 근거가 있어야 한다. 지금 보기 싫다는 이유로 자르면 정답을 잃는다.

되돌리기가 실제로 무엇을 복구하는지 작은 예로 보자. 자체 교육 예제로 예산 5, 과제 A의 비용 2·효과 3, B의 비용 3·효과 4, C의 비용 4·효과 6을 두고 각 과제를 한 번씩만 선택한다. 현재 상태는 (선택목록, 비용합, 효과합)이며 처음에는 (빈 목록,0,0)이다. A 선택 뒤 ({A},2,3), B 선택 뒤 ({A,B},5,7)이 된다. 여기서 C를 추가하면 비용이 9이므로 이 가지는 예산을 넘겨 더 진행하지 않는다. B 선택을 취소하면 반드시 ({A},2,3)으로 돌아가며, 다음 C 선택도 비용 6이라 제외한다. A까지 취소하면 (빈 목록,0,0)이 되어 B만 고른 해와 C만 고른 해도 조사할 수 있다.

가능한 완성 선택은 빈 목록, {A}, {B}, {C}, {A,B}이며 효과는 각각 0,3,4,6,7이어서 최적은 {A,B}다. {A,C}, {B,C}, {A,B,C}는 비용이 예산을 넘는다. 비용이 모두 양수이므로 이미 예산을 넘은 부분선택에 과제를 더해도 유효해가 될 수 없다는 것이 여기서 가지치기를 정당화하는 이유다. B를 취소할 때 목록에서만 B를 빼고 비용합 5를 남기면 어떤 문제가 생기는가? 이후 상태가 실제 선택 {A}의 비용 2와 달라져 가능한 선택을 잘못 버린다. 선택과 취소가 목록·비용·효과를 함께 되돌려야 한다는 것을 앞 두 상태와 대조한다.

N-퀸은 N×N 격자에서 서로 같은 행·열·대각선에 놓이지 않도록 N개의 말을 배치하는 문제다. 한 행에 하나씩 놓으면서 이미 사용한 열과 두 대각선을 집합으로 관리하고 충돌하는 후보는 즉시 버린다. 제약전파는 한 선택으로 불가능해진 값을 연결된 다음 후보에서도 제거하는 것이고, 대칭제거는 회전·반사처럼 본질적으로 같은 해를 대표 하나만 탐색하도록 줄이는 것이다. 최악에는 경우의 수가 지수적으로 커질 수 있지만, 좋은 후보 순서·제약전파·대칭제거·상한 계산은 실제 탐색량을 크게 줄일 수 있다.

같은 축으로 비교한다

비교축분할정복그리디동적계획백트래킹
부분문제보통 독립선택 뒤 하나의 잔여문제서로 겹침후보 선택에 따라 분기
선택 변경부분답을 결합일반적으로 되돌리지 않음여러 선택의 최적값 비교실패하면 되돌림
정당성 핵심분할·결합의 완전성, 귀납교환논증·절단 성질 등상태 충분성·의존순서, 최적화라면 최적 부분구조후보공간 완전성·안전한 가지치기
대표 자원재귀 스택·결합 버퍼정렬·우선순위 구조상태표·복원정보탐색 스택·제약집합·현재 최선
흔한 비용aT(n/b)+f(n)정렬 등이 지배상태 수 × 전이 수최악 지수적 후보 수
잘 맞는 상황독립 부분문제와 효율적 결합국소 선택을 확정할 증명반복 부분문제와 관리 가능한 상태조합 제약, 모든 해·정확한 최적해 탐색
실패 신호중복 계산·비싼 결합작은 반례 하나로 최적성 붕괴상태폭발·잘못된 점화식가지치기 거의 없음·정답 누락

빠르다, 정확하다 같은 한 단어 비교는 부족하다. 정확성 보장 조건, 최악복잡도, 필요한 메모리, 입력 범위와 근삿값 허용 여부를 함께 써야 한다.

정답을 보장하는 이유를 전략별로 쓴다

앞서가기 논증은 그리디가 만든 부분해가 매 단계에서 어떤 최적해의 같은 길이 부분보다 뒤처지지 않음을 보인 뒤 최종 품질을 결론 내리는 방법이다. 앞 단계의 비교기준과 다음 단계에도 그 관계가 보존되는 이유를 함께 써야 한다.

전략흔히 쓰는 설명도구답안에서 확인할 문장
분할정복수학적 귀납, 재귀 불변조건부분문제의 답이 옳으면 결합 결과도 전체 조건을 만족한다
그리디교환논증, 앞서가기 논증, 절단 성질최적해의 선택을 그리디 선택으로 바꿔도 품질이 나빠지지 않는다
동적계획상태 귀납, 최적화에서는 최적성 원리점화식이 필요한 모든 이전 상태를 포함하며, 최적화라면 모든 마지막 선택과 이전 상태의 최적성을 포괄한다
백트래킹탐색공간 분할, 가지치기 안전성모든 후보는 정확히 한 가지에 속하고 잘린 가지에는 답이 없다

증명을 장황한 수식으로만 쓸 필요는 없다. 다만 최적이라고 가정한다로 결론을 반복해서도 안 된다. 무엇을 바꾸어도 손해가 없는지, 점화식이 모든 마지막 선택을 포함하는지, 가지치기 조건이 왜 안전한지를 구체적으로 밝힌다.

여기까지의 결론

분할정복은 나눈 답의 결합, 그리디는 되돌리지 않는 선택의 증명, 동적계획은 충분한 상태와 의존순서, 백트래킹은 후보공간의 완전성과 안전한 가지치기가 핵심이다. 재귀나 표 같은 코드 모양만으로 전략을 구분하지 않는다. 다음부터는 문제의 목표·겹침·증명 가능성·상태 수·자원예산으로 전략을 선택한다.

선택은 여덟 질문으로 좁힌다

  1. 목표: 가능해 하나, 모든 해, 정확한 최적해, 근사해 중 무엇인가?
  2. 분해: 더 작은 같은 형태로 나눌 수 있는가?
  3. 겹침: 같은 부분문제가 여러 경로에서 반복되는가?
  4. 국소선택: 선택을 되돌리지 않아도 된다는 증명이 있는가?
  5. 상태: 미래에 필요한 정보를 작고 유일한 상태로 표현할 수 있는가?
  6. 가지치기: 불가능하거나 현재 최선보다 나쁜 가지를 안전하게 판정할 수 있는가?
  7. 예산: 입력 최대치에서 시간·공간 상한을 감당할 수 있는가?
  8. 검증: 작은 전수탐색과 반례 생성으로 정확성을 비교할 수 있는가?

그리디 증명이 없다면 동적계획이나 탐색을 검토한다. 상태 수가 너무 크면 상태압축·문제분해·근사 또는 제약탐색을 비교한다. 빠르게 쓸 만한 답을 찾되 일반적인 정확성이나 품질보장은 따로 증명되지 않은 경험적 규칙을 휴리스틱(heuristic)이라고 하므로, 이를 선택하면 실패사례와 품질 측정방법을 함께 밝힌다. 정확한 최적해가 필수가 아니라면 오차보장과 실행시간을 명시한 근사법이 더 적절할 수도 있다.

시간과 공간을 세는 법

전략시간 비용을 결정하는 요소놓치기 쉬운 공간
분할정복부분문제 수·크기·결합비용재귀 깊이, 임시 결합 배열
그리디후보 정렬, 선택 횟수, 자료구조 연산우선순위 큐·선택상태
동적계획가능한 상태 수 × 상태당 전이 수전체 표, 복원 포인터, 큰 값 표현
백트래킹실제 방문 노드 수, 최악 후보공간재귀 스택, 현재 부분해, 제약 인덱스

동적계획의 O(nB)에서 B가 숫자값이면 입력 비트 길이에 대해서는 매우 클 수 있다. 이처럼 숫자값에는 다항식이지만 그 수를 적는 비트 길이에 대해서는 지수적으로 커질 수 있는 비용을 의사다항(pseudopolynomial)이라고 하며, 단순히 다항시간이라고 쓰면 오해가 생긴다. 백트래킹도 가지치기 후 평균 실행이 빠르다는 실험과 최악 상한을 분리해야 한다. 그리디는 선택 전에 정렬하면 전체가 흔히 O(n log n)이며, 분할정복은 재귀식의 결합항을 빼먹지 않는다.

없앨 수 없는 교환관계

긴장얻는 것치르는 비용판단 기준
그리디 단순성 ↔ 최적성 보장빠른 결정·작은 메모리적용 가능한 문제구조가 제한됨교환논증 또는 문제별 정리 존재 여부
동적계획 시간 ↔ 공간중복 계산 제거상태표 메모리 증가상태 수, 롤링 배열·복원 필요 여부
메모이제이션 ↔ 표 채우기필요한 상태만 방문 ↔ 순서·상수비용 통제호출 스택 ↔ 불필요 상태 계산희소 상태, 의존순서, 최대 깊이
백트래킹 정확성 ↔ 예측가능한 시간모든 해·정확한 최적해 가능최악 지수시간입력 최대치, 가지치기 강도, 시간제한
상태 세분화 ↔ 상태폭발더 정확한 미래 구분차원·메모리 증가같은 상태로 합쳐도 미래 선택이 동일한가
전처리 ↔ 질의속도정렬·색인 후 반복 질의 가속준비·갱신 비용질의 횟수와 데이터 변경률

좋은 설계는 한 전략을 끝까지 고집하지 않는다. 예를 들어 백트래킹의 남은 최적값 상한을 동적계획으로 계산하거나, 분할정복한 부분을 동적계획으로 풀 수 있다. 조합할수록 경계와 비용을 더 명확히 써야 한다.

어디서 실패하는가

실패원인·징후결과예방·검증
분할정복 종료사례 누락크기가 줄지 않거나 빈 구간 처리 없음무한재귀·경계 오류감소량과 최소 입력을 명세하고 시험
결합 불변조건 오류부분답은 맞지만 합치는 규칙이 원소를 잃음전체 오답순열·정렬·중복 보존조건 검사
그리디 반례 누락가장 큰 값 등 직관만 사용일부 입력에서 비최적작은 입력 전수탐색으로 반례 탐색, 교환논증
DP 상태정보 부족서로 다른 미래를 가진 경우를 같은 상태로 합침점화식은 계산되나 오답상태의 충분성을 반례로 검사
DP 순서·초깃값 오류참조할 상태가 미계산, 불가능 상태를 0으로 둠거짓 최적값의존 그래프, 무한대 표식, 경계표 작성
DP 상태폭발차원·값 범위가 큼메모리 부족·시간초과상태 수를 먼저 계산하고 압축·대안 비교
백트래킹 복구 누락선택 취소 때 집합·합계 일부가 남음다음 가지 오염선택/해제 대칭, 불변조건 검사
위험한 가지치기경험적 상한을 증명된 상한처럼 사용최적해 영구 누락안전성 증명, 가지치기 없는 작은 정답과 대조
복잡도 전제 은폐평균 입력·작은 수치범위에만 의존운영 중 급격한 지연최대 입력·적대 입력·공간까지 분리 기록

하나의 작은 반례로 전략 차이를 확인한다

문제는 동전 {1, 3, 4}를 반복 사용하여 금액 6을 최소 개수로 만드는 것이다.

그리디: 가장 큰 4 선택 → 남은 2 → 1, 1 선택 = 3개
최적해: 3, 3 = 2개

DP 상태: dp[x] = 금액 x의 최소 동전 수
초기값: dp[0] = 0
전이:   dp[x] = 1 + min(dp[x-c])  (c는 x 이하의 동전)
결과:   dp[6] = 2

그리디는 유효한 해를 빠르게 만들지만 최적성을 잃었다. 동적계획은 금액별 최적 답을 저장해 정확한 답을 만든다. 백트래킹으로 모든 조합을 탐색해도 정답을 얻지만, 금액과 동전 종류가 커지면 후보 수가 급증한다. 분할정복만 적용하면 같은 남은 금액을 여러 경로에서 반복 계산하므로, 답을 저장하는 순간 동적계획의 핵심으로 넘어간다.

이 예는 동적계획이 언제나 우월하다는 뜻이 아니다. 통화 체계처럼 특정 동전집합에서 그리디 최적성이 증명되거나 입력 범위가 매우 크고 근사해가 허용되면 다른 선택이 적절할 수 있다.

알고리즘 설계의 핵심 학습 논점

알고리즘을 공부할 때는 특정 정렬법 하나를 외우는 데 그치지 않고, 문제구조에 맞는 전략과 그 전략이 옳은 이유를 설명해야 한다. 다음 다섯 가지를 점검하자.

  1. 문제 명세와 입력 제약을 기준으로 설계전략을 선택한다.
  2. 분할정복·그리디·동적계획·백트래킹의 부분문제 구조와 작동원리를 구분한다.
  3. 정당성 조건과 반례, 시간·공간 복잡도를 함께 제시한다.
  4. 상태·자료구조·가지치기·결합방식이 성능과 정확성에 미치는 영향을 설명한다.
  5. 실패조건과 검증방법까지 답안 구조로 전환한다.

앞 절의 탐색·정렬·그래프 알고리즘은 이 원리를 구체화한 사례다. 같은 사례를 다시 볼 때, 부분문제의 관계·선택의 정당성·상태 수·가지치기 조건을 기준으로 전략을 설명해 보자.

시험에서는 어떻게 묻는가: 10점

다음은 알고리즘 설계전략의 선택과 정당성을 연습하기 위한 자체 제작 문제다. 실제 기출이나 공식 배점 기준을 뜻하지 않는다.

분할정복, 그리디, 동적계획, 백트래킹의 작동원리와 적용조건을 비교하고, 각 전략의 대표 실패조건을 설명하시오.

작동원리는 부분문제를 줄이는 방식, 적용조건은 정당성을 보장하는 문제구조, 실패조건은 오답 또는 실행불능이 생기는 조건을 요구한다. 알고리즘 예시만 네 개 쓰면 요구어를 충족하지 못한다.

답안 목차·풀이·교정 근거 보기

10점 답안 목차

  1. 정의와 선택기준
    • 부분문제 관계·선택 확정·상태 반복·후보공간
  2. 네 전략의 작동원리
    • 분할·정복·결합 / 국소선택 / 상태·점화식 / 선택·검사·복구
  3. 정당성·복잡도 비교
    • 귀납·교환논증·최적성 원리·가지치기 안전성
  4. 실패조건과 결론
    • 중복·반례·상태폭발·지수탐색, 입력제약 기반 선택

답안 도식

목표·입력·제약·정확도부터 고정한다. 독립적으로 나누어 결합할 수 있으면 분할정복, 국소 선택을 확정해도 손해가 없음을 증명하면 그리디, 반복되는 충분한 상태를 관리할 수 있으면 동적계획, 후보 분기와 제약을 완전 탐색하고 안전하게 잘라낼 수 있으면 백트래킹을 검토한다. 정당성 근거와 시간·공간 비용, 반례·최악 입력을 함께 설명하고 작은 전수정답 대조 및 경계시험을 수행한다. 위의 같은 축 비교와 증명도구를 재사용한다.

10점 모범답안

알고리즘 설계전략은 문제의 부분구조와 선택관계를 이용해 해법을 구성하고 정당성과 비용을 설명하는 방식이다. 분할정복은 독립적인 작은 문제로 나누어 재귀적으로 풀고 결합한다. 분할이 줄어드는 종료조건과 결합의 완전성을 귀납적으로 보이며, 전체 비용은 부분문제 수·크기와 결합비용을 포함한 재귀식으로 계산한다. 부분문제가 겹치거나 결합이 비싸면 중복과 비용이 커진다.

그리디는 매 단계의 국소 최선 선택을 되돌리지 않는다. 교환논증이나 절단 성질로 그 선택을 포함하는 최적해가 존재함을 보여 줘야 하며, 동전 {1,3,4}의 금액 6처럼 반례가 있으면 정확한 최적화법이 아니다. 동적계획은 반복되는 부분문제를 충분한 상태와 점화식으로 나타내고 필요한 이전 상태부터 계산해 답을 저장한다. 계수·판정에도 적용할 수 있고, 최적화 문제에서는 최적 부분구조와 최적성 원리를 추가로 확인한다. 시간은 상태 수와 상태당 전이 수, 공간은 상태표와 복원정보로 계산하며 상태가 미래에 필요한 정보를 빠뜨리거나 상태 수가 크면 실패한다.

백트래킹은 선택트리를 깊이우선으로 탐색하다 제약을 위반하거나 더 좋은 답이 불가능하면 되돌린다. 후보 생성의 완전성과 가지치기의 안전성을 보여 줘야 하며 최악에는 지수시간이다. 따라서 재귀·표·우선순위 큐 같은 코드 모양이 아니라 목표, 부분문제 독립·중복, 국소선택 증명, 상태 수, 가지치기와 시간·공간 예산으로 전략을 선택하고 작은 전수정답·반례·경계입력으로 검증한다.

예산 5에서 두 과제를 끝까지 계산한다

독립적인 과제 A는 비용 2·효과 3, B는 비용 3·효과 4이며 각 과제는 최대 한 번만 선택한다. dp[i][b]는 앞의 i개 과제로 예산 b 이하에서 얻는 최대효과다. 과제 i를 빼면 dp[i−1][b], 넣을 수 있으면 dp[i−1][b−c[i]]+v[i]이므로 두 후보의 큰 값을 저장한다. 표에는 b=0,1,2,3,4,5 순서의 값을 한 행으로 묶었다.

고려한 과제예산 0~5의 최대효과핵심 계산
없음0, 0, 0, 0, 0, 0아무 과제도 없으면 모두 0
A까지0, 0, 3, 3, 3, 3예산 4도 A를 한 번만 넣어 3
A와 B0, 0, 3, 4, 4, 7예산 5는 max(3,dp[1][2]+4)=max(3,7)=7

최종칸 7은 이전 행 3과 다르므로 B를 선택하고 남은 예산은 5−3=2다. A 행의 예산 2 값 3도 이전 행 0과 다르므로 A를 선택한다. 선택목록 {A,B}의 비용 2+3=5, 효과 3+4=7이 표와 일치한다. 동률이면 제외를 택하는 등 복원 규칙을 고정하면 여러 최적해 중 하나를 일관되게 얻는다.

1차원 배열에서 A를 처리할 때 예산을 오름차순으로 순회하면 dp[2]=3을 만든 뒤 dp[4]=dp[2]+3=6으로 같은 A를 두 번 쓰게 된다. 내림차순이면 예산 4를 계산할 때 아직 이전 행의 dp[2]=0을 읽어 3에 머문다. 이 차이가 0/1과 무제한 선택을 가르는 실제 상태 변화다.

2차원 점화식을 1차원으로 줄일 때 순서가 바뀌면 답도 바뀐다

2차원 표 dp[i][b]는 i번째 과제를 계산할 때 이전 행 i-1만 읽는다. 최댓값만 필요하면 한 배열을 재사용할 수 있지만, 예산 b를 작은 값부터 갱신하면 이번 과제로 방금 바꾼 dp[b-c[i]]를 다시 읽어 같은 과제를 여러 번 고르게 된다. 따라서 0/1 선택에서는 b=B..c[i]의 역순으로 갱신해 각 칸이 여전히 이전 행의 값을 읽도록 한다.

큰 b부터: 이전 행의 값을 읽는다 · 상태 따라가기

A 비용 2·효과 3을 한 번만 쓰는 0/1 조건에서 dp의 모든 칸은 0이다. 모든 단계에서 dp 배열·이번 A·용량 b의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

큰 b부터: 이전 행의 값을 읽는다

넓은 화면과 모바일에서 같은 관계를 각각의 배치로 읽을 수 있습니다.

큰 b부터: 이전 행의 값을 읽는다A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.dp[0]0dp[1]0dp[2]0dp[3]0dp[4]3 이전 값 0 + 효과 3b 감소: 4, 3, 2
큰 b부터 이전 셀을 읽는 실제 의존성A의 비용 2와 효과 3을 한 번 적용한다. b=4를 먼저 갱신한 직후 배열은 dp[0..4]=0,0,0,0,3이다. 화살표는 아직 이전 행인 dp[2]=0을 읽어 효과 3을 더한 dp[4]=3의 의존성이다. b=3과 2는 아직 갱신하지 않았다. 세로 셀 순서는 예산 인덱스이며 시간축이 아니다.큰 b부터 갱신b: 4 → 3 → 20+3dp[0]0dp[1]0dp[2]0dp[3]0dp[4]30은 이전 dp[2]A: 비용 2 · 효과 3b=4 갱신 직후b=3,2는 갱신 전

A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.

이 예의 조건

  • A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.
  • A의 비용 2와 효과 3을 한 번 적용한다. b=4를 먼저 갱신한 직후 배열은 dp[0..4]=0,0,0,0,3이다. 화살표는 아직 이전 행인 dp[2]=0을 읽어 효과 3을 더한 dp[4]=3의 의존성이다. b=3과 2는 아직 갱신하지 않았다. 세로 셀 순서는 예산 인덱스이며 시간축이 아니다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
초기 배열

A 비용 2·효과 3을 한 번만 쓰는 0/1 조건에서 dp의 모든 칸은 0이다.

  • dp 배열: dp=[0,0,0,0,0]
  • 이번 A·용량 b: A 전·b=4부터
  • 내림순은 이번 A가 반영되지 않은 작은 칸을 읽기 위한 순서다.
b=4 갱신

b=4에서는 옛 dp[2]=0에 효과 3을 더한다.

  • dp 배열: dp=[0,0,0,0,3]
  • 이번 A·용량 b: b=4·옛 dp[2]=0
  • dp[4]=3이며 이번 A가 이미 들어간 dp[2]를 읽지 않는다.
b=3 갱신

다음 b=3에서는 옛 dp[1]=0을 읽어 3으로 갱신한다.

  • dp 배열: dp=[0,0,0,3,3]
  • 이번 A·용량 b: b=3·옛 dp[1]=0
  • 큰 용량에서 작은 용량으로 갱신해 같은 A의 중복 사용을 막는다.
b=2 완료

마지막 b=2에서는 해당 칸을 dp[0]=0에 +3을 더한 값으로 갱신하고 끝낸다.

  • dp 배열: dp=[0,0,3,3,3]
  • 이번 A·용량 b: b=2·A 1회 사용
  • dp[2]를 나중에 갱신하므로 앞 b=4에서 새 dp[2]를 재사용하지 않는다.

큰 b부터: 이전 행의 값을 읽는다 · 상태 따라가기

A 비용 2·효과 3을 한 번만 쓰는 0/1 조건에서 dp의 모든 칸은 0이다. 모든 단계에서 dp 배열·이번 A·용량 b의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

큰 b부터: 이전 행의 값을 읽는다

넓은 화면과 모바일에서 같은 관계를 각각의 배치로 읽을 수 있습니다.

큰 b부터: 이전 행의 값을 읽는다A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.dp[0]0dp[1]0dp[2]0dp[3]0dp[4]3 이전 값 0 + 효과 3b 감소: 4, 3, 2
큰 b부터 이전 셀을 읽는 실제 의존성A의 비용 2와 효과 3을 한 번 적용한다. b=4를 먼저 갱신한 직후 배열은 dp[0..4]=0,0,0,0,3이다. 화살표는 아직 이전 행인 dp[2]=0을 읽어 효과 3을 더한 dp[4]=3의 의존성이다. b=3과 2는 아직 갱신하지 않았다. 세로 셀 순서는 예산 인덱스이며 시간축이 아니다.큰 b부터 갱신b: 4 → 3 → 20+3dp[0]0dp[1]0dp[2]0dp[3]0dp[4]30은 이전 dp[2]A: 비용 2 · 효과 3b=4 갱신 직후b=3,2는 갱신 전

A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.

이 예의 조건

  • A의 비용은 2, 효과는 3이다. 아직 A를 적용하지 않은 이전 행은 모두 0이다. b=4를 먼저 갱신하면 dp[2]는 이전 행의 0이므로 dp[4]=0+3=3이 된다. 표시된 배열은 이 갱신 직후이며 뒤의 b=3,2 갱신 전에 찍은 상태다. 큰 b에서 작은 b로 갱신하여 같은 A를 최대 한 번 사용한다.
  • A의 비용 2와 효과 3을 한 번 적용한다. b=4를 먼저 갱신한 직후 배열은 dp[0..4]=0,0,0,0,3이다. 화살표는 아직 이전 행인 dp[2]=0을 읽어 효과 3을 더한 dp[4]=3의 의존성이다. b=3과 2는 아직 갱신하지 않았다. 세로 셀 순서는 예산 인덱스이며 시간축이 아니다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
초기 배열

A 비용 2·효과 3을 한 번만 쓰는 0/1 조건에서 dp의 모든 칸은 0이다.

  • dp 배열: dp=[0,0,0,0,0]
  • 이번 A·용량 b: A 전·b=4부터
  • 내림순은 이번 A가 반영되지 않은 작은 칸을 읽기 위한 순서다.
b=4 갱신

b=4에서는 옛 dp[2]=0에 효과 3을 더한다.

  • dp 배열: dp=[0,0,0,0,3]
  • 이번 A·용량 b: b=4·옛 dp[2]=0
  • dp[4]=3이며 이번 A가 이미 들어간 dp[2]를 읽지 않는다.
b=3 갱신

다음 b=3에서는 옛 dp[1]=0을 읽어 3으로 갱신한다.

  • dp 배열: dp=[0,0,0,3,3]
  • 이번 A·용량 b: b=3·옛 dp[1]=0
  • 큰 용량에서 작은 용량으로 갱신해 같은 A의 중복 사용을 막는다.
b=2 완료

마지막 b=2에서는 해당 칸을 dp[0]=0에 +3을 더한 값으로 갱신하고 끝낸다.

  • dp 배열: dp=[0,0,3,3,3]
  • 이번 A·용량 b: b=2·A 1회 사용
  • dp[2]를 나중에 갱신하므로 앞 b=4에서 새 dp[2]를 재사용하지 않는다.

작은 b부터: 같은 A의 새 값을 다시 읽는다 · 상태 따라가기

같은 A 비용 2·효과 3, 모든 dp=0에서 잘못된 오름순을 비교한다. 모든 단계에서 dp 배열·오름순의 재사용의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

작은 b부터: 같은 A의 새 값을 다시 읽는다

넓은 화면과 모바일에서 같은 관계를 각각의 배치로 읽을 수 있습니다.

작은 b부터: 같은 A의 새 값을 다시 읽는다A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.dp[0]0dp[1]0dp[2]3dp[3]3dp[4]6 새 값 3 + 효과 3b 증가: 2, 3, 4

A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.

작은 b부터 새 셀을 다시 읽는 의존성비용 2와 효과 3인 A에서 작은 b부터 갱신하면 b=2의 새 dp[2]=3을 b=4가 다시 읽어 dp[4]=3+3=6이 되어 같은 A를 두 번 사용하므로 0/1 선택 계약을 위반하며, b=4 갱신 직후의 예산 인덱스 배열은 0,0,3,3,6이다.작은 b부터 갱신b: 2 → 3 → 43+3dp[0]0dp[1]0dp[2]3dp[3]3dp[4]63은 새 dp[2]A: 비용 2 · 효과 3같은 A를 두 번 사용0/1 선택 계약 위반

이 예의 조건

  • A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.
  • 비용 2와 효과 3인 A에서 작은 b부터 갱신하면 b=2의 새 dp[2]=3을 b=4가 다시 읽어 dp[4]=3+3=6이 되어 같은 A를 두 번 사용하므로 0/1 선택 계약을 위반하며, b=4 갱신 직후의 예산 인덱스 배열은 0,0,3,3,6이다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
초기 배열

같은 A 비용 2·효과 3, 모든 dp=0에서 잘못된 오름순을 비교한다.

  • dp 배열: dp=[0,0,0,0,0]
  • 오름순의 재사용: b=2부터
  • 0/1 조건을 그대로 두고 갱신 순서만 바꾼 오류 사례다.
b=2 갱신

dp[0]=0에 A 효과 3을 더해 dp[2]=3을 만든다.

  • dp 배열: dp=[0,0,3,0,0]
  • 오름순의 재사용: 이번 A 반영 dp[2]=3
  • 이 작은 칸은 이미 이번 A를 사용한 값이 된다.
b=3 갱신

dp[1]=0에 효과 3을 더해 dp[3]=3이다.

  • dp 배열: dp=[0,0,3,3,0]
  • 오름순의 재사용: 다음 b=4
  • 오름순에서 새 dp[2]는 다음 큰 용량의 입력으로 남아 있다.
b=4 중복 반영

b=4에서는 새 dp[2]=3에 같은 A의 3을 또 더해 6이 된다.

  • dp 배열: dp=[0,0,3,3,6]
  • 오름순의 재사용: dp4=3+3=6
  • 정상 내림순의 dp[4]=3과 달리 같은 A를 두 번 사용해 0/1 계약을 어긴다.

작은 b부터: 같은 A의 새 값을 다시 읽는다 · 상태 따라가기

같은 A 비용 2·효과 3, 모든 dp=0에서 잘못된 오름순을 비교한다. 모든 단계에서 dp 배열·오름순의 재사용의 위치를 유지하며 값과 허용 조건을 함께 확인합니다.

작은 b부터: 같은 A의 새 값을 다시 읽는다

넓은 화면과 모바일에서 같은 관계를 각각의 배치로 읽을 수 있습니다.

작은 b부터: 같은 A의 새 값을 다시 읽는다A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.dp[0]0dp[1]0dp[2]3dp[3]3dp[4]6 새 값 3 + 효과 3b 증가: 2, 3, 4

A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.

작은 b부터 새 셀을 다시 읽는 의존성비용 2와 효과 3인 A에서 작은 b부터 갱신하면 b=2의 새 dp[2]=3을 b=4가 다시 읽어 dp[4]=3+3=6이 되어 같은 A를 두 번 사용하므로 0/1 선택 계약을 위반하며, b=4 갱신 직후의 예산 인덱스 배열은 0,0,3,3,6이다.작은 b부터 갱신b: 2 → 3 → 43+3dp[0]0dp[1]0dp[2]3dp[3]3dp[4]63은 새 dp[2]A: 비용 2 · 효과 3같은 A를 두 번 사용0/1 선택 계약 위반

이 예의 조건

  • A의 비용은 2, 효과는 3이다. b=2에서 dp[2]=3을 만든 뒤 b=4에서 같은 배열의 새 dp[2]를 읽어 dp[4]=3+3=6이 된다. 이것은 A를 두 번 사용한 값이므로 원문의 0/1 선택 계약에서 잘못된 답이다. 표시된 배열은 b=4 갱신 직후다.
  • 비용 2와 효과 3인 A에서 작은 b부터 갱신하면 b=2의 새 dp[2]=3을 b=4가 다시 읽어 dp[4]=3+3=6이 되어 같은 A를 두 번 사용하므로 0/1 선택 계약을 위반하며, b=4 갱신 직후의 예산 인덱스 배열은 0,0,3,3,6이다.
  • 이 원문의 교육용 사례·조건 안에서 상태를 대조합니다. 실제 구축·실험 결과나 원문에 없는 성능 보장을 추가하지 않습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
초기 배열

같은 A 비용 2·효과 3, 모든 dp=0에서 잘못된 오름순을 비교한다.

  • dp 배열: dp=[0,0,0,0,0]
  • 오름순의 재사용: b=2부터
  • 0/1 조건을 그대로 두고 갱신 순서만 바꾼 오류 사례다.
b=2 갱신

dp[0]=0에 A 효과 3을 더해 dp[2]=3을 만든다.

  • dp 배열: dp=[0,0,3,0,0]
  • 오름순의 재사용: 이번 A 반영 dp[2]=3
  • 이 작은 칸은 이미 이번 A를 사용한 값이 된다.
b=3 갱신

dp[1]=0에 효과 3을 더해 dp[3]=3이다.

  • dp 배열: dp=[0,0,3,3,0]
  • 오름순의 재사용: 다음 b=4
  • 오름순에서 새 dp[2]는 다음 큰 용량의 입력으로 남아 있다.
b=4 중복 반영

b=4에서는 새 dp[2]=3에 같은 A의 3을 또 더해 6이 된다.

  • dp 배열: dp=[0,0,3,3,6]
  • 오름순의 재사용: dp4=3+3=6
  • 정상 내림순의 dp[4]=3과 달리 같은 A를 두 번 사용해 0/1 계약을 어긴다.

실제 선택목록까지 복원하려면 2차원 표나 별도의 선택·부모정보를 남겨야 한다. 단순한 1차원 최댓값 배열만으로는 일반적으로 어떤 과제를 골랐는지 되살릴 수 없다. 공간을 줄이는 결정과 답을 복원하는 결정은 함께 검토해야 한다.

시험에서는 어떻게 묻는가: 25점

다음 역시 본문만으로 풀 수 있게 만든 자체 제작 문제다.

비용과 기대효과가 주어진 정보화 개선과제 중 예산 한도 안에서 총효과를 최대화하는 0/1 선택 알고리즘을 설계하시오. 동적계획의 상태·점화식·복잡도와 복원방안을 제시하고, 그리디 및 백트래킹 대안의 적용조건·실패조건·검증방안을 비교하시오.

0/1은 각 과제를 선택하거나 선택하지 않는다는 뜻이다. 효과가 선택한 분량에 선형으로 비례하고 과제들이 서로 독립적이어서 임의 비율로 나눌 수 있을 때는 효과/비용 비율 그리디를 정당화할 수 있다. 과제를 쪼갤 수 없거나 효과가 비선형이거나 과제 간 종속성이 있으면 그 결론을 그대로 쓸 수 없으며, 일반적인 0/1 문제의 정확해도 보장하지 않는다. 답안은 상태의 뜻과 범위부터 고정해야 한다.

답안 목차·풀이·교정 근거 보기

25점 답안 목차

  1. 문제 경계와 전제
    • 과제별 정수 비용·효과, 예산 B, 0/1 선택, 효과 합 최대
  2. 동적계획 설계
    • 상태 의미, 선택/비선택 점화식, 초깃값·계산순서
    • 2차원 표, 최댓값용 1차원 역순 압축, 선택·부모정보를 이용한 복원
  3. 복잡도와 대안 비교
    • O(nB) 시간·공간, 수치값 의존성
    • 비율 그리디의 비최적 반례, 백트래킹의 지수상한·가지치기
  4. 실패·통제
    • 상태폭발, 정수범위, 종속·상호배타 제약, 복원 불일치
  5. 검증과 운영 판단
    • 작은 전수탐색 대조, 경계·최대부하, 입력·목표 변화 시 재설계

25점 답안 도식

과제 i의 비용 c[i], 효과 v[i], 예산 B에서 dp[i][b]는 앞의 i개 과제로 예산 b 이하에서 얻는 최대효과다. i를 제외한 후보는 dp[i−1][b], c[i]≤b일 때 선택한 후보는 dp[i−1][b−c[i]]+v[i]이며 두 후보의 max를 저장한다. dp[n][B]에서 역추적하고 선택목록·총비용·총효과를 검증한다. 추상 흐름을 반복하는 대신 위의 예산 5 전체 계산과 복원을 사용하고, 바로 아래 완성 답안의 상태·전이식·초깃값·계산순서 및 복원 정보를 대조한다.

25점 모범답안

입력은 n개 개선과제의 양의 정수 비용 c[i], 기대효과 v[i]와 정수 예산 B다. 과제는 분할할 수 없고 한 번만 선택하며, 선택비용 합이 B 이하인 해 중 효과 합 최대를 구한다. 종속·상호배타 과제는 우선 범위 밖으로 두고 별도 제약 확장으로 명시한다.

상태 dp[i][b]는 앞의 i개 과제만 고려하여 예산 b 이하에서 얻을 수 있는 최대효과다. 과제 i를 선택하지 않으면 dp[i-1][b], 비용이 b 이하일 때 선택하면 dp[i-1][b-c[i]]+v[i]이므로 둘의 최댓값을 저장한다. 초깃값은 과제가 없거나 예산이 0일 때 0이며, i=1..n, b=0..B 순서로 채운다. 각 칸의 선택 여부를 기록하거나 dp[i][b]와 이전 행을 역비교하면 dp[n][B]에서 실제 과제목록을 복원할 수 있다.

2차원 구현의 시간은 O(nB), 공간은 O(nB)다. 최댓값만 필요하면 예산을 큰 값부터 역순으로 순회하는 1차원 O(B) 공간으로 압축할 수 있다. 작은 값부터 순회하면 같은 과제를 여러 번 선택하는 무제한 문제로 의미가 바뀌므로 0/1 불변조건을 깨뜨린다. B는 숫자값이어서 예산 단위가 매우 세밀하거나 크면 상태폭발이 생기는 의사다항 비용임을 명시한다.

효과가 선택 분량에 선형으로 비례하고 과제들이 서로 독립적이며 임의 비율로 나눌 수 있을 때는 효과/비용 비율 그리디를 정당화할 수 있다. 일반적인 0/1 선택에서는 반례가 존재해 정확해를 보장하지 않는다. 백트래킹은 선택/비선택 트리를 완전 탐색하고 남은 효과의 낙관적 상한이 현재 최선 이하일 때 가지치기하면 정확해를 구할 수 있지만 최악 O(2^n)이다. 따라서 B가 관리 가능하면 동적계획, n이 작고 제약이 복잡하며 가지치기가 강하면 백트래킹, 근사 허용과 품질보장이 있으면 근사법을 비교한다.

검증은 n=0, B=0, 모든 과제가 예산 초과, 동일 비용·효과, 최적해 다수, 정수 합계 한계를 포함한다. 작은 입력에서는 모든 부분집합 전수결과와 DP·복원목록을 대조하고, 선택목록의 비용합·효과합과 표의 최종값이 일치하는지 검사한다. 종속·상호배타·다중예산이 추가되면 현재 상태가 미래 제약을 구분하지 못하므로 상태나 문제모형을 다시 설계한다.

직접 연습: 숫자와 조건을 바꾸어 전략을 검증한다

다음 세 문제는 자체 연습이다. 먼저 결과를 계산하고, 그 결과를 보장하는 조건을 함께 적어 보자.

  1. 동전 {3,4}를 반복 사용하여 금액 5와 6을 만드는 최소 개수를 구하라. 불가능한 상태를 0으로 초기화하면 금액 5에서 어떤 거짓 후보가 나오는가?
  2. 예산 5, A(비용 2·효과 3), B(3·4), C(4·6)를 각각 한 번만 선택한다. 효과/비용 비율 순서로 고르는 그리디와 모든 부분집합의 최적해를 비교하라. 같은 비용·효과라도 과제를 자유롭게 나눌 수 있다면 왜 결론이 달라지는가?
  3. 과제 1000개, 예산 B=1,000,000, 값 한 칸을 8바이트로 두자. 2차원 (n+1)×(B+1) 표와 1차원 B+1 배열의 값 저장공간을 바이트로 계산하라. 1차원 배열이 작으면 O(nB) 실행시간도 자동으로 감당할 수 있는가?
연습 풀이와 전제 확인 보기
  1. 5는 만들 수 없고 6은 3+3의 2개다. 불가능한 dp[2]나 dp[1]을 0으로 두면 dp[5]=1+min(dp[2],dp[1])=1이라는 거짓 답이 생긴다. 무한대 표식을 유지하고 유한한 이전 상태만 후보로 쓰면 이 오류를 막는다.
  2. 비율은 C가 1.5, A가 1.5, B가 4/3이다. 동률을 A 우선으로 두면 A 다음 C는 예산 밖이므로 B를 골라 효과 7을 얻지만, C 우선이면 남은 예산 1로 효과 6에 멈춘다. 전수 비교의 최적은 비용 5·효과 7의 {A,B}다. 동률 규칙에 따라 한 예에서 맞아도 일반 0/1 문제의 최적성 증명이 되지 않는다. 임의 비율로 나눌 수 있고 효과가 분량에 선형 비례한다면 C 전체와 A의 절반으로 예산 5를 써 효과 7.5를 얻는다. 이 경우는 분할 가능한 다른 문제다.
  3. 2차원 값 저장공간은 1001×1,000,001×8=8,008,008,008바이트, 1차원은 1,000,001×8=8,000,008바이트다. 이 수에는 컨테이너·객체·복원정보와 실행환경의 추가 공간이 포함되지 않는다. 1차원으로 줄여도 약 10억 개 예산 상태의 갱신을 검토하므로 시간 비용은 남는다. 필요한 최적값·복원 여부와 실행시간 예산을 함께 정하고 실제 최대 입력에서 측정해야 한다.

근거와 현행성

정의와 전략 경계는 미국 국립표준기술연구소(NIST) 정보기술연구소의 Dictionary of Algorithms and Data Structures에서 divide and conquer, greedy algorithm, dynamic programming, memoization, principle of optimality, backtracking, recursion 항목과 대조했다. 사이트 DOI는 10.18434/T4/1422485, 기준 확인일은 2026-08-31이다.

예산 수치와 입력 길이를 구별하는 비용 설명은 MIT 6.006의 배낭문제·의사다항 시간 강의자료와 함께 대조했다. 추가 연습의 메모리 수치는 한 칸 8바이트라는 자체 가정의 계산이며 특정 언어의 실제 배열 메모리를 뜻하지 않는다.

본문의 표·도식·동전 반례·정보화 과제 선택 문제와 답안은 원문 표현이나 그림을 옮기지 않고 교재용으로 독자 구성했다. 복잡도는 본문에 명시한 전형적 구현과 전제 아래의 이론값이며 특정 언어·제품의 보장을 뜻하지 않는다. 각 문제의 조건에서 전략이 올바른지 확인하는 것이 목적이며, 자체 제작 답안을 공식 채점 기준으로 해석하지 않는다.

30초 정리

  1. 분할정복은 독립 부분문제를 나누어 풀고 결합하며, 그리디는 증명 가능한 국소선택을 확정한다.
  2. 동적계획은 겹치는 부분문제를 상태·점화식으로 한 번씩 풀고, 백트래킹은 완전한 선택트리를 안전하게 가지치기한다.
  3. 전략 이름보다 정당성 조건, 상태·자료구조, 시간·공간과 반례·최악입력을 함께 써야 한다.
  4. 작은 전수정답과 경계입력으로 검증하고 입력 범위나 정확도 요구가 바뀌면 전략을 다시 선택한다.

다음 장부터는 같은 원칙을 운영체제, 수치해석, 가상화와 네트워크의 구체적인 문제구조에 적용한다.