CodingTest/Baekjoon

Baekjoon 1138 | 한 줄로 서기(Python)

tmdrn9 2025. 2. 25. 13:57

📌문제

SILVER2 / 구현 / 그리디 알고리즘

https://www.acmicpc.net/problem/1138

📌문제 분석 및 설계

 

문제와 예제를 보니 자신보다 작은 사람이 왼쪽에 몇 명 있는지를 고려해야 한다는 점을 발견했다.

 

1️⃣ 키가 1인 사람의 자리 결정

  • 키가 1인 사람은 자신보다 작은 사람이 없으므로,
    → 자신보다 키가 큰 사람 수에 해당하는 인덱스에 배치된다.

2️⃣ 키가 큰 사람들의 자리 결정 (키 ≥ 2)

  • 키가 2 이상인 사람들은 왼쪽에 있는 작은 사람의 수를 고려해야 한다.
  • 자신보다 작은 사람이 이미 배치되어 있다면, 원래 있어야 할 자리보다 더 뒤로 가야 한다.

3️⃣ 예제 상황 분석

  • 예를 들어, 키가 3번인 친구가 줄을 설 차례이고,
    • 왼쪽에 키가 큰 사람이 1명 있다.
    • 현재 줄의 상태가 (비어있음), 2, 1, (비어있음) 이라면,
    • 원래 index 1에 3번 친구가 배치되어야 하지만,
    • 이미 작은 키(2)가 차지하고 있으므로 index+1로 이동.
    • 그런데 그 자리에도 작은 키(1)가 있으므로 index+2가 최종 자리.

4️⃣ 핵심 설계 로직

  • 자기보다 키가 큰 사람 수(k)를 기준으로 초기 자리 설정
  • 왼쪽에서 작은 키의 사람을 발견할 때마다 k를 증가
  • 이렇게 하면 자신의 자리를 자연스럽게 찾을 수 있다.

💡 즉, 자기보다 작은 사람이 이미 자리를 차지하고 있다면, 그만큼 자신의 자리도 뒤로 이동해야 한다!

 

그 외 고려한 사항은 

  • line을 초기화 할때 0이 아닌 N+1로 한것이다. 왜냐하면 나의 시스템에서 0으로 초기화를 하면 자기보다 작은 사람 카운팅할때 카운팅되기 때문에 n+1로 설정했다.

 

📌소스 코드

n=int(input())
tall_i=list(map(int,input().split()))
line=[n+1]*n

for i,t_i in enumerate(tall_i):
    if i==0:
        line[t_i]=i+1
    else:
        turn=0
        low_cnt=0
        k=t_i+1
        while turn<k:
            if line[turn]<i+1:
                low_cnt+=1
                k+=1
            turn+=1
        line[t_i+low_cnt]=i+1

for t in line:
    print(t,end=' ')

 

지피티한테 보여주니 기존 코드에서 while 내부에서 loop를 계속 증가시키는 방식이 아니라, 한 번만 스캔하면서 배치하여 연산량을 줄여서 코드를 더 간단하게 아래와 같이 만들어줬다. 하지만 나는 이해가 촘 안가기도하고.. 그렇다 ...

 

n = int(input())
tall_i = list(map(int, input().split()))
line = [-1] * n  # 초기값을 -1로 설정

for i in range(n):
    count = tall_i[i]  # 왼쪽에 있어야 할 큰 키 사람 수
    for j in range(n):
        if line[j] == -1:  # 빈자리일 때만 count 감소
            if count == 0:  # 왼쪽에 있어야 할 사람 수를 모두 찾았으면 배치
                line[j] = i + 1
                break
            count -= 1

print(*line)

 

그리고 새로 안 건 *line하면 주르르 나온다는거... 꿀팁이다 ㅎ