Algorithm 문제/μ•Œκ³ λ¦¬μ¦˜ λ¬Έμ œν•΄κ²°μ „λž΅

[python] μ•Œκ³ λ¦¬μ¦˜ 문제 ν•΄κ²° μ „λž΅ 1ꢌ :: μ†Œν’ (p155) 문제

희은w 2020. 2. 12. 01:28

6.3 문제: μ†Œν’ (문제 ID: PICNIC, λ‚œμ΄λ„: ν•˜)

문제

μ•ˆλ“œλ‘œλ©”λ‹€ μœ μΉ˜μ› μ΅μŠ€ν”„λ ˆμŠ€λ°˜μ—μ„œλŠ” λ‹€μŒ 주에 μœ¨λ™κ³΅μ›μœΌλ‘œ μ†Œν’μ„ κ°‘λ‹ˆλ‹€. 원석 μ„ μƒλ‹˜μ€ μ†Œν’ λ•Œ 학생듀을 두 λͺ…μ”© 짝을 μ§€μ–΄ ν–‰λ™ν•˜κ²Œ ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 그런데 μ„œλ‘œ μΉœκ΅¬κ°€ μ•„λ‹Œ 학생듀끼리 짝을 μ§€μ–΄ μ£Όλ©΄ μ„œλ‘œ μ‹Έμš°κ±°λ‚˜ 같이 λŒμ•„λ‹€λ‹ˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, 항상 μ„œλ‘œ 친ꡬ인 ν•™μƒλ“€λΌλ¦¬λ§Œ 짝을 μ§€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

각 ν•™μƒλ“€μ˜ μŒμ— λŒ€ν•΄ 이듀이 μ„œλ‘œ μΉœκ΅¬μΈμ§€ μ—¬λΆ€κ°€ μ£Όμ–΄μ§ˆ λ•Œ, 학생듀을 짝 지을 수 μžˆλŠ” λ°©λ²•μ˜ 수λ₯Ό κ³„μ‚°ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ„Έμš”. 짝이 λ˜λŠ” 학생듀이 μΌλΆ€λ§Œ λ‹€λ₯΄λ”라도 λ‹€λ₯Έ 방법이라고 λ΄…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ λ‹€μŒ 두 κ°€μ§€ 방법은 μ„œλ‘œ λ‹€λ₯Έ λ°©λ²•μž…λ‹ˆλ‹€.

  • (νƒœμ—°,μ œμ‹œμΉ΄)(μ¨λ‹ˆ,ν‹°νŒŒλ‹ˆ)(νš¨μ—°,유리)
  • (νƒœμ—°,μ œμ‹œμΉ΄)(μ¨λ‹ˆ,유리)(νš¨μ—°, ν‹°νŒŒλ‹ˆ)

μ‹œκ°„ 및 λ©”λͺ¨λ¦¬ μ œν•œ

ν”„λ‘œκ·Έλž¨μ€ 1초 내에 μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜κ³ , 64MB μ΄ν•˜μ˜ λ©”λͺ¨λ¦¬λ§Œμ„ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μž…λ ₯

μž…λ ₯의 첫 μ€„μ—λŠ” ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ 수 C(C<=50)κ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€. 각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 첫 μ€„μ—λŠ” ν•™μƒμ˜ 수 n(2<=n<=10)κ³Ό 친ꡬ 쌍의 수 m(0<=m<n*(n-1)/2)이 μ£Όμ–΄μ§‘λ‹ˆλ‹€. κ·Έ λ‹€μŒ 쀄에 m개의 μ •μˆ˜ 쌍으둜 μ„œλ‘œ 친ꡬ인 두 ν•™μƒμ˜ λ²ˆν˜Έκ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€. λ²ˆν˜ΈλŠ” λͺ¨λ‘ 0λΆ€ν„° n-1 μ‚¬μ΄μ˜ μ •μˆ˜μ΄κ³ , 같은 μŒμ€ μž…λ ₯에 두 번 μ£Όμ–΄μ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ν•™μƒλ“€μ˜ μˆ˜λŠ” μ§μˆ˜μž…λ‹ˆλ‹€.

좜λ ₯

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ§ˆλ‹€ ν•œ 쀄에 λͺ¨λ“  학생을 친ꡬ끼리만 짝지어쀄 수 μžˆλŠ” λ°©λ²•μ˜ 수λ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€.

λ‚˜μ˜ λ‹΅

import sys
import copy

test_case=int(input())
result = list()

def makePartner(std_in,dic_in,c):
    first_std = str(std_in[0])
    if first_std in dic_in:
        for value in dic_in[first_std]:
            std = copy.deepcopy(std_in)
            dic = copy.deepcopy(dic_in)
            if int(value) in std:
                del std[0]
                std.remove(int(value))
            else:
                continue
            if not(len(std)):
                result[c]+=1
            else:
                makePartner(std,dic,c)
    else:
        result[c]=0

