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

[python] μ•Œκ³ λ¦¬μ¦˜ 문제 ν•΄κ²° μ „λž΅ 1ꢌ :: μ‹œκ³„ λ§žμΆ”κΈ° (p168) 문제

희은w 2020. 2. 15. 22:18

6.8 문제: μ‹œκ³„ λ§žμΆ”κΈ° (문제 ID: CLOCKSYNC, λ‚œμ΄λ„: 쀑)

문제

4x4 격자 ν˜•νƒœλ‘œ 배치된 μ—΄μ—¬μ„― 개의 μ‹œκ³„κ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 μ‹œκ³„λ“€μ€ λͺ¨λ‘ 12μ‹œ, 3μ‹œ, 6μ‹œ, ν˜Ήμ€ 9μ‹œλ₯Ό 가리킀고 μžˆλŠ”λ°, 이 μ‹œκ³„λ“€μ΄ λͺ¨λ‘ 12μ‹œλ₯Ό 가리킀도둝 λ°”κΎΈκ³  μ‹ΆμŠ΅λ‹ˆλ‹€. μ‹œκ³„μ˜ μ‹œκ°„μ„ μ‘°μž‘ν•˜λŠ” μœ μΌν•œ 방법은 μ—΄ 개의 μŠ€μœ„μΉ˜λ“€μ„ μ‘°μž‘ν•˜λŠ” κ²ƒμœΌλ‘œ, 각 μŠ€μœ„μΉ˜λ“€μ€ λͺ¨λ‘ μ κ²ŒλŠ” μ„Έ κ°œμ—μ„œ λ§Žκ²ŒλŠ” λ‹€μ„― 개의 μ‹œκ³„μ— μ—°κ²°λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. ν•œ μŠ€μœ„μΉ˜λ₯Ό λˆ„λ₯Ό λ•Œλ§ˆλ‹€, ν•΄λ‹Ή μŠ€μœ„μΉ˜μ™€ μ—°κ²°λœ μ‹œκ³„λ“€μ˜ μ‹œκ°„μ€ 3μ‹œκ°„μ”© μ•žμœΌλ‘œ μ›€μ§μž…λ‹ˆλ‹€. (12μ‹œμΌλ•ŒλŠ” 3μ‹œλ‘œ, 3μ‹œ=>6μ‹œ, 6μ‹œ =>9μ‹œ, 9μ‹œ=>12μ‹œ)

μŠ€μœ„μΉ˜λ“€κ³Ό 그듀이 μ—°κ²°λœ μ‹œκ³„λ“€μ˜ λͺ©λ‘μ΄ 주어지고 ν˜„μž¬ κ°€λ¦¬ν‚€λŠ” μ‹œκ°„λ“€μ΄ μ£Όμ–΄μ‘Œμ„ λ•Œ λͺ¨λ“  μ‹œκ³„λ₯Ό 12μ‹œλ‘œ 돌리기 μœ„ν•΄ μ΅œμ†Œν•œ μŠ€μœ„μΉ˜λ₯Ό λͺ‡ λ²ˆμ΄λ‚˜ λˆŒλŸ¬μ•Ό ν•˜λŠ”μ§€ κ³„μ‚°ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ„Έμš”.

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

ν”„λ‘œκ·Έλž¨μ€ 10초 μ•ˆμ— μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜λ©°, 64MB μ΄ν•˜μ˜ λ©”λͺ¨λ¦¬λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μž…λ ₯

첫 쀄에 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 개수 C(C<=30)κ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€. 각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λŠ” ν•œ 쀄에 16개의 μ •μˆ˜λ‘œ 주어지며, 각 μ •μˆ˜λŠ” 0λΆ€ν„° 15κΉŒμ§€ 각 μ‹œκ³„κ°€ 가리킀고 μžˆλŠ” μ‹œκ°„μ„ 12,3,6,9 쀑 ν•˜λ‚˜λ‘œ ν‘œν˜„ν•©λ‹ˆλ‹€.

좜λ ₯

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‹Ή μ •μˆ˜ ν•˜λ‚˜λ₯Ό ν•œ 쀄에 좜λ ₯ν•©λ‹ˆλ‹€. 이 μ •μˆ˜λŠ” μ‹œκ³„λ“€μ„ λͺ¨λ‘ 12μ‹œλ‘œ λŒλ €λ†“κΈ° μœ„ν•΄ μŠ€μœ„μΉ˜λ₯Ό λˆŒλŸ¬μ•Ό ν•  μ΅œμ†Œ νšŸμˆ˜μ—¬μ•Ό ν•˜λ©°, λ§Œμ•½ 이것이 λΆˆκ°€λŠ₯ν•  경우 -1을 좜λ ₯ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μŠ€μœ„μΉ˜ 번호 μ—°κ²°λœ μ‹œκ³„λ“€ μŠ€μœ„μΉ˜ 번호 μ—°κ²°λœ μ‹œκ³„λ“€
0 0,1,2 5 0,2,14,15
1 3,7,9,11 6 3,14,15
2 4,10,14,15 7 4,5,7,14,15
3 0,4,5,6,7 8 1,2,3,4,5
4 6,7,8,10,12 9 3,4,5,9,13

