문제:

김지민은 N명이 참가하는 스타 토너먼트에 진출했다. 토너먼트는 다음과 같이 진행된다. 일단 N명의 참가자는 번호가 1번부터 N번까지 배정받는다. 그러고 난 후에 서로 인접한 번호끼리 스타를 한다. 이긴 사람은 다음 라운드에 진출하고, 진 사람은 그 라운드에서 떨어진다. 만약 그 라운드의 참가자가 홀수명이라면, 마지막 번호를 가진 참가자는 다음 라운드로 자동 진출한다. 다음 라운드에선 다시 참가자의 번호를 1번부터 매긴다. 이때, 번호를 매기는 순서는 처음 번호의 순서를 유지하면서 1번부터 매긴다. 이 말은 1번과 2번이 스타를 해서 1번이 진출하고, 3번과 4번이 스타를 해서 4번이 진출했다면, 4번은 다음 라운드에서 번호 2번을 배정받는다. 번호를 다시 배정받은 후에 한 명만 남을 때까지 라운드를 계속 한다.

마침 이 스타 대회에 임한수도 참가했다. 김지민은 갑자기 스타 대회에서 우승하는 욕심은 없어지고, 몇 라운드에서 임한수와 대결하는지 궁금해졌다. 일단 김지민과 임한수는 서로 대결하기 전까지 항상 이긴다고 가정한다. 1 라운드에서 김지민의 번호와 임한수의 번호가 주어질 때, 과연 김지민과 임한수가 몇 라운드에서 대결하는지 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에 참가자의 수 N과 1 라운드에서 김지민의 번호와 임한수의 번호가 순서대로 주어진다. N은 100,000보다 작거나 같은 자연수이고, 김지민의 번호와 임한수의 번호는 N보다 작거나 같은 자연수이고, 서로 다르다.

출력:

첫째 줄에 김지민과 임한수가 대결하는 라운드 번호를 출력한다. 만약 서로 대결하지 않을 때는 -1을 출력한다.

풀이방법:

 주어진 조건에 따라 수행하게 하는 구현문제다. 앞에서부터 순차적으로 두 사람을 뽑은 뒤에 각 사람이 k와 l인지 확인하고, 둘 중 하나에 해당하면 그 사람이 무조건 이기게 한다. 만약 각각 k와 l에 해당하면 반복문을 중단시킨다.(만약 둘다 아니라면 먼저 들어온 사람을 이기게 한다.) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from collections import deque
def game(person):
    round_ = 0
    while person:
        round_+=1
        next_person = deque()
        while person:
            if len(person)==1:
                next_person.append(person.pop())
            else:
                a, b = person.popleft(), person.popleft()
                if a == k:
                    if b==l:
                        return round_
                    else:
                        next_person.append(a)
                elif a == l:
                    if b==k:
                        return round_
                    else:
                        next_person.append(a)
                elif b==l:
                    if a==k:
                        return round_
                    else:
                        next_person.append(b)
                elif b==k:
                    if a==l:
                        return round_
                    else:
                        next_person.append(b)
                else:
                    next_person.append(a)
        person = next_person
    return 0
N, k, l = map(int,input().split())
person = deque(range(1,N+1))
answer = game(person)
if answer:
    print(answer)
else:
    print(-1)
cs

문제링크:

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

 

1057번: 토너먼트

김지민은 N명이 참가하는 스타 토너먼트에 진출했다. 토너먼트는 다음과 같이 진행된다. 일단 N명의 참가자는 번호가 1번부터 N번까지 배정받는다. 그러고 난 후에 서로 인접한 번호끼리 스타를

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1351. 무한 수열  (0) 2021.09.24
[BOJ]1202. 보석 도둑  (0) 2021.09.23
[BOJ] 14890. 경사로  (0) 2021.09.15
[BOJ]14719. 빗물  (0) 2021.09.14
[BOJ]2470. 두 용액  (0) 2021.09.13

문제:

크기가 N×N인 지도가 있다. 지도의 각 칸에는 그 곳의 높이가 적혀져 있다.

오늘은 이 지도에서 지나갈 수 있는 길이 몇 개 있는지 알아보려고 한다. 길이란 한 행 또는 한 열 전부를 나타내며, 한쪽 끝에서 다른쪽 끝까지 지나가는 것이다. 

다음과 같은 N=6인 경우 지도를 살펴보자.

이때, 길은 총 2N개가 있으며, 아래와 같다.

길을 지나갈 수 있으려면 길에 속한 모든 칸의 높이가 모두 같아야 한다. 또는, 경사로를 놓아서 지나갈 수 있는 길을 만들 수 있다. 경사로는 높이가 항상 1이며, 길이는 L이다. 또, 개수는 매우 많아 부족할 일이 없다. 경사로는 낮은 칸과 높은 칸을 연결하며, 아래와 같은 조건을 만족해야한다.

  • 경사로는 낮은 칸에 놓으며, L개의 연속된 칸에 경사로의 바닥이 모두 접해야 한다.
  • 낮은 칸과 높은 칸의 높이 차이는 1이어야 한다.
  • 경사로를 놓을 낮은 칸의 높이는 모두 같아야 하고, L개의 칸이 연속되어 있어야 한다.

