[python] 백준 1783 : 병든 나이트(자세한 풀이)

728x90

[python] 백준 1783 : 병든 나이트(자세한 풀이)

1783번: 병든 나이트 (acmicpc.net)

 

1783번: 병든 나이트

첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

실버 4

그리디


접근

가로가 M, 세로가 N이다.

N의 크기에 따라 나이트가 이동할 수 있는 경우의 수가 제한이 되는 부분이 있기 때문에 bfs대신 그리드를 경우의 수에 따라 나눠서 적용하는 방법을 사용해야 한다.

 

문제 조건에 따라 나이트가 이동할 수 있는 경우의 수는 다음과 같이 4가지이다.

etc-image-0

문제 조건을 읽어보면, 나이트의 초기 위치는 반드시 맨 왼쪽 아래 구석에 있기 때문에 세로 N의 길이에 따라 나이트의 이동 패턴이 제한된다.

 

N=1의 경우

나이트는 무슨 수를 써도 한 발자국도 움직이지 못하기 때문에 방문횟수는 1이다. (맨 처음 위치)

 

N=2의 경우

나이트의 이동 패턴은 두가지로 제한된다.

etc-image-1

그런데 문제 조건에 따르면, 방문횟수가 5가 될때는 나이트가 처음 제시된 4가지의 이동패턴을 적어도 한번씩은 사용을 해야만 한다고 한다.(방문횟수가 4가 될때까지는 아무 조건이 없다.)

 

따라서 N=2인 상황에서는 나이트의 방문횟수가 4를 초과할 수가 없다.

etc-image-2

방문횟수가 5가 되는 위치에 도달했다면 4가지 이동패턴을 한번씩 사용했어야 하는데 그럴 수가 없는 상황이기 때문이다. 

 

따라서 M(가로길이)의 값이 7이상이라면 방문횟수는 무조건 4로 고정된다.

M이 8미만일때의 방문횟수는 다음과 같다.

M 방문횟수
1 1
2 1
3 2
4 2
5 3
6 3
7 4

따라서 방문횟수를 간단하게 공식화하면 M+1//2와 같다.

 

결론적으로 M<7 의 경우 방문횟수는 M+1//2, M>=7의 경우의 방문횟수는 4가 되는 것이다. 이를 더 간단하게 

print(min(4, M+1//2))으로도 나타낼 수 있다.

 

 

N>=3 인 경우

세로로 뻥 뚤려있어서 이동의 제약이 사라지게 된다.

구하고자 하는 값이 방문할 수 있는 칸의 최대 개수라는 점과, 방문횟수가 5가 될 때는 4가지 이동패턴을 한번씩은 사용했어야 한다는 점을 염두에 두고 다음과 같은 경우의 수들을 살펴보자.

 

경우의 수 1

etc-image-3

가로로 한칸씩만 이동한다면 조건에 따라 나이트 방문횟수의 최댓값은 4가 된다. 4->5로 가지 못하는 이유는 4가지 이동패턴을 한번씩 사용해야 한다는 조건에 어긋나기 때문이다.

따라서 M <= 4의 범위에서 방문횟수는 M이 된다는 것을 알 수 있다.

 

 

방문횟수가 5에 도달할 때까지 4가지 이동패턴을 모두 사용하는 경우의 수(경우의 수 2)

etc-image-4

4가지 이동패턴을 모두 사용하는 M=7 구간부터는 방문횟수가 최댓값이 되어야하므로 1칸씩만 이동하면 된다.

아래의 경우도 마찬가지다.

 

방문횟수가 5에 도달할 때까지 4가지 이동패턴을 모두 사용하는 경우의 수(경우의 수 3)

etc-image-5

결론적으로 M>6 구간부터는 방문횟수는 M-2로 고정된다.

M=7일때 방문횟수가 5이고, 그 다음부터는 1씩 증가하는 것이 방문횟수의 최댓값이 되기 때문이다.

 

이제 위의 3가지 경우의 수를 M값에 따른 방문횟수의 표로 나타내면 다음과 같다.

M 방문횟수 M 방문횟수 M 방문횟수
1 1 1 1 1 1
2 2 2 1 2 2
3 3 3 2 3 3
4 4 4 2 4 3
x   5 3 5 4
x   6 4 6 4

결국 M <= 4까지의 구간에서는 방문횟수가 M이 되고, 5<=M<=6 의 구간에서는 방문횟수가 4가 되는 것이 최댓값이 된다는 것을 알 수 있다. 이는 m <= 6의 범위에서 print(min(4, m))이고 m>6의 범위에서 print(m-2)가 된다.

 

코드

import sys; input = sys.stdin.readline
n, m = map(int, input().split())
if n == 1:
    print(1)
elif n == 2:
    print(4, (m+1)//2)
elif m <= 6:
    print(min(4, m))
else:
    print(m-2)

 

실버 4라고 하기에는 너무 어려운 문제가 아닌가...

728x90