λ‚˜μ˜ λ‹΅

import sys

c = int(input()) # testcase

switch_list=[[0,1,2],[0,2,14,15],[0,4,5,6,7],[1,2,3,4,5],[3,4,5,9,13],[3,7,9,11],[3,14,15],[4,5,7,14,15],[4,10,14,15],[6,7,8,10,12]]

def click_switch(index,time_list,type):
    tmp_list = switch_list[index]

    for i in tmp_list:
        time_list[i]+=3*type
        if time_list[i]>12:
            time_list[i] -=12
        if time_list[i]<0:
            time_list[i]+=12
    return time_list

def SwitchNum(time_list,sum_click,min_click):

    clock_index= int(-1)
    for clock in time_list: # 12μ‹œκ°€ μ•„λ‹Œ 첫 μ‹œκ³„ μ°ΎκΈ°
        if clock!=12:
            clock_index = time_list.index(clock)
            break

    if clock_index == -1: # λͺ¨λ‘ 12μ‹œλΌλ©΄
        return sum_click
    if sum_click > min_click: # μ§€κΈˆκΉŒμ§€ λ‚˜μ˜¨ μ΅œμ†Œ 횟수λ₯Ό μ΄ˆκ³Όν–ˆμœΌλ©΄
        return min_click

    tmp_switches = list()
    save_switches = list()
    for index in range(0,len(switch_list)):
        if clock_index in switch_list[index]:
            tmp = switch_list[index].index(clock_index)
            store_index = len(tmp_switches)
            for i in range(0,len(tmp_switches)):
                if tmp<tmp_switches[i][1]:
                    store_index = i
            tmp_switches.insert(store_index,[index,tmp])

    for i in tmp_switches:
        save_switches.append(i[0])

    for index in save_switches:
        time_list = click_switch(index,time_list,1)
        sum_click+=1
        net = SwitchNum(time_list,sum_click,min_click)
        time_list = click_switch(index,time_list,-1)
        sum_click-=1
        if net<min_click:
            min_click = net

    return min_click

for case in range(0,c):
    clock_time = list()
    try:
        clock_time=input().split()
    except:
        print("clock time input error")
        #sys.exit()
    for i in range(0,16):
        clock_time[i] = int(clock_time[i])

    click_num = int(0)
    result = list()
    result.append(SwitchNum(clock_time,click_num,987654321))

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

μ²˜μŒμ— ν•˜λ‚˜μ˜ 쑰각을 μŠ€μœ„μΉ˜ ν•˜λ‚˜ λˆ„λ₯΄κΈ°λΌκ³  보고 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν–ˆλ‹€. μ±…μ—μ„œ 주어진 μŠ€μœ„μΉ˜μ˜ μˆœμ„œλ₯Ό κ·ΈλŒ€λ‘œ ν•˜μ—¬ 12μ‹œκ°€ μ•„λ‹Œ 첫번째 μ‹œκ³„λ₯Ό μ°Ύμ•„, ν•΄λ‹Ή μ‹œκ³„λ₯Ό ν¬ν•¨ν•˜κ³  μžˆλŠ” μŠ€μœ„μΉ˜λ₯Ό 배열에 담은 ν›„ λ°°μ—΄μ—μ„œ ν•˜λ‚˜μ”© κΊΌλ‚΄λ©΄μ„œ μž¬κ·€μ μœΌλ‘œ μ²˜λ¦¬ν•˜λ €κ³  ν•˜μ˜€λ‹€.

