본문 바로가기

HOW/BaekJoon

[BaekJoon] #7568 덩치 | 백준 파이썬(python) 풀이 및 접근방법

문제

위의 그림과 같이 육각형으로 이루어진 벌집이 있다. 그림에서 보는 바와 같이 중앙의 방 1부터 시작해서 이웃하는 방에 돌아가면서 1씩 증가하는 번호를 주소로 매길 수 있다. 숫자 N이 주어졌을 때, 벌집의 중앙 1에서 N번 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나가는지(시작과 끝을 포함하여)를 계산하는 프로그램을 작성하시오. 예를 들면, 13까지는 3개, 58까지는 5개를 지난다.

첫째 줄에 N(1 ≤ N ≤ 1,000,000,000)이 주어진다.

입력으로 주어진 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나는지 출력한다.우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x,y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x,y), (p,q)라고 할 때 x>p 그리고 y>q 이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56,177), (45,165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55,173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, "덩치"로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다.

 

첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다. 단, 2 ≤ N ≤ 50, 10 ≤ x,y ≤ 200 이다.

 

여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.


접근

이번 문제는 브루트포스라고 하는 알고리즘의 한 종류를 활용하는 문제입니다.

브루트포스가 무어냐하면 간단하게 말해서 가능한 모든 수를 대입해 보는 것이라고 할 수 있습니다.

예를 들어 자물쇠의 비밀번호가 4자리라면 0000부터 9999까지 대입해 보는 것이라고 할 수 있습니다.

무척이나 무식하고 오래거리는 방식이기에 굳이 그런걸 배워야 하나 싶지만

시간과 능력만 있다면 어떠한 암호도 해결할 수 있는 무서운 녀석이기에 모든 프로그래머들이 알아두어야 할 내용입니다.

 

여튼 위에서 알아본 브루트포스(우리말로는 무차별대입 입니다.)를 이용해 이 문제를 푼다면 어떻게 계획을 세우면 될까요?

문제의 내용은 덩치의 등급을 매기는 것이 주 내용이었습니다만 한 가지 힌트가 존재하였습니다.

 

만일 자신보다 더 큰 덩치의 사람이 $k$명이라면 그 사람의 덩치 등수는 $k+1$이 된다.

 

'덩치등수'란 것은 자신보다 더 큰 덩치의 사람의 수에서 1을 더한 것이라고 합니다.

제일 큰 사람부터 순서대로 세우는 방식이 아니기에 간단하게 자신보다 더 큰 덩치의 사람의 수를 세면 됩니다.

이러한 문제는 '브루트포스'가 어울리겠죠?

 

한 명을 정한 뒤 나머지 사람들의 덩치를 조사하여 나머지 사람이 크다면 덩치 등수 변수에 +1를 하고 같거나 작은 경우엔 continue로 넘겨주면 되겠습니다.

 


풀이

n = int(input())
people = []

for i in range(n):
    x, y = map(int, input().split())
    people.append([])
    people[i].append(x)
    people[i].append(y)
    people[i].append(1)
    
for i in range(n):
    for ii in range(n):
        if i == ii:
            continue
        else:
            if people[i][0] < people[ii][0] and people[i][1] < people[ii][1]:
                people[i][2] += 1
            else:
                continue

re = str(people[0][2])
for i in range(1, n):
    grade = people[i][2]
    re = re + " " + str(grade) 
    
print(re)

풀이 코드는 위와 같습니다.

우선 사람 수를 n으로 입력 받습니다. 그뒤 i에 range를 통해 0부터 n-1의 수를 대입하고, people 리스트에 각각 키와 몸무게, 덩치 등수를 입력합니다. ($k+1$이므로 기본적으로 1이 입력되어야 합니다.)

 

그뒤 i로 기준군을 준비하고 ii에 비교군을 준비합니다.

만일 $i=ii$인 상황 즉 동일인물일 경우 패스합니다.

아닐 경우 비교하여 기준군이 작다면 덩치 등수에 1을 더합니다.

 

그뒤 re 변수를 준비하고 for 문을 통하여 덩치 등수를 순서대로 연결합니다.

그리고 출력합니다.

 


마무리

이번 문제는 크게 어려운 문제가 아니었습니다. 제일 큰 사람부터 순서대로 나열하는 것이 아닌 단순하게 나보다 큰 사람의 수를 알면 되었기에 어렵지 않게 해결했을거라고 생각됩니다.

 

본 문제의 출처는 백준과 한국정보올림피아드(Koi) 입니다.