본문 바로가기

알고리즘/Baekjoon

[BOJ] 1138 한 줄로 서기 Python

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

 

1138번: 한 줄로 서기

첫째 줄에 사람의 수 N이 주어진다. N은 10보다 작거나 같은 자연수이다. 둘째 줄에는 키가 1인 사람부터 차례대로 자기보다 키가 큰 사람이 왼쪽에 몇 명이 있었는지 주어진다. i번째 수는 0보다

www.acmicpc.net

한 줄로 서기

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초 128 MB 10203 5879 4922 58.651%

문제

N명의 사람들은 매일 아침 한 줄로 선다. 이 사람들은 자리를 마음대로 서지 못하고 오민식의 지시대로 선다.

어느 날 사람들은 오민식이 사람들이 줄 서는 위치를 기록해 놓는다는 것을 알았다. 그리고 아침에 자기가 기록해 놓은 것과 사람들이 줄을 선 위치가 맞는지 확인한다.

사람들은 자기보다 큰 사람이 왼쪽에 몇 명 있었는지만을 기억한다. N명의 사람이 있고, 사람들의 키는 1부터 N까지 모두 다르다.

각 사람들이 기억하는 정보가 주어질 때, 줄을 어떻게 서야 하는지 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 사람의 수 N이 주어진다. N은 10보다 작거나 같은 자연수이다. 둘째 줄에는 키가 1인 사람부터 차례대로 자기보다 키가 큰 사람이 왼쪽에 몇 명이 있었는지 주어진다. i번째 수는 0보다 크거나 같고, N-i보다 작거나 같다. i는 0부터 시작한다.

출력

첫째 줄에 줄을 선 순서대로 키를 출력한다.

풀이 코드1  (메모리 초과)

import sys
input = sys.stdin.readline
from itertools import permutations

n = int(input())

items = list(i for i in range(1, n+1))
line = list(map(int, input().split()))

for permu in list(permutations(items, n)):
    tmp = []
    for i in range(1, n+1):
        cnt = 0
        for num in permu:
            if num == i:
                break
            else:
                if num > i : # 앞에 더 큰 사람이 있는 경우
                    cnt += 1
        tmp.append(cnt)

    if line == tmp:
        print(*permu)
        break

permutation을 이용해 모든 경우의 수를 다 확인하는 코드 ..

역시 메모리 초과가 났다.

처음 규칙을 찾지 못해서 이렇게 풀었는데, 문제를 풀떄 꼭 규칙을 찾고 그것을 이용해야 한다 ....

 

풀이 코드2 (정답 참고)

import sys
input = sys.stdin.readline

n = int(input())
heights = list(map(int, input().split()))
result = [0]*(n)

for i in range(n):
    cnt = 0
    for j in range(n):
        if result[j] == 0:
            cnt += 1
        if cnt == heights[i]+1:
            result[j] = i+1
            break


print(*result)

핵심 아이디어는 '작은 사람부터' 차례대로 배치하는 것이다.

배치하는 규칙은 자신보다 큰 사람의 수만큼 빈자리를 남겨두고 세우면 된다.

작은사람부터 배치하게 된다면, 이후 배치하게될 경우에는 빈자리만 세어도 그 빈자리가 자기보다 큰 사람이 되기 때문이다.

이 포인트를 생각하지 못했다.

규칙을 빠르게 생각해내는 연습이 많이 부족하다.

연습하자 연습 !!