이와 같은 λ°©λ²•μœΌλ‘œ κ΅¬ν˜„μ„ ν–ˆμ„ λ•Œ 첫번째 μ˜ˆμ œλΆ€ν„° λ¬΄ν•œ μž¬κ·€ν•¨μˆ˜μ— λ“€μ–΄κ°€μ„œ μ˜€λ²„ν”Œλ‘œμš° μ—λŸ¬κ°€ 났닀. λ”°λΌμ„œ 주어진 μŠ€μœ„μΉ˜ μˆœμ„œλŒ€λ‘œ κ³ λ €ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, μŠ€μœ„μΉ˜λ₯Ό κ³ λ €ν•˜λŠ” μˆœμ„œλ₯Ό λ°”κΏ”λ³΄μžλŠ” 생각에 μŠ€μœ„μΉ˜λ₯Ό index μˆœμ„œλŒ€λ‘œ 배열에 λ„£μ–΄λ³΄μ•˜λ‹€. μ—¬κΈ°μ„œ index μˆœμ΄λž€ 12μ‹œκ°€ μ•„λ‹Œ 첫번째 μˆ˜κ°€ ν•΄λ‹Ή 배열에 λ“€μ–΄μžˆλŠ” μœ„μΉ˜μ΄λ‹€.

ex_) 12 6 6 6 6 .... μ—μ„œ 12μ‹œκ°€ μ•„λ‹Œ 첫번째 μˆ˜λŠ” 2번째 μ‹œκ³„μ— μžˆλŠ” 6μ‹œμ΄λ‹€. 2번째 μ‹œκ³„(index:1)와 μ—°κ²°λœ μŠ€μœ„μΉ˜λŠ” 0,8이 μžˆλŠ”λ° 0μ—μ„œμ˜ 1의 indexλŠ” 1이고 8μ—μ„œμ˜ 1의 indexλŠ” 0μ΄λ―€λ‘œ 8번째 λ²„νŠΌμ„ 더 μš°μ„ μ μœΌλ‘œ λˆŒλŸ¬λ³Έλ‹€.

μ΄λ ‡κ²Œ κ΅¬ν˜„ν•œ μ΄μœ λŠ” 12 6 6 6 6 ... μ΄λΌλŠ” μ˜ˆμ œμ—μ„œ μ˜€λ²„ν”Œλ‘œμš°κ°€ 뜬 μ΄μœ κ°€ 8번 μŠ€μœ„μΉ˜λ³΄λ‹€ 0번 μŠ€μœ„μΉ˜λ₯Ό μš°μ„ ν•˜μ˜€κΈ° λ•Œλ¬Έμ— 0번 μŠ€μœ„μΉ˜λ₯Ό κ³ λ €ν•˜λŠ” κ³Όμ •μ—μ„œ λ¬΄ν•œ μž¬κ·€μ— λΉ μ Έμ„œ 라고 μƒκ°ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

μ΄λ ‡κ²ŒκΉŒμ§€ κ΅¬ν˜„ν–ˆμœΌλ‚˜ 첫번째 λ¬Έμ œλŠ” ν•΄κ²°ν•˜μ˜€μ§€λ§Œ, λ‘λ²ˆμ§Έ λ¬Έμ œλŠ” μ—­μ‹œ μ˜€λ²„ν”Œλ‘œμš°λ•Œλ¬Έμ— ν•΄κ²°ν•˜μ§€ λͺ»ν•˜μ˜€λ‹€. κ·Έλž˜μ„œ 쀑간에

if sum_click > min_click: # μ§€κΈˆκΉŒμ§€ λ‚˜μ˜¨ μ΅œμ†Œ 횟수λ₯Ό μ΄ˆκ³Όν–ˆμœΌλ©΄
        return min_click

λΌλŠ” μ½”λ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ μ΄λ•ŒκΉŒμ§€ 12μ‹œλ₯Ό 맞좜 수 μžˆλŠ” μ΅œμ†Œμ˜ μŠ€μœ„μΉ˜ 수λ₯Ό μ°Ύμ•˜λ‹€λ©΄, κ·Έ μŠ€μœ„μΉ˜ μˆ˜λ³΄λ‹€ λ„˜μ–΄κ°€λŠ” κ²½μš°λŠ” κ³ λ €ν•˜μ§€ μ•ŠκΈ°λ‘œ ν•˜μ˜€λ‹€. ν•˜μ§€λ§Œ 이 λ•Œλ„ 처음과 λ§ˆμ°¬κ°€μ§€λ‘œ 잘λͺ»λœ 길에 λ“€μ–΄μ„œλ©΄ λ¬΄ν•œ μž¬κ·€λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμœΌλ―€λ‘œ λͺ¨λ“  상황에 μžˆμ–΄μ„œ ν•΄κ²°λ°©μ•ˆμ€ μ•„λ‹ˆμ—ˆλ‹€.