아래와 같은 경우에는 경사로를 놓을 수 없다.

  • 경사로를 놓은 곳에 또 경사로를 놓는 경우
  • 낮은 칸과 높은 칸의 높이 차이가 1이 아닌 경우
  • 낮은 지점의 칸의 높이가 모두 같지 않거나, L개가 연속되지 않은 경우
  • 경사로를 놓다가 범위를 벗어나는 경우

L = 2인 경우에 경사로를 놓을 수 있는 경우를 그림으로 나타내면 아래와 같다.

경사로를 놓을 수 없는 경우는 아래와 같다.

위의 그림의 가장 왼쪽부터 1번, 2번, 3번, 4번 예제라고 했을 때, 1번은 높이 차이가 1이 아니라서, 2번은 경사로를 바닥과 접하게 놓지 않아서, 3번은 겹쳐서 놓아서, 4번은 기울이게 놓아서 불가능한 경우이다.

가장 위에 주어진 그림 예의 경우에 지나갈 수 있는 길은 파란색으로, 지나갈 수 없는 길은 빨간색으로 표시되어 있으며, 아래와 같다. 경사로의 길이 L = 2이다.

지도가 주어졌을 때, 지나갈 수 있는 길의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

출력:

첫째 줄에 지나갈 수 있는 길의 개수를 출력한다.

풀이방법:

check 함수를 사용해서 가로에 대해서 먼저 체크하고, 행과 열을 바꿔 세로에 대해서 체크하도록 한다.

check 함수 내에서는 현재값과 다음값의 높이 차이에 대해서 확인하고, 같다면 그대로 넘어간다. 만약 차이가 1보다 크다면 경사로를 놓을 수 없는 경우이기 때문에 0을 반환한다.

 만약 1 혹은 -1만큼의 차이가 나면 그 위치로부터 L의 경사로를 놓을 수 있는지 확인한다. 이 때 확인해야 하는 것은 낮은 지점의 높이가 L개 만큼 연속되는지, 이미 경사로가 놓아져 있는지 확인해야 한다. 이 과정이 모두 확인되면 visited배열에 경사로를 놓으며 넘어가고 그렇지 않다면 0을 반환하도록 한다. 이렇게 끝까지 탐색했는데 문제가 없는 경우라면 answer에 1을 더하도록 한다.

 모든 탐색을 마친 뒤에 answer 값을 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
N, L = map(int,input().split())
 
