λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μΉ΄ν…Œκ³ λ¦¬ μ—†μŒ

μˆœμ—΄ μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜ κ°œλ…κ³Ό 예제 (κ΅¬ν˜„)

by 5566 2023. 9. 18.

1. μˆœμ—΄κ³Ό μ‘°ν•©μ˜ κΈ°λ³Έ κ°œλ…

μˆœμ—΄κ³Ό 쑰합은 μˆ˜ν•™μ μΈ κ°œλ…μœΌλ‘œ, 주어진 μ›μ†Œλ“€μ„ μ‘°ν•©ν•˜μ—¬ λ‹€μ–‘ν•œ 경우λ₯Ό λ§Œλ“€μ–΄λ‚΄λŠ” 방법을 μ˜λ―Έν•©λ‹ˆλ‹€. μˆœμ—΄μ€ 주어진 μ›μ†Œλ“€μ˜ μˆœμ„œλ₯Ό λ°”κΏ”μ„œ λ§Œλ“€ 수 μžˆλŠ” 경우의 수λ₯Ό λ§ν•˜λ©°, 쑰합은 μˆœμ„œμ— 상관없이 주어진 μ›μ†Œλ“€μ„ 뽑아 λ§Œλ“€ 수 μžˆλŠ” 경우의 수λ₯Ό λ§ν•©λ‹ˆλ‹€.

μˆœμ—΄

μ›μ†Œλ“€μ΄ μˆœμ„œλ₯Ό 가지고 λ°°μ—΄λ˜λŠ” 것을 μˆœμ—΄μ΄λΌκ³  ν•©λ‹ˆλ‹€. n개의 μ›μ†Œκ°€ μžˆμ„ λ•Œ, 이듀을 일렬둜 λ‚˜μ—΄ν•˜λŠ” 경우의 μˆ˜λŠ” n! (n νŒ©ν† λ¦¬μ–Ό)μž…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ›μ†Œ A, B, C의 μˆœμ—΄μ€ ABC, ACB, BAC, BCA, CAB, CBA의 6가지 κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. μˆœμ—΄μ€ μ›μ†Œμ˜ μˆœμ„œμ— 따라 λ‹€λ₯Έ 경우λ₯Ό λ§Œλ“€μ–΄λ‚΄λ―€λ‘œ, μˆœμ„œκ°€ μ€‘μš”ν•œ κ²½μš°μ— 주둜 ν™œμš©λ©λ‹ˆλ‹€.

μ‘°ν•©

μ›μ†Œλ“€μ„ μˆœμ„œμ— 상관없이 μ„ νƒν•˜μ—¬ λ§Œλ“€ 수 μžˆλŠ” 경우의 수λ₯Ό 쑰합이라고 ν•©λ‹ˆλ‹€. n개의 μ›μ†Œ 쀑 r개λ₯Ό μ„ νƒν•˜λŠ” 쑰합은 C(n, r) λ˜λŠ” nCr둜 ν‘œκΈ°ν•©λ‹ˆλ‹€. 쑰합은 μ›μ†Œμ˜ μˆœμ„œμ— 상관없이 μ„ νƒν•˜λ―€λ‘œ, λ™μΌν•œ μ›μ†Œλ“€μ„ μ‚¬μš©ν•˜μ—¬ λ§Œλ“€μ–΄μ§„ κ²½μš°λŠ” ν•œ κ°€μ§€λ‘œ μ·¨κΈ‰λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ›μ†Œ A, B, C μ€‘μ—μ„œ 2개의 μ›μ†Œλ₯Ό μ„ νƒν•˜μ—¬ λ§Œλ“€ 수 μžˆλŠ” 쑰합은 AB, AC, BC의 3가지 κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€.

μˆœμ—΄κ³Ό 쑰합은 λ‹€μ–‘ν•œ 문제 해결에 μ‚¬μš©λ  수 μžˆλŠ” μœ μš©ν•œ κ°œλ…μœΌλ‘œ, 컴퓨터 μ•Œκ³ λ¦¬μ¦˜μ—μ„œλ„ 널리 ν™œμš©λ©λ‹ˆλ‹€. λ‹€μŒ μž₯μ—μ„œλŠ” μˆœμ—΄κ³Ό μ‘°ν•©μ˜ κ΅¬ν˜„ 방법에 λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

2. μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜μ˜ κ΅¬ν˜„