또 λ‹€μ‹œ 생각해본 λ°©μ•ˆμ€ κ³„μ†ν•΄μ„œ 12μ‹œκ°€ μ•„λ‹Œ 첫번째 μ‹œκ³„λ₯Ό μ°ΎκΈ°λ³΄λ‹€λŠ” 1번째 μ‹œκ³„λΆ€ν„° 16번째 μ‹œκ³„κΉŒμ§€ μ°¨λ‘€λŒ€λ‘œ μ§„ν–‰ν•˜λ©΄μ„œ 12μ‹œκ°€ μ•„λ‹Œ μ‹œκ³„λ₯Ό λ°”κΎΈλŠ” λ°©μ•ˆμ΄λ‹€. ν•˜μ§€λ§Œ 이와 같은 λ°©μ•ˆμ΄ μ‹œκ°„, 곡간적인 문제λ₯Ό 쀄여쀄 것이라고 생각지 μ•ŠλŠ”λ‹€..

λ©”λͺ¨λ¦¬

Partition of a set of 140558 objects. Total size = 10299088 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 45997 33 3304117 32 3304117 32 str
1 34805 25 1467044 14 4771161 46 tuple
2 17279 12 1025087 10 5796248 56 bytes
3 8666 6 730012 7 6526260 63 types.CodeType
4 1395 1 670536 7 7196796 70 type
5 8043 6 579096 6 7775892 76 function
6 2115 2 505916 5 8281808 80 dict (no owner)
7 1395 1 405012 4 8686820 84 dict of type
8 361 0 291340 3 8978160 87 dict of module
9 367 0 150860 1 9129020 89 set
<381 more rows. Type e.g. '_.more' to view.>

첫번째 예제 κ΅¬ν˜„ λ©”λͺ¨λ¦¬μ΄λ‹€.

항상 λΉ„μŠ·ν•˜λ‹€.

주어진 λ‹΅κ³Ό λ‹€λ₯Έ 점
  1. μŠ€μœ„μΉ˜λ₯Ό λˆ„λ₯΄λŠ” μˆœμ„œλŠ” μ€‘μš”ν•˜μ§€ μ•Šλ‹€.

    계산해야 ν•  것은 μŠ€μœ„μΉ˜λ₯Ό λͺ‡ 번 λˆ„λ₯΄λŠ” 것이냐 인데, λ‚˜λŠ” μ˜€λ²„ν”Œλ‘œμš°λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ μˆœμ„œμ— λ„ˆλ¬΄ μ§‘μ°©ν–ˆλ˜ 것 κ°™λ‹€.

  2. λ¬΄ν•œν•œ 경우의 수λ₯Ό μœ ν•œν•˜κ²Œ λ§Œλ“€μž.

    μ‹œκ³„κ°€ 12μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ λŒμ•„μ˜¨λ‹€λŠ” 점을 μ΄μš©ν•΄μ„œ μ–΄λ–€ μŠ€μœ„μΉ˜κ±΄ μ΅œλŒ€ 3번 이상 λˆ„λ₯΄μ§€ μ•Šκ²Œ ν•˜μž.

    정말 생각지도 λͺ»ν–ˆλ˜ κ°€μ •

    전체 경우의 μˆ˜κ°€ 4(0~3번)의 10μŠΉλ°–μ— μ•ˆλ¨

  3. return 방식

    계속 ν—·κ°ˆλ¦¬λŠ” 것 쀑에 ν•˜λ‚˜μΈλ°, 주어진 λ‹΅μ—μ„œλŠ” 10번째 μŠ€μœ„μΉ˜μ— 닿을 λ•Œλ₯Ό 기점으둜 ν•˜μ—¬ 정렬이 λ˜μ—ˆμœΌλ©΄ 0을 returnν•˜κ²Œ ν•΄μ„œ solve ν•¨μˆ˜μ˜ return을 타고 ret을 μ°¨λ‘€λ‘œ 거쳐 λ§ˆμ§€λ§‰μ— ret으둜 return 되게 ν•˜μ˜€λ‹€. μ΄λŸ¬ν•œ 방식은 κ²°κ΅­ μ• μ΄ˆμ— 4가지 경우의 수λ₯Ό μ™„μ „ νƒμƒ‰ν•œλ‹€λŠ” 아이디어가 μžˆμ–΄μ•Ό ν•˜κ³ , μžˆμ—ˆμ–΄λ„ κ΅¬ν˜„μ„ μƒκ°ν•˜κΈ΄ μ–΄λ €μ› λ˜ 것 κ°™λ‹€. (잘 μ΅ν˜€λ‘μž!)

λ§ˆμ§€λ§‰ 경우의 수 λ”°μ§ˆ λ•Œ return 값을 μ΄μš©ν•΄ return 값을 거슬러 올라올 수 있게 λ§Œλ“€κΈ°

λ°˜μ‘ν˜•