def check(map_):
    visited = [0]*N
    for i in range(N-1):
        if map_[i]==map_[i+1]:
            continue
        if abs(map_[i]-map_[i+1]) > 1:
            return 0
        if map_[i]-map_[i+1== 1:
            tmp = map_[i+1]
            for j in range(i+1,i+L+1):
                if 0<= j < N:
                    if map_[j]!=tmp:
                        return 0
                    if visited[j]:
                        return 0
                    visited[j] = 1
                else:
                    return 0
        else:
            tmp = map_[i]
            for j in range(i,i-L,-1):
                if 0<= j < N:
                    if map_[j]!=tmp:
                        return 0
                    if visited[j]:
                        return 0
                    visited[j] = 1
                else:
                    return 0
    return 1
        
maps = []
for _ in range(N):
    maps.append(list(map(int,input().split())))
    
answer = 0 
for map_ in maps:
    if check(map_):
        answer+=1
        
maps = list(map(list,zip(*maps)))
for map_ in maps:
    if check(map_):
        answer+=1
        
print(answer)
cs

문제링크:

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

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1202. 보석 도둑  (0) 2021.09.23
[BOJ]1057. 토너먼트  (0) 2021.09.16
[BOJ]14719. 빗물  (0) 2021.09.14
[BOJ]2470. 두 용액  (0) 2021.09.13
[BOJ]1655. 가운데를 말해요  (0) 2021.09.10

문제:

2차원 세계에 블록이 쌓여있다. 비가 오면 블록 사이에 빗물이 고인다.

비는 충분히 많이 온다. 고이는 빗물의 총량은 얼마일까?

입력:

첫 번째 줄에는 2차원 세계의 세로 길이 H과 2차원 세계의 가로 길이 W가 주어진다. (1 ≤ H, W ≤ 500)

두 번째 줄에는 블록이 쌓인 높이를 의미하는 0이상 H이하의 정수가 2차원 세계의 맨 왼쪽 위치부터 차례대로 W개 주어진다.

따라서 블록 내부의 빈 공간이 생길 수 없다. 또 2차원 세계의 바닥은 항상 막혀있다고 가정하여도 좋다.

출력:

2차원 세계에서는 한 칸의 용량은 1이다. 고이는 빗물의 총량을 출력하여라.

빗물이 전혀 고이지 않을 경우 0을 출력하여라.

풀이방법:

 양 끝점을 제외한 칸에서부터 왼쪽과 오른쪽을 각각 탐색해서 가장 낮은 위치를 찾아내고, 왼쪽의 가장 낮은 위치와 오른쪽의 가장 낮은 위치 더 낮은 값이 해당 칸에 빗물이 고인 수치다. 이 과정을 모든 칸에 진행하면서 값을 누적시키면 최종 답을 구할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
H, W = map(int,input().split())
block = list(map(int,input().split()))
 
answer = 0
for cur in range(1, W-1):
    left_block = block[cur]
    for i in range(cur-1,-1,-1):
        if left_block < block[i]:
            left_block = block[i]
    right_block = block[cur]
    for j in range(cur+1,W):
        if right_block < block[j]:
            right_block = block[j]
    min_block = min(left_block, right_block)
    answer += min_block-block[cur]
print(answer)
cs

문제링크:

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

 

14719번: 빗물

첫 번째 줄에는 2차원 세계의 세로 길이 H과 2차원 세계의 가로 길이 W가 주어진다. (1 ≤ H, W ≤ 500) 두 번째 줄에는 블록이 쌓인 높이를 의미하는 0이상 H이하의 정수가 2차원 세계의 맨 왼쪽 위치

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1057. 토너먼트  (0) 2021.09.16
[BOJ] 14890. 경사로  (0) 2021.09.15
[BOJ]2470. 두 용액  (0) 2021.09.13
[BOJ]1655. 가운데를 말해요  (0) 2021.09.10
[BOJ]2110. 공유기 설치  (0) 2021.09.09

문제:

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의 값은 4이다.

 

배열은 회전 연산을 수행할 수 있다. 회전 연산은 세 정수 (r, c, s)로 이루어져 있고, 가장 왼쪽 윗 칸이 (r-s, c-s), 가장 오른쪽 아랫 칸이 (r+s, c+s)인 정사각형을 시계 방향으로 한 칸씩 돌린다는 의미이다. 배열의 칸 (r, c)는 r행 c열을 의미한다.

예를 들어, 배열 A의 크기가 6×6이고, 회전 연산이 (3, 4, 2)인 경우에는 아래 그림과 같이 회전하게 된다.

회전 연산이 두 개 이상이면, 연산을 수행한 순서에 따라 최종 배열이 다르다.

다음은 배열 A의 크기가 5×6이고, 회전 연산이 (3, 4, 2), (4, 2, 1)인 경우의 예시이다.

배열 A에 (3, 4, 2), (4, 2, 1) 순서로 연산을 수행하면 배열 A의 값은 12, (4, 2, 1), (3, 4, 2) 순서로 연산을 수행하면 15 이다.

배열 A와 사용 가능한 회전 연산이 주어졌을 때, 배열 A의 값의 최솟값을 구해보자. 회전 연산은 모두 한 번씩 사용해야 하며, 순서는 임의로 정해도 된다.

입력:

첫째 줄에 배열 A의 크기 N, M, 회전 연산의 개수 K가 주어진다.

둘째 줄부터 N개의 줄에 배열 A에 들어있는 수 A[i][j]가 주어지고, 다음 K개의 줄에 회전 연산의 정보 r, c, s가 주어진다.

출력:

배열 A의 값의 최솟값을 출력한다.

제한:

  • 3 ≤ N, M ≤ 50
  • 1 ≤ K ≤ 6
  • 1 ≤ A[i][j] ≤ 100
  • 1 ≤ s
  • 1 ≤ r-s < r < r+s ≤ N
  • 1 ≤ c-s < c < c+s ≤ M

풀이방법:

 제시되어 있는 방법대로 구현을 하면 되는 문제다. 다만 회전을 하는 것을 한번 구현한 뒤, 점점 안으로 작게 회전을 해야하고, 모서리 부분을 신경쓰면서 구현을 진행해야 한다.

 점점 작아지는 것은 while과 s를 사용해서 구현할 수 있다. s에 의해서 꼭짓점들이 구해지기 때문에, s를 1씩 빼면서 while 반복문을 사용한다. 종료되는 조건은 가장 왼쪽 윗 칸과 가장 오른쪽 아랫 칸이 작아지는 시점이며, r+s==r-s인 경우다.

 permutation을 사용해서 모든 조건을 구한 뒤에 입력받은 A를 copy한 뒤에 회전 연산을 해서 원래 입력값을 보존하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from itertools import permutations
import copy
 
def rotate(coord):
    r, c, s = coord    
    while True:
        if r-s==r+s:
            break
        tmp = None
        for i in range(c-s,c+s+1):
            if tmp is None:
                tmp = A[r-s][i]
            else:
                A[r-s][i], tmp = tmp, A[r-s][i]
        for i in range(r-s+1,r+s+1):
            A[i][c+s], tmp = tmp, A[i][c+s]
        for i in range(c+s-1,c-s-1,-1):
            A[r+s][i], tmp = tmp, A[r+s][i]
        for i in range(r+s-1,r-s-1,-1):
            A[i][c-s], tmp = tmp, A[i][c-s]
        s-=1
    
N, M, K = map(int,input().split())
= []
for _ in range(N):
    A.append(list(map(int,input().split())))
    
commands = []
for _ in range(K):
    r, c, s = map(int,input().split())
    commands.append((r-1, c-1, s))
    
command_lists = list(permutations(commands,K))
answer = float('inf')
for command_list in command_lists:
    A_copy = copy.deepcopy(A)
    for c in command_list:
        rotate(c)
    for i in range(N):
        answer = min(sum(A[i]),answer)
    A = copy.deepcopy(A_copy)
print(answer)    
cs

문제링크:

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

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1655. 가운데를 말해요  (0) 2021.09.10
[BOJ]2110. 공유기 설치  (0) 2021.09.09
[BOJ]2638. 치즈  (0) 2021.09.06
[BOJ]2636. 치즈  (0) 2021.09.03
[BOJ] 11054. 가장 긴 바이토닉 부분 수열  (0) 2021.09.02

문제:

뿌요뿌요의 룰은 다음과 같다.

필드에 여러 가지 색깔의 뿌요를 놓는다. 뿌요는 중력의 영향을 받아 아래에 바닥이나 다른 뿌요가 나올 때까지 아래로 떨어진다.

뿌요를 놓고 난 후, 같은 색 뿌요가 4개 이상 상하좌우로 연결되어 있으면 연결된 같은 색 뿌요들이 한꺼번에 없어진다. 이때 1연쇄가 시작된다.

뿌요들이 없어지고 나서 위에 다른 뿌요들이 있다면, 역시 중력의 영향을 받아 차례대로 아래로 떨어지게 된다.

아래로 떨어지고 나서 다시 같은 색의 뿌요들이 4개 이상 모이게 되면 또 터지게 되는데, 터진 후 뿌요들이 내려오고 다시 터짐을 반복할 때마다 1연쇄씩 늘어난다.

터질 수 있는 뿌요가 여러 그룹이 있다면 동시에 터져야 하고 여러 그룹이 터지더라도 한번의 연쇄가 추가된다.

남규는 최근 뿌요뿌요 게임에 푹 빠졌다. 이 게임은 1:1로 붙는 대전게임이라 잘 쌓는 것도 중요하지만, 상대방이 터뜨린다면 연쇄가 몇 번이 될지 바로 파악할 수 있는 능력도 필요하다. 하지만 아직 실력이 부족하여 남규는 자기 필드에만 신경 쓰기 바쁘다. 상대방의 필드가 주어졌을 때, 연쇄가 몇 번 연속으로 일어날지 계산하여 남규를 도와주자!

입력:

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다.

이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다.

R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

입력으로 주어지는 필드는 뿌요들이 전부 아래로 떨어진 뒤의 상태이다. 즉, 뿌요 아래에 빈 칸이 있는 경우는 없다.

출력:

현재 주어진 상황에서 몇연쇄가 되는지 출력한다. 하나도 터지지 않는다면 0을 출력한다.

풀이방법:

 bfs를 사용하는 문제다. 그리고 뿌요는 중력의 영향을 받아 아래에 바닥이나 다른 뿌요가 나올 때까지 아래로 떨어지는 것을 쉽게 구현하기 위해 map과 zip을 사용해서 행과 열의 위치를 바꿔서 문제를 해결했다.

 빈공간이 아닌 뿌요를 만났을 때, bfs를 수행한다. 이 때 탐색한 횟수가 4가 넘으면 방문했던 곳들을 모두 fall_이라는 곳에 다시 저장해 없어질 대상임을 표시한다. 이렇게 모든 뿌요들을 모두 탐색한 뒤에 나중에 한번에 뿌요들을 지우고 떨어지는 행동을 수행하게 한다. 이 과정이 한번이라도 발생했다면 다시 한 번 bfs를 수행하고, 그렇지 않다면 답을 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
puyo = []
for _ in range(12):
    puyo.append(input())
    
puyo = list(map(list,zip(*puyo)))
puyo_copy = puyo.copy()
 
from collections import deque
dx = [0,1,0,-1]
dy = [1,0,-1,0]
def bfs(i,j):
    queue = deque([(i,j)])
    visited = [[0 for _ in range(12)] for _ in range(6)]
    visited[i][j] = 1
    cnt = 1
    while queue:
        x, y = queue.popleft()
        for k in range(4):
            nx = x + dx[k]
            ny = y + dy[k]
            if 0<= nx < 6 and 0<= ny < 12 and not visited[nx][ny]:
                if puyo_copy[i][j]==puyo_copy[nx][ny]:
                    visited[nx][ny] = 1
                    queue.append((nx,ny))
                    cnt+=1
    if cnt>=4:
        for i in range(6):
            for j in range(12):
                if visited[i][j]:
                    fall_[i][j]=1
        return 1
    else:
        return 0
 
def falling():
    for i,f in enumerate(fall_):
        empty = ['.']*f.count(1)
        puyo_copy[i] = empty + [p for j,p in enumerate(puyo_copy[i]) if not f[j]]
        
time =0
while  True:
    flag=0
    fall_ = [[0 for _ in range(12)] for _ in range(6)]
    for i in range(6):
        for j in range(12):
            if puyo_copy[i][j]!='.':
                flag += bfs(i,j)
    if flag:
        time+=1
    else:
        break
    falling()
    
print(time)
cs

문제링크:

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

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

 

'Algorithm' 카테고리의 다른 글

[BOJ]13913. 숨바꼭질 4  (0) 2022.08.11
[BOJ]3190. 뱀  (0) 2021.08.19
[BOJ]1520. 내리막길  (0) 2021.08.17
[BOJ]1987. 알파벳  (0) 2021.08.10
[BOJ]14425. 문자열 집합  (0) 2021.06.24

문제:

N×M (5≤N, M≤100)의 모눈종이 위에 아주 얇은 치즈가 <그림 1>과 같이 표시되어 있다. 단, N 은 세로 격자의 수이고, M 은 가로 격자의 수이다. 이 치즈는 냉동 보관을 해야만 하는데 실내온도에 내어놓으면 공기와 접촉하여 천천히 녹는다. 그런데 이러한 모눈종이 모양의 치즈에서 각 치즈 격자(작 은 정사각형 모양)의 4변 중에서 적어도 2변 이상이 실내온도의 공기와 접촉한 것은 정확히 한시간만에 녹아 없어져 버린다. 따라서 아래 <그림 1> 모양과 같은 치즈(회색으로 표시된 부분)라면 C로 표시된 모든 치즈 격자는 한 시간 후에 사라진다.

<그림 2>와 같이 치즈 내부에 있는 공간은 치즈 외부 공기와 접촉하지 않는 것으로 가정한다. 그러므 로 이 공간에 접촉한 치즈 격자는 녹지 않고 C로 표시된 치즈 격자만 사라진다. 그러나 한 시간 후, 이 공간으로 외부공기가 유입되면 <그림 3>에서와 같이 C로 표시된 치즈 격자들이 사라지게 된다.

모눈종이의 맨 가장자리에는 치즈가 놓이지 않는 것으로 가정한다. 입력으로 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로 표시된다. 또한, 각 0과 1은 하나의 공백으로 분리되어 있다.

출력:

출력으로는 주어진 치즈가 모두 녹아 없어지는데 걸리는 정확한 시간을 정수로 첫 줄에 출력한다.

풀이방법:

https://codedrive.tistory.com/470

2636. 치즈 문제에서 조건이 하나 더 추가된 문제다. 2636 문제에 delete 배열을 이용해서 접한 횟수를 추가적으로 세서, 2 이상인 경우에만 치즈가 녹게 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from collections import deque
 
dx = [0,1,0,-1]
dy = [1,0,-1,0]
 
def bfs(i,j):
    queue = deque([(i,j)])
    visited = [[0 for _ in range(M)] for _ in range(N)]
    visited[i][j] = -1
    exist = False
    while queue:
        x,y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<= nx < N and 0<= ny < M and not visited[nx][ny]:
                if cheese[nx][ny]:
                    delete[nx][ny]+=1
                    exist = True
                else:
                    visited[nx][ny] = -1
                    queue.append((nx,ny))
    for i in range(N):
        for j in range(M):
            if delete[i][j] >= 2:
                cheese[i][j] = 0
    return exist
 
N, M = map(int,input().split())
cheese = []
for _ in range(N):
    cheese.append(list(map(int,input().split())))
    
time = 0
while True:
    delete = [[0 for _ in range(M)] for _ in range(N)]
    conti = bfs(0,0)
    if conti:
        time+=1
    else:
        break
print(time)
cs

문제링크:

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

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2110. 공유기 설치  (0) 2021.09.09
[BOJ]17406. 배열 돌리기 4  (0) 2021.09.08
[BOJ]2636. 치즈  (0) 2021.09.03
[BOJ] 11054. 가장 긴 바이토닉 부분 수열  (0) 2021.09.02
[BOJ]2565. 전깃줄  (0) 2021.09.01

문제:

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓여 있지 않으며 치즈에는 하나 이상의 구멍이 있을 수 있다.

이 치즈를 공기 중에 놓으면 녹게 되는데 공기와 접촉된 칸은 한 시간이 지나면 녹아 없어진다. 치즈의 구멍 속에는 공기가 없지만 구멍을 둘러싼 치즈가 녹아서 구멍이 열리면 구멍 속으로 공기가 들어가게 된다. <그림 1>의 경우, 치즈의 구멍을 둘러싼 치즈는 녹지 않고 ‘c’로 표시된 부분만 한 시간 후에 녹아 없어져서 <그림 2>와 같이 된다.

다시 한 시간 후에는 <그림 2>에서 ‘c’로 표시된 부분이 녹아 없어져서 <그림 3>과 같이 된다.

<그림 3>은 원래 치즈의 두 시간 후 모양을 나타내고 있으며, 남은 조각들은 한 시간이 더 지나면 모두 녹아 없어진다. 그러므로 처음 치즈가 모두 녹아 없어지는 데는 세 시간이 걸린다. <그림 3>과 같이 치즈가 녹는 과정에서 여러 조각으로 나누어 질 수도 있다.

입력으로 사각형 모양의 판의 크기와 한 조각의 치즈가 판 위에 주어졌을 때, 공기 중에서 치즈가 모두 녹아 없어지는 데 걸리는 시간과 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 치즈가 없는 칸은 0, 치즈가 있는 칸은 1로 주어지며 각 숫자 사이에는 빈칸이 하나씩 있다.

출력:

첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력한다.

풀이방법:

 일반적인 bfs와 다르게 이 치즈 문제에서는 '치즈 안에 빈 공간이 있는 경우에는 녹지 않는다' 라는 조건이 있기 때문에, 이를 신경써야 한다. 따라서 치즈를 기준으로 bfs를 하는 것이 아니라 공기를 기준으로 bfs를 수행하며 치즈를 만난 경우에 탐색을 종료하고 기록하는 방식으로 한다.

 0,0은 항상 공기이기 때문에(판의 가장자리) 이 점으로부터 시작해서 bfs를 수행하고, 모든 탐색을 마친 뒤에 한 번에 치즈를 녹이도록 한다. 이를 치즈가 모두 녹을 때까지 반복한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from collections import deque
import sys
 
#input = sys.stdin.readline
 
dx = [0,1,0,-1]
dy = [1,0,-1,0]
 
def bfs(count):
    while queue:
        x,y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            
            if 0<= nx < N and 0<= ny < M and not visited[nx][ny]:
                visited[nx][ny] = 1
                if cheese[nx][ny]==1:
                    cheese[nx][ny] = -1
                    count-=1
                else:
                    queue.append((nx,ny))
    return count
 
def melt():
    for i in range(N):
        for j in range(M):
            if cheese[i][j] == -1:
                cheese[i][j] = 0
 
N,M = map(int,input().split())
cheese = []
count = 0
for _ in range(N):
    sub_cheese = list(map(int,input().split()))
    count += sum(sub_cheese)
    cheese.append(sub_cheese)
    
time = 0
answer = count
queue = deque()
while count:
    visited = [[0 for _ in range(M)] for _ in range(N)]
    queue.append((0,0))
    visited[0][0= 1
    count = bfs(count)
    
    if count:
        answer = count
        
    time+=1
    melt()
    
print(time)
print(answer)
cs

문제링크:

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

 

2636번: 치즈

첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]17406. 배열 돌리기 4  (0) 2021.09.08
[BOJ]2638. 치즈  (0) 2021.09.06
[BOJ] 11054. 가장 긴 바이토닉 부분 수열  (0) 2021.09.02
[BOJ]2565. 전깃줄  (0) 2021.09.01
[BOJ]2042. 구간 합 구하기  (0) 2021.08.31

문제:

지구 온난화로 인하여 북극의 빙산이 녹고 있다. 빙산을 그림 1과 같이 2차원 배열에 표시한다고 하자. 빙산의 각 부분별 높이 정보는 배열의 각 칸에 양의 정수로 저장된다. 빙산 이외의 바다에 해당되는 칸에는 0이 저장된다. 그림 1에서 빈칸은 모두 0으로 채워져 있다고 생각한다.

그림 1. 행의 개수가 5이고 열의 개수가 7인 2차원 배열에 저장된 빙산의 높이 정보

빙산의 높이는 바닷물에 많이 접해있는 부분에서 더 빨리 줄어들기 때문에, 배열에서 빙산의 각 부분에 해당되는 칸에 있는 높이는 일년마다 그 칸에 동서남북 네 방향으로 붙어있는 0이 저장된 칸의 개수만큼 줄어든다. 단, 각 칸에 저장된 높이는 0보다 더 줄어들지 않는다. 바닷물은 호수처럼 빙산에 둘러싸여 있을 수도 있다. 따라서 그림 1의 빙산은 일년후에 그림 2와 같이 변형된다.

그림 3은 그림 1의 빙산이 2년 후에 변한 모습을 보여준다. 2차원 배열에서 동서남북 방향으로 붙어있는 칸들은 서로 연결되어 있다고 말한다. 따라서 그림 2의 빙산은 한 덩어리이지만, 그림 3의 빙산은 세 덩어리로 분리되어 있다.

한 덩어리의 빙산이 주어질 때, 이 빙산이 두 덩어리 이상으로 분리되는 최초의 시간(년)을 구하는 프로그램을 작성하시오. 그림 1의 빙산에 대해서는 2가 답이다. 만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다.

입력:

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 나타내는 M개의 정수가 한 개의 빈 칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0 이상 10 이하이다. 배열에서 빙산이 차지하는 칸의 개수, 즉, 1 이상의 정수가 들어가는 칸의 개수는 10,000 개 이하이다. 배열의 첫 번째 행과 열, 마지막 행과 열에는 항상 0으로 채워진다.

출력:

첫 줄에 빙산이 분리되는 최초의 시간(년)을 출력한다. 만일 빙산이 다 녹을 때까지 분리되지 않으면 0을 출력한다.

풀이방법:

bfs를 사용해서 빙산을 녹이면서 덩어리가 2개가 되는 순간 그 때의 year 값을 출력하면 된다. 처음 가정으로는 한 덩어리의 빙산이기 때문에 빙산을 발견하면 그 점으로부터 bfs를 수행하면 된다. 빙산으로부터 4방향을 보고 나중에 한 번에 녹여야 하기 때문에 바로 녹이지 않고, 나중에 한 번에 녹이도록 한다.

만약 bfs를 두 번 탐색하는 경우에는 2개의 빙산이 있는 경우이기 때문에 더이상 진행하지 않도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from collections import deque
import sys
 
#input = sys.stdin.readline
 
dx = [0,1,0,-1]
dy = [1,0,-1,0]
 
def check():
    visited = [[0 for _ in range(M)] for _ in range(N)]
    group_cnt = 0
    melting_queue = []
    for i in range(1,N-1):
        for j in range(1,M-1):
            if ice_mountain[i][j] and not visited[i][j]:
                group_cnt+=1
                d = deque([(i,j)])
                visited[i][j] = 1
                while d:
                    x,y = d.popleft()
                    melt_cnt = 0
                    for k in range(4):
                        nx = x + dx[k]
                        ny = y + dy[k]
                        if 0<= nx < N and 0 <=ny < M and not visited[nx][ny]:
                            if ice_mountain[nx][ny]:
                                d.append((nx,ny))
                                visited[nx][ny] = 1
                            else:
                                melt_cnt +=1
                    if melt_cnt:
                        melting_queue.append(((x,y),melt_cnt))
                        
    return melting_queue,group_cnt
                    
 
N,M = map(int,input().split())
ice_mountain = []
for i in range(N):
    ice_mountain.append(list(map(int,input().split())))
    
year = 0
while True:
    melting_queue, cnt = check()
    if not cnt:
        year = 0
        break
    elif cnt >= 2:
        break
    for i,dc in melting_queue:
        x,y = i
        ice_mountain[x][y] = max(ice_mountain[x][y]-dc,0)
    year+=1
print(year)
cs

문제링크:

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

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]2565. 전깃줄  (0) 2021.09.01
[BOJ]2042. 구간 합 구하기  (0) 2021.08.31
[BOJ]10942. 팰린드롬?  (0) 2021.08.26
[BOJ]1963. 소수경로  (0) 2021.08.24
[BOJ]1074. Z  (0) 2021.08.12