주어진 μ›μ†Œμ˜ μˆœμ—΄μ„ μƒμ„±ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ μž¬κ·€μ μΈ 방법을 μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•Œκ³ λ¦¬μ¦˜μ˜ κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. 주어진 μ›μ†Œλ“€ 쀑 μ„ νƒλ˜μ§€ μ•Šμ€ μ›μ†Œλ₯Ό ν•˜λ‚˜μ”© μ„ νƒν•©λ‹ˆλ‹€.
  2. μ„ νƒλœ μ›μ†Œλ₯Ό 결과에 μΆ”κ°€ν•©λ‹ˆλ‹€.
  3. μ„ νƒλœ μ›μ†Œλ₯Ό μ œμ™Έν•œ λ‚˜λ¨Έμ§€ μ›μ†Œλ“€λ‘œ μž¬κ·€ ν˜ΈμΆœν•©λ‹ˆλ‹€.
  4. μž¬κ·€ ν˜ΈμΆœμ„ 톡해 얻은 결과에 μ„ νƒν•œ μ›μ†Œλ₯Ό λΆ™μ—¬μ„œ μˆœμ—΄μ„ μ™„μ„±ν•©λ‹ˆλ‹€.
  5. λͺ¨λ“  μ›μ†Œλ“€μ΄ 선택될 λ•ŒκΉŒμ§€ λ°˜λ³΅ν•©λ‹ˆλ‹€.

μ•„λž˜λŠ” 이 μ•Œκ³ λ¦¬μ¦˜μ„ Python으둜 κ΅¬ν˜„ν•œ μ˜ˆμ‹œμž…λ‹ˆλ‹€:

def permutation(elements, result, depth):
    # μž¬κ·€ 호좜 μ’…λ£Œ 쑰건: λͺ¨λ“  μ›μ†Œκ°€ 선택됐을 λ•Œ
    if depth == len(elements):
        print(result)
        return

    for i in range(len(elements)):
        # 이미 μ„ νƒλœ μ›μ†ŒλŠ” κ±΄λ„ˆλœλ‹ˆλ‹€.
        if elements[i] in result:
            continue

        # μ›μ†Œλ₯Ό μ„ νƒν•˜κ³  μž¬κ·€ ν˜ΈμΆœν•©λ‹ˆλ‹€.
        result.append(elements[i])
        permutation(elements, result, depth + 1)

        # μ„ νƒν•œ μ›μ†Œλ₯Ό λ‹€μ‹œ μ œκ±°ν•©λ‹ˆλ‹€.
        result.pop()

# μˆœμ—΄μ„ μƒμ„±ν•˜κΈ° μœ„ν•΄ ν˜ΈμΆœν•©λ‹ˆλ‹€.
elements = ['A', 'B', 'C']
permutation(elements, [], 0)

μœ„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 주어진 μ›μ†Œλ“€μ„ λͺ¨λ‘ μ‚¬μš©ν•˜μ—¬ 생성할 수 μžˆλŠ” μˆœμ—΄μ„ 좜λ ₯ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 3개의 μ›μ†Œ A, B, C둜 생성할 수 μžˆλŠ” μˆœμ—΄μ€ ABC, ACB, BAC, BCA, CAB, CBAμž…λ‹ˆλ‹€. 이 μ•Œκ³ λ¦¬μ¦˜μ€ μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•˜λ―€λ‘œ, μ›μ†Œμ˜ κ°œμˆ˜μ— 따라 μ‹œκ°„ λ³΅μž‘λ„κ°€ μ¦κ°€ν•©λ‹ˆλ‹€. λ‹€μŒ μž₯μ—μ„œλŠ” μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ— λŒ€ν•΄ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

3. μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ˜ κ΅¬ν˜„

μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ€ 주어진 μ›μ†Œλ“€ μ€‘μ—μ„œ 일뢀λ₯Ό μ„ νƒν•˜μ—¬ 쑰합을 μƒμ„±ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€. 일반적으둜 μž¬κ·€μ μΈ 방법을 μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•Œκ³ λ¦¬μ¦˜μ˜ κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. 주어진 μ›μ†Œλ“€ μ€‘μ—μ„œ 일뢀λ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
  2. μ„ νƒλœ μ›μ†Œλ₯Ό 결과에 μΆ”κ°€ν•©λ‹ˆλ‹€.
  3. μ„ νƒλœ μ›μ†Œλ₯Ό μ œμ™Έν•œ λ‚˜λ¨Έμ§€ μ›μ†Œλ“€λ‘œ μž¬κ·€ ν˜ΈμΆœν•©λ‹ˆλ‹€.
  4. μž¬κ·€ ν˜ΈμΆœμ„ 톡해 얻은 결과에 μ„ νƒν•œ μ›μ†Œλ₯Ό λΆ™μ—¬μ„œ 쑰합을 μ™„μ„±ν•©λ‹ˆλ‹€.
  5. μ„ νƒλ˜μ§€ μ•Šμ€ μ›μ†Œλ“€μ„ μΆ”κ°€λ‘œ μ„ νƒν•˜λ©΄μ„œ λͺ¨λ“  쑰합을 μƒμ„±ν•©λ‹ˆλ‹€.

μ•„λž˜λŠ” 이 μ•Œκ³ λ¦¬μ¦˜μ„ Python으둜 κ΅¬ν˜„ν•œ μ˜ˆμ‹œμž…λ‹ˆλ‹€:

def combination(elements, result, depth, start):
    # μž¬κ·€ 호좜 μ’…λ£Œ 쑰건: λͺ¨λ“  μ›μ†Œκ°€ 선택됐을 λ•Œ
    if depth == len(result):
        print(result)
        return

    for i in range(start, len(elements)):
        # μ›μ†Œλ₯Ό μ„ νƒν•˜κ³  μž¬κ·€ ν˜ΈμΆœν•©λ‹ˆλ‹€.
        result[depth] = elements[i]
        combination(elements, result, depth + 1, i + 1)

# 쑰합을 μƒμ„±ν•˜κΈ° μœ„ν•΄ ν˜ΈμΆœν•©λ‹ˆλ‹€.
elements = ['A', 'B', 'C']
r = 2  # 선택할 μ›μ†Œμ˜ 개수
combination(elements, [None] * r, 0, 0)

μœ„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 주어진 μ›μ†Œλ“€ μ€‘μ—μ„œ r개λ₯Ό μ„ νƒν•˜μ—¬ 생성할 수 μžˆλŠ” λͺ¨λ“  쑰합을 좜λ ₯ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 3개의 μ›μ†Œ A, B, C μ€‘μ—μ„œ 2개의 μ›μ†Œλ₯Ό μ„ νƒν•˜μ—¬ 생성할 수 μžˆλŠ” 쑰합은 AB, AC, BCμž…λ‹ˆλ‹€. 이 μ•Œκ³ λ¦¬μ¦˜μ€ 주어진 μ›μ†Œλ“€μ˜ κ°œμˆ˜μ™€ 선택할 μ›μ†Œμ˜ κ°œμˆ˜μ— 따라 μ‹œκ°„ λ³΅μž‘λ„κ°€ μ¦κ°€ν•©λ‹ˆλ‹€. μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜κ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ κ΅¬ν˜„λœ μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ€ λ‹€μ–‘ν•œ 문제 해결에 μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€.

4. μˆœμ—΄κ³Ό μ‘°ν•©μ˜ μ‘μš© 예제

μˆœμ—΄κ³Ό 쑰합은 λ‹€μ–‘ν•œ 문제 해결에 μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. 이제 μˆœμ—΄κ³Ό μ‘°ν•©μ˜ μ‘μš© 예제λ₯Ό λͺ‡ 가지 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

4.1. 둜또 번호 생성기

둜또 번호 μƒμ„±κΈ°λŠ” 1λΆ€ν„° 45κΉŒμ§€μ˜ 숫자 μ€‘μ—μ„œ 6개의 숫자λ₯Ό μ„ νƒν•˜μ—¬ 둜또 번호λ₯Ό μƒμ„±ν•˜λŠ” λ¬Έμ œμž…λ‹ˆλ‹€. 이 λ¬Έμ œλŠ” 쑰합을 μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ μ˜ˆμ‹œμž…λ‹ˆλ‹€:

def generate_lotto_numbers():
    elements = list(range(1, 46))
    r = 6

    combination(elements, [None] * r, 0, 0)

μœ„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 1λΆ€ν„° 45κΉŒμ§€μ˜ 숫자 μ€‘μ—μ„œ 6개의 숫자λ₯Ό μ„ νƒν•˜μ—¬ 생성할 수 μžˆλŠ” λͺ¨λ“  μ‘°ν•©, 즉 둜또 번호λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 둜또 번호 생성기λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