for case in range(0,test_case):
    try:
        n_m = ""
        partner = ""
        n_m=input()
        partner = input()

        tmp_index= int()
        partner_dic = dict()

    except:
        print("input error")
        sys.exit()

    # make n, m
    for i in range(0,len(n_m)):
        if n_m[i]==" ":
            tmp_index = i

    n = int(n_m[:tmp_index])
    m = int(n_m[tmp_index:])

    # make student list
    student = list()
    for i in range(0,n):
        student.append(i)

    # make partner dictionary
    i=1
    while len(partner):
        if partner[i]==" ":
            key= partner[i-1]
            value = partner[i+1]
            partner= partner[i+3:]
            i=1
            if key>value:
                tmp = key
                key = value
                value = tmp
            if not(key in partner_dic):
                partner_dic[key]=list()
            partner_dic[key].append(value)
        else:
            i+=1

    check_bool = test_case>50 or n<2 or n>10 or m<0 or m>n*(n-1)/2
    if check_bool :
        print("input bool error")
        sys.exit()

    result.append(0)
    makePartner(student,partner_dic,case)

for i in result:
    print(i)
μ„€λͺ…

std_in, 즉 student listλŠ” ν˜„μž¬ 짝이 λ˜μ§€ λͺ»ν•œ 학생듀을 λ‚˜νƒ€λ‚΄λŠ” λ¦¬μŠ€νŠΈμ΄λ‹€.

dic_in, 즉 partner_dic dictionaryλŠ” 친ꡬ 관계λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ”•μ…”λ„ˆλ¦¬μ΄λ‹€. λ‹€μŒκ³Ό 같이 key 값이 value 값보닀 μž‘κ²Œ μ •λ ¬ν•˜μ—¬, a=>bκ°€ λ˜λ„λ‘ λ§Œλ“€μ—ˆλ‹€.

  1. λ‹€μŒκ³Ό 같이 std_inμ—μ„œ 첫번째 μš”μ†Œλ₯Ό λ°›μ•„μ˜€κ³  dic_in의 key값에 μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.

    (μœ„μ—μ„œ dic_in을 μ •λ ¬ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 3=>0은 찾을 수 μ—†μ—ˆμ„ μˆ˜λ„ 있음)

    첫번째 학생을 뢈러옴

  2. μžˆλ‹€λ©΄

    μΉœκ΅¬κ°€ μžˆλ‹€λ©΄

  3. dic_inμ—μ„œ ν•΄λ‹Ή key κ°’κ³Ό μ—°κ²°λœ value 값듀을 for문으둜 λ°›μ•„μ˜¨λ‹€.

    μΉœκ΅¬λ“€μ„ λΆˆλŸ¬μ˜¨λ‹€.

  4. ν•΄λ‹Ή key, value λͺ¨λ‘κ°€ std_inμ—μ„œ μ‘΄μž¬ν•œλ‹€λ©΄ std_inμ—μ„œ μ‚­μ œ

    μΉœκ΅¬κ΄€κ³„κ°€ 있고, 아직 짝이 λ§Ίμ–΄μ§€μ§€ μ•Šμ•˜λ‹€λ©΄ 짝을 λ§Ίμ–΄μ£ΌκΈ°

  5. std_in의 길이가 0이면 경우의 μˆ˜μ— 1 λ”ν•˜κΈ°

    짝짓기가 λλ‚¬μœΌλ©΄ 경우의 수 ν•˜λ‚˜μ— ν•΄λ‹Ή

  6. std_in이 λ‚¨μ•„μžˆμœΌλ©΄ λ‚¨μ•„μžˆλŠ” std_in의 첫번째 μš”μ†Œλ₯Ό λ°›μ•„μ™€μ„œ 1λΆ€ν„° λ‹€μ‹œ 반볡

    아직 μ•ˆ λλ‚¬μœΌλ©΄ λ‚¨μ•„μžˆλŠ” ν•™μƒμ˜ 짝을 μ°Ύμ•„μ£ΌκΈ°

μ‹œκ°„ λ³΅μž‘λ„

μ΅œμ•…μœΌλ‘œ κ³„μ‚°ν–ˆμ„ λ•Œ, N이 μ΅œλŒ“κ°’ 10이고 M이 45라고 κ°€μ •ν•˜λ©΄ 학생듀이 λͺ¨λ‘ 짝을 이룰 수 μžˆλŠ” μƒνƒœκ°€ λœλ‹€. 이 경우의 수λ₯Ό λͺ¨λ‘ κ³„μ‚°ν•˜κΈ° μœ„ν•΄ μœ„μ˜ μ½”λ“œλ₯Ό 돌리면, 9*7*5*3*1 = 945이 λ‚˜μ˜€λ―€λ‘œ μ΅œλŒ€ 945의 λ³΅μž‘λ„κ°€ λ‚˜μ˜¨λ‹€.