문제:

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.

게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다.

뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.

  • 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
  • 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
  • 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.

사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하라.

입력:

첫째 줄에 보드의 크기 N이 주어진다. (2 ≤ N ≤ 100) 다음 줄에 사과의 개수 K가 주어진다. (0 ≤ K ≤ 100)

다음 K개의 줄에는 사과의 위치가 주어지는데, 첫 번째 정수는 행, 두 번째 정수는 열 위치를 의미한다. 사과의 위치는 모두 다르며, 맨 위 맨 좌측 (1행 1열) 에는 사과가 없다.

다음 줄에는 뱀의 방향 변환 횟수 L 이 주어진다. (1 ≤ L ≤ 100)

다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데,  정수 X와 문자 C로 이루어져 있으며. 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다. X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순으로 주어진다.

출력:

첫째 줄에 게임이 몇 초에 끝나는지 출력한다.

풀이방법:

 일반적인 움직임 대신에 여러 제약 조건이 있는 문제다. 움직이는 방향과 같은 경우에는 일반적으로 상하좌우 모두 탐색하는 것이 아닌 지정된 방향만으로 이동을 하며, 지정된 시간에만 회전을 하도록 한다. 회전에 대한 정보는 key가 time인 dict 형태로 저장해서 지정된 시간이 되면 rotate 함수를 통해 해당 방향으로 회전하도록 한다.

 움직이는 방법과 같은 경우에는 사과를 만날 경우에는 방문 표시(-1, 몸통을 의미)만 하면서 이동하며, 만약 사과가 아닌 경우에만 덱에서만 빼주며 자리를 0으로 비워준다.

 그리고 몸이나 벽을 만날 경우에는 바로 종료하게 해서 그 때의 시간을 출력하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from collections import deque
 
