새소식

PS/백준

[백준/21873] 개구리 징검다리 건너기 (Python)

  • -

Problem : https://www.acmicpc.net/problem/21873

 

21873번: 개구리 징검다리 건너기

첫 번째 줄에 개구리들을 움직여야 하는 횟수 $M$을 출력한다. 단, $M$은 $1\,500\,000$을 넘어서는 안된다. 두 번째 줄부터 $M$개의 줄에 걸쳐서 움직인 개구리의 정보를 순서대로 출력한다. $p$번째

www.acmicpc.net

 

Difficulty : Gold 1

 

Status : Solved

 

Time : 00:12:21

 


 

문제 설명

 

더보기

 

서대문구에 있는 한 연못에 N마리의 하얀 개구리와 N마리의 검은 개구리가 2N+1개의 연꽃으로 이루어진 징검다리를 건너려고 하고 있다. 그림에서 보이는 것과 같이 각 무리의 개구리들에는 앞에서부터 1부터 N까지 번호가 붙어있다. 각 무리의 개구리들은 징검다리를 건너서 서로 반대쪽으로 지나가려고 하고 있다. 그러나 바쁜 일이 있는 개구리들은 서로 먼저 지나가라고 양보하기 어려운 상황이었기 때문에 모두 동시에 징검다리를 건너려고 한다.

개구리들은 다음과 같이 이동할 수 있다.

 

  • 하얀 개구리들은 오른쪽으로만, 검은 개구리들은 왼쪽으로만 움직인다.
  • 한 번에 한 마리의 개구리만 움직일 수 있다.
  • 자신의 진행 방향 바로 앞에 있는 연꽃이 비어있는 경우, 진행 방향으로 한 칸 이동할 수 있다.
  • 자신의 진행 방향 바로 앞에 있는 연꽃에 자신의 색과 다른 개구리가 있는 경우, 그 개구리 한 마리를 건너뛰어서 두 칸 이동할 수 있다.
  • 자신의 진행 방향 앞에 있는 두 개 이상의 연꽃이 비어있다고 하더라도 한 번에 두 칸 이상 이동할 수 없다.
  • 두 마리 이상의 개구리를 뛰어넘거나, 자신의 색과 같은 색의 개구리를 뛰어넘을 수 없다.

 

위의 규칙에 따라 각 개구리를 움직여서 그림과 같이 개구리들이 반대편에 도달할 수 있도록 하여라.

 

 

입력 및 출력

 

더보기

입력

각 무리에 있는 개구리의 수 N이 주어진다. (1 <= N <= 1,000)

 

출력

첫 번째 줄에 개구리들을 움직여야 하는 횟수 M을 출력한다. 단, M은 1,500,000을 넘어서는 안된다.

두 번째 줄부터 M개의 줄에 걸쳐서 움직인 개구리의 정보를 순서대로 출력한다. p번째 하얀 개구리가 움직인 경우 1 p를 출력하고, p번째 검은 개구리가 움직인 경우 2 p를 출력한다.

 

입력 예시

 

1

 

출력 예시

 

3
1 1
2 1
1 1

 

 


 

풀이

 

브루트포스로 테스팅하고 싶을테지만... 그럴 필요는 없다.

재귀적으로, 맨 처음에는 다음과 같은 상황이 가능하다.

 

  • 처음은 흰색(검은색이여도 상관없다) 개구리 1번이 1칸 움직인다.
  • 이전에 다른 색 개구리가 N번까지 움직였다고 가정하자. 그렇다면 다른 색  N번째 개구리의 칸 뒤쪽(진행 방향 반대)은 비어있을 것이고, 현재 색 1번 개구리는 N번 개구리를 뛰어넘어 그 칸에 도달할 수 있다. 현재 색 2번 개구리는 1번 개구리가 움직이면서 발생한 빈 칸에 도달할 수 있다. 이런 식으로 진행하면, 현재 색 개구리는 N+1번 개구리까지 움직일 수 있게 된다.
  • 즉 1 ~ N번까지, 1 ~ i번째 개구리를 이동하는 것이 포인트이다. 총 횟수는 N*(N+1) / 2이다.
  • 그리고 N번째 개구리가 모두 이동했다면, N번째 개구리와 다른 색의 1번째 개구리부터 N번째 개구리가 이동 가능하다. 이동 횟수는 N이다.
  • 이제부터는 반대로 적용된다. 1 ~ N번까지, i ~ N번째 개구리를 이동시킨다. i번째 이하 개구리는 배치가 끝난 상황이기 때문이다. 이동 횟수는 N*(N+1)/2이다.

 

따라서 최적의 이동 횟수는 N^2 + 2*N이며, 앞선 알고리즘에 따라 차례대로 출력을 진행하면 된다(줄글로 쓰니 어려워 보이는데, 실제로 그림을 그려가면 직관적으로 이해가 쉽다. 개구리를 N=2, N=3일때 직접 옮겨보도록 하자)

 

풀이 코드

N = int(input())

print(N**2 + 2*N)
cnt = 0
for i in range(1, N+1) :
  for j in range(1, i+1) :
    print(cnt+1, j)
  cnt = 1-cnt
for i in range(1, N+1) :
  print(cnt+1, i)
cnt = 1-cnt
for i in range(1, N+1) :
  for j in range(i, N+1) :
    print(cnt+1, j)
  cnt = 1-cnt

풀이 완료!

'PS > 백준' 카테고리의 다른 글

[백준/1045] 도로 (Python)  (1) 2024.01.16
[백준/2237] 수열 축소 (Python)  (0) 2024.01.16
[백준/9446] 아이템 제작 (Python)  (0) 2024.01.15
[백준/3344] N-Queen (Python)  (1) 2024.01.14
[백준/14438] 수열과 쿼리 17 (Python)  (0) 2024.01.13
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.