λ©”λͺ¨λ¦¬

λ©”λͺ¨λ¦¬λŠ” μ•½ 10MB μ‚¬μš©ν•˜μ˜€μŒ

Partition of a set of 140543 objects. Total size = 10,296,461 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 45995 33 3303978 32 3303978 32 str
1 34802 25 1466880 14 4770858 46 tuple
2 17277 12 1025011 10 5795869 56 bytes
3 8665 6 729928 7 6525797 63 types.CodeType
4 1395 1 670536 7 7196333 70 type
5 8042 6 579024 6 7775357 76 function
6 2116 2 506052 5 8281409 80 dict (no owner)
7 1395 1 405012 4 8686421 84 dict of type
8 361 0 291624 3 8978045 87 dict of module
9 367 0 149324 1 9127369 89 set
<381 more rows. Type e.g. '_.more' to view.>

 

python λ©”λͺ¨λ¦¬ 츑정법 : http://egloos.zum.com/mcchae/v/11174965

μ£Όμ–΄μ§„ λ‹΅κ³Ό λ‹€λ₯Έ 점
  1. μ£Όμ–΄μ§„ 닡은 '짝을 μ°Ύμ•˜λŠ”μ§€', 'μΉœκ΅¬μΈμ§€'의 μ—¬λΆ€λ₯Ό μ§κ΄€μ μœΌλ‘œ μ•ŒκΈ° μ‰½κ²Œ λ°°μ—΄λ‘œ ν‘œν˜„ν•˜μ˜€λ‹€. ν•˜μ§€λ§Œ μ΄λŠ” μ“Έλͺ¨μ—†λŠ” 값듀도 많이 λ‹΄κ³  μžˆμœΌλ―€λ‘œ λ©”λͺ¨λ¦¬ λ‚­λΉ„λ‘œ λ³Ό μˆ˜λ„ μžˆλ‹€. (자료ꡬ쑰 차이)

    본인은 '짝을 μ°Ύμ•˜λŠ”μ§€'λŠ” list인 student둜 ν‘œν˜„ν•˜κ³  'μΉœκ΅¬μΈμ§€'λŠ” dictionary인 partner_dic둜 ν‘œν˜„ν•˜μ˜€λ‹€. μ΄λŠ” 보기에 λ©”λͺ¨λ¦¬λ₯Ό μ ˆμ•½ν•œ κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ λ°˜λ³΅λ¬Έμ„ 돌 λ•Œλ§ˆλ‹€ deepcopyλ₯Ό μΌμ–΄μ•Όν–ˆμœΌλ―€λ‘œ μ ˆμ•½ν–ˆλ‹€κ³  λ³Ό μˆ˜λ„ μ—†λ‹€.

  2. 경우의 수 μΈ‘μ • ν›„, μ›λž˜ λ°°μ—΄λ‘œ 돌렀 놓기

    taken[firstFree] = taken[pairWith] = true;
    ret += countPairings(taken);
    taken[firstFree] = taken[pairWith] = false;

    본인은 std의 μš”μ†Œλ₯Ό μ§€μ› λ‹€κ°€ λŒλ €λ†“λŠ” 것 λŒ€μ‹ μ—, copy 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ deepcopy둜 배열듀을 λ³΅μ‚¬ν•΄μ„œ μ‚¬μš©ν•˜μ˜€λ‹€. λ”°λΌμ„œ 돌렀 놓을 ν•„μš”κ°€ μ—†μ—ˆλ‹€.

  3. return 값을 이용

    κ²°κ΅­ λ§ˆμ§€λ§‰μ— retμ΄λΌλŠ” 값을 returnν•˜μ—¬ 문제의 닡을 좜λ ₯함

    본인은 μ™ΈλΆ€ λ³€μˆ˜μ— λ”ν•˜λŠ” μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜μ˜€μŒ

    μ•ˆ 쒋은 방법인듯함! (고치기)

  4. 쀑볡을 μ œκ±°ν•˜κΈ° μœ„ν•΄ 남은 학생듀 쀑 λΉ λ₯Έ 번호λ₯Ό λΆˆλŸ¬μ˜€λŠ” 방식을 μ‚¬μš©

    본인은 쀑볡을 μ œκ±°ν•˜κΈ° μœ„ν•΄ 친ꡬ 관계λ₯Ό ν‘œν˜„ν•˜λŠ” dictionaryλ₯Ό keyκ°€ value보닀 μž‘λ„λ‘ ν•˜μ—¬ μ •λ ¬ν•˜μ˜€μŒ

λ°˜μ‘ν˜•