dx = [-1,0,1,0]
dy = [0,1,0,-1]
 
def rotate(now,D):
    return (now - 1) % 4 if D=="L" else (now + 1) % 4
 
def dummy():
    direction = 1
    time = 1
    d = deque([(0,0)])
    x,y = 0,0
    apples[x][y] = -1
    while True:
        x, y = x + dx[direction], y + dy[direction]
        if 0<= x < N and 0<= y < N and apples[x][y] !=-1:
            if not apples[x][y]:
                tx, ty = d.popleft()
                apples[tx][ty] = 0
            apples[x][y] = -1
            d.append((x,y))
            if infos.get(time):
                direction = rotate(direction,infos.get(time))
            time+=1
        else:
            break
    return time
    
= int(input())
= int(input())
apples = [[0 for _ in range(N)] for _  in range(N)]
for _ in range(K):
    x,y = map(int,input().split())
    apples[x-1][y-1= 1
 
= int(input())
infos = {}
for _ in range(L):
    t, d = input().split()
    infos[int(t)] = d
 
print(dummy())
cs

문제링크:

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

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

 

'Algorithm' 카테고리의 다른 글

[BOJ]13913. 숨바꼭질 4  (0) 2022.08.11
[BOJ]11559. Puyo Puyo  (0) 2021.09.07
[BOJ]1520. 내리막길  (0) 2021.08.17
[BOJ]1987. 알파벳  (0) 2021.08.10
[BOJ]14425. 문자열 집합  (0) 2021.06.24

문제:

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다.

오늘부터 인구 이동이 시작되는 날이다.

인구 이동은 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다.

  • 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면, 두 나라가 공유하는 국경선을 오늘 하루동안 연다.
  • 위의 조건에 의해 열어야하는 국경선이 모두 열렸다면, 인구 이동을 시작한다.
  • 국경선이 열려있어 인접한 칸만을 이용해 이동할 수 있으면, 그 나라를 오늘 하루 동안은 연합이라고 한다.
  • 연합을 이루고 있는 각 칸의 인구수는 (연합의 인구수) / (연합을 이루고 있는 칸의 개수)가 된다. 편의상 소수점은 버린다.
  • 연합을 해체하고, 모든 국경선을 닫는다.

각 나라의 인구수가 주어졌을 때, 인구 이동이 몇 번 발생하는지 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N, L, R이 주어진다. (1 ≤ N ≤ 50, 1 ≤ L ≤ R ≤ 100)

둘째 줄부터 N개의 줄에 각 나라의 인구수가 주어진다. r행 c열에 주어지는 정수는 A[r][c]의 값이다. (0 ≤ A[r][c] ≤ 100)

인구 이동이 발생하는 횟수가 2,000번 보다 작거나 같은 입력만 주어진다.

출력:

인구 이동이 몇 번 발생하는지 첫째 줄에 출력한다.

풀이방법:

**이 문제는 pypy3으로 통과했습니다.**

 이 문제는 for(bfs)라고 생각했다. 우선 bfs를 사용한 이유는 한 나라로부터 인접한 국가들을 찾는 방법은 bfs가 가장 적당하다고 생각했기 때문이다. 하지만 이러한 bfs를 NxN 크기의 땅에 모두에 대해서 수행해야 했기 때문에 for(bfs)라고 생각했다. 그리고 이러한 문제때문에 시간초과가 발생할 수 있을 것 같다는 걱정이 들었는데, 실제로 python3으로는 시간초과가 발생하여서 pypy3으로 이 문제를 해결하였다.

 bfs를 통해서 국경이 열리는 나라들을 찾으며 인구 수를 더하며 count를 센다. 한 번의 bfs 탐색이 끝나게 되면, 업데이트를 하는 과정을 거치고, 다시 이어서 bfs를 수행하도록 한다. 

 이러한 과정을 인구 이동이 발생하지 않을 때까지 반복한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
dx = [-1001]
dy = [0-110]
def move(countrys,openB):
    change = False
    for i in range(N):
        for j in range(N):
            if openB[i][j] == 0:
                sum_ = countrys[i][j]
                queue = [(i,j)]
                total_queue = [(i,j)]
                openB[i][j]=1
                while len(queue):
                    tmp = []
                    for q in queue:
                        x,y = q
                        for idx in range(4):
                            nx = dx[idx] + x
                            ny = dy[idx] + y
                            if 0<= nx < N and 0 <= ny < N and openB[nx][ny]==0:
                                if L<= abs(countrys[nx][ny] - countrys[x][y]) <=R:
                                    tmp.append((nx,ny))
                                    sum_ += countrys[nx][ny]
                                    openB[nx][ny] = 1
                    total_queue.extend(tmp)
                    queue = tmp
                if len(total_queue) > 1:
                    change = True
                    avg = sum_//len(total_queue)
                    for x,y in total_queue:
                        countrys[x][y] = avg
    return change, countrys
 
N, L, R = map(int,input().split())
countrys = []
for _ in range(N):
    countrys.append(list(map(int,input().split())))
    
 
answer = 0
while True:
    openB = [[0 for _ in range(N)] for _ in range(N)]
    conti,countrys= move(countrys,openB)
    if conti:
        answer +=1
    else:
        break
print(answer)
cs

문제링크:

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]5557. 1학년  (0) 2021.07.13
[BOJ]10973. 이전 순열  (0) 2021.07.08
[BOJ]14891. 톱니바퀴  (0) 2021.07.01
[BOJ]11725. 트리의 부모 찾기  (0) 2021.06.29
[BOJ]14725. 개미굴  (0) 2021.06.22

+ Recent posts