4.2. μ•”ν˜Έ 해독

μ•”ν˜Έ 해독은 주어진 μ•”ν˜Έλ₯Ό ν•΄λ…ν•˜μ—¬ 원문을 μ°ΎλŠ” λ¬Έμ œμž…λ‹ˆλ‹€. μ•”ν˜Έ 해독은 μˆœμ—΄μ„ μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ μ˜ˆμ‹œμž…λ‹ˆλ‹€:

def decrypt_message(ciphertext, result, depth, used):
    # μž¬κ·€ 호좜 μ’…λ£Œ 쑰건: λͺ¨λ“  λ¬Έμžκ°€ 해독됐을 λ•Œ
    if depth == len(result):
        print(result)
        return

    for i in range(len(ciphertext)):
        if not used[i]:
            # 문자λ₯Ό ν•΄λ…ν•˜κ³  μž¬κ·€ ν˜ΈμΆœν•©λ‹ˆλ‹€.
            result[depth] = ciphertext[i]
            used[i] = True
            decrypt_message(ciphertext, result, depth + 1, used)
            used[i] = False

μœ„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 주어진 μ•”ν˜Έλ₯Ό ν•΄λ…ν•˜μ—¬ κ°€λŠ₯ν•œ λͺ¨λ“  원문을 좜λ ₯ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ•”ν˜Έ 해독을 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μˆœμ—΄κ³Ό 쑰합은 이외에도 λ§Žμ€ λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜λŠ” 데에 μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ μˆœμ—΄κ³Ό 쑰합을 μ‘μš©ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν•¨μœΌλ‘œμ¨, λ‹€μ–‘ν•œ μ•Œκ³ λ¦¬μ¦˜μ„ 읡힐 수 있고 문제 ν•΄κ²° λŠ₯λ ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

5. μˆœμ—΄κ³Ό μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„ 뢄석

μˆœμ—΄κ³Ό μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ€ μ›μ†Œμ˜ 개수 nκ³Ό 선택할 μ›μ†Œμ˜ 개수 r에 따라 μ‹œκ°„ λ³΅μž‘λ„κ°€ μ¦κ°€ν•©λ‹ˆλ‹€. 이제 각 μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό λΆ„μ„ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

5.1. μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„

μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜μ€ μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€. 탐색해야 ν•˜λŠ” 경우의 μˆ˜λŠ” n!개이며, 각 ν˜ΈμΆœλ§ˆλ‹€ n-1, n-2, ..., 1번의 μž¬κ·€ 호좜이 λ°œμƒν•©λ‹ˆλ‹€. λ”°λΌμ„œ μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(n!)μž…λ‹ˆλ‹€.

5.2. μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„

μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ€ μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜κ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ μž¬κ·€ ν˜ΈμΆœμ„ μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€. 탐색해야 ν•˜λŠ” 경우의 μˆ˜λŠ” nCr개이며, 각 ν˜ΈμΆœλ§ˆλ‹€ r-1, r-2, ..., 1번의 μž¬κ·€ 호좜이 λ°œμƒν•©λ‹ˆλ‹€. λ”°λΌμ„œ μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(nCr)μž…λ‹ˆλ‹€.

μˆœμ—΄κ³Ό μ‘°ν•© μ•Œκ³ λ¦¬μ¦˜μ€ 경우의 수λ₯Ό λͺ¨λ‘ νƒμƒ‰ν•˜κΈ° λ•Œλ¬Έμ— 일뢀 λ¬Έμ œμ—μ„œλŠ” λΉ„νš¨μœ¨μ μΌ 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ›μ†Œμ˜ κ°œμˆ˜κ°€ 맀우 큰 경우 탐색 μ‹œκ°„μ΄ κΈ‰κ²©νžˆ 증가할 수 μžˆμŠ΅λ‹ˆλ‹€. 이런 κ²½μš°μ—λŠ” λ‹€λ₯Έ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜κ±°λ‚˜ μ΅œμ ν™” 기법을 μ μš©ν•˜μ—¬ 효율적인 해결책을 μ°Ύμ•„μ•Ό ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 문제의 쑰건과 μ œμ•½μ„ κ³ λ €ν•˜μ—¬ μ•Œλ§žμ€ μ•Œκ³ λ¦¬μ¦˜μ„ μ„ νƒν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.

λŒ“κΈ€