문제:

 재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 안전한 영역이 최대로 몇 개가 만들어 지는 지를 조사하려고 한다. 이때, 문제를 간단하게 하기 위하여, 장마철에 내리는 비의 양에 따라 일정한 높이 이하의 모든 지점은 물에 잠긴다고 가정한다.

 

 어떤 지역의 높이 정보는 행과 열의 크기가 각각 N인 2차원 배열 형태로 주어지며 배열의 각 원소는 해당 지점의 높이를 표시하는 자연수이다. 예를 들어, 다음은 N=5인 지역의 높이 정보이다.

이제 위와 같은 지역에 많은 비가 내려서 높이가 4 이하인 모든 지점이 물에 잠겼다고 하자. 이 경우에 물에 잠기는 지점을 회색으로 표시하면 다음과 같다.

물에 잠기지 않는 안전한 영역이라 함은 물에 잠기지 않는 지점들이 위, 아래, 오른쪽 혹은 왼쪽으로 인접해 있으며 그 크기가 최대인 영역을 말한다. 위의 경우에서 물에 잠기지 않는 안전한 영역은 5개가 된다.(꼭짓점으로만 붙어 있는 두 지점은 인접하지 않는다고 취급한다.)

 

또한 위와 같은 지역에서 높이가 6이하인 지점을 모두 잠기게 만드는 많은 비가 내리면 물에 잠기지 않는 안전한 영역은 아래 그림에서와 같이 네 개가 됨을 확인할 수 있다.

이와 같이 장마철에 내리는 비의 양에 따라서 물에 잠기지 않는 안전한 영역의 개수는 다르게 된다. 위의 예와 같은 지역에서 내리는 비의 양에 따른 모든 경우를 다 조사해 보면 물에 잠기지 않는 안전한 영역의 개수 중에서 최대인 경우는 5임을 알 수 있다.

어떤 지역의 높이 정보가 주어졌을 때, 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 계산하는 프로그램을 작성하시오.

입력:

첫째 줄에는 어떤 지역을 나타내는 2차원 배열의 행과 열의 개수를 나타내는 수 N이 입력된다. N은 2 이상 100 이하의 정수이다. 둘째 줄부터 N개의 각 줄에는 2차원 배열의 첫 번째 행부터 N번째 행까지 순서대로 한 행씩 높이 정보가 입력된다. 각 줄에는 각 행의 첫 번째 열부터 N번째 열까지 N개의 높이 정보를 나타내는 자연수가 빈 칸을 사이에 두고 입력된다. 높이는 1 이상 100 이하의 정수이다.

출력:

첫째 줄에 장마철에 물에 잠기지 않는 안전한 영역의 최대 개수를 출력한다.

풀이방법:

 bfs를 사용해서 풀수는 있을 것 같지만 dfs를 사용해서 풀었다. 재귀의 깊이가 얼마나 될지 모르고, deepcopy를 사용하기 위해서 sys와 copy를 import 했다.


 지역의 높이 정보 입력값을 받으면서 max 연산을 취해서 지역 내에 가장 높은 영역이 값을 얻도록 했다. (뒤에서 for 반복문에서 사용하기 위해) 입력을 다 받은 뒤에는 이 높이 정보를 deepcopy한 뒤 현재 rain에 맞게(1부터 시작한다.) 값을 빼주고 만약 0 이하로 떨어지게 된다면 0으로 만들고 나머지는 그대로 냅뒀다.

 

 이제 이렇게 비에 잠긴 영역들을 표시했으니 dfs를 사용해서 살아있는 영역의 개수를 구한다. 각 점을 탐색하며 0이 아닌 곳에서 dfs 탐색을 시작하며 탐색 되는 곳은 0으로 만들어줘서 방문했음을 알려준다. 이렇게 반복해서 하면 영역의 개수를 구할 수 있고 max 연산을 통해 최댓값을 구한다.

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
import sys
import copy
 
sys.setrecursionlimit(1000000)
 
n=int(input())
region=[]
dx=[0,0,-1,1]
dy=[1,-1,0,0]
 
maxH=0
answer=1
 
def dfs(x,y,visited):
    visited[x][y]=0
    for i in range(4):
        nx = x +dx[i]
        ny = y +dy[i]
        if (0 <= nx < n) and (0 <= ny < n):
            if visited[nx][ny] != 0:
                dfs(nx,ny,visited)
 
for _ in range(n):
    temp = list(map(int,input().split()))
    if maxH < max(temp):
        maxH = max(temp)
    region.append(temp)
    
for h in range(1,maxH+1):
    visited=copy.deepcopy(region)
    for i in range(n):
        for j in range(n):
            if visited[i][j] <= h:
                visited[i][j] = 0
    count = 0
    for x in range(n):
        for y in range(n):
            if visited[x][y] !=0:
                dfs (x,y,visited)
                count+=1
    answer = max(answer,count)
 
print(answer)
cs

 

문제링크:

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

 

2468번: 안전 영역

재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는 �

www.acmicpc.net

 

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

[Programmers]2018 Kakao[1차]추석 트래픽  (0) 2020.05.26
[Programmers]2019 Kakao 불량 사용자  (0) 2020.05.21
[BOJ]2167. 2차원 배열의 합  (0) 2020.05.14
[BOJ]1350. 진짜 공간  (0) 2020.05.12
[BOJ]5014. 스타트링크  (0) 2020.05.07

문제:

강호는 코딩 교육을 하는 스타트업 스타트링크에 지원했다. 오늘은 강호의 면접날이다. 하지만, 늦잠을 잔 강호는 스타트링크가 있는 건물에 늦게 도착하고 말았다.

 

스타트링크는 총 F층으로 이루어진 고층 건물에 사무실이 있고, 스타트링크가 있는 곳의 위치는 G층이다. 강호가 지금 있는 곳은 S층이고, 이제 엘리베이터를 타고 G층으로 이동하려고 한다.

 

보통 엘리베이터에는 어떤 층으로 이동할 수 있는 버튼이 있지만, 강호가 탄 엘리베이터는 버튼이 2개밖에 없다. U버튼은 위로 U층을 가는 버튼, D버튼은 아래로 D층을 가는 버튼이다.(만약, U층 위, 또는 D층 아래에 해당하는 층이 없을 때는, 엘리베이터는 움직이지 않는다)

 

강호가 G층에 도착하려면, 버튼을 적어도 몇 번 눌러야 하는지 구하는 프로그램을 작성하시오. 만약, 엘리베이터를 이용해서 G층에 갈 수 없다면, "use the stairs"를 출력한다.

입력:

첫째 줄에 F, S, G, U, D가 주어진다. (1<=S,G<=F<=1000000, 0<=U,D<=1000000) 건물은 1층부터 시작하고, 가장 높은 층은 F층이다.

출력:

첫째 줄에 강호가 S층에서 G층으로 가기 위해 눌러야 하는 버튼의 수의 최솟값을 출력한다. 만약, 엘리베티어로 이동할 수 없을 때는 "use the stairs"를 출력한다.

풀이방법:

 BFS로 경우의 수를 카운팅하면서 최소의 값을 찾을 수 있다. 우선 S와 G가 같으면 버튼을 누를 필요가 없기 때문에 0으로 답을 출력하도록 했다. 이제 이외의 경우에 대해서 BFS를 사용하기 위해, 초기 시작 층인 S로 state를 초기화 했고, 중복방문을 제거하기 위해서 visited를 초기화 했다.

 이제 갈 수 없는 경우( 0층, F층 초과)만 있을 때까지 계속 반복하기 위해서 while을 len(state) 초기화 했고, 현재 층을 s라고 할 때 다음과 같은 경우에만 이동하도록 한다.

 

1. s+U가 F층 이하이고, 방문하지 않은 곳이라면

2. s-F가 1층 이상이고, 방문하지 않은 곳이라면

 

이를 반복하면서 G가 나타나거나, 1,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
F,S,G,U,D=map(int,input().split())
 
if S==G:
    state=[]
    correct=True
else:
    state=[S]
    visited=[0]*(F+1)
    visited[S]=1
    correct=False
answer=0
while len(state):
    temp=[]
    for s in state:
        if s+<= F and visited[s+U]==0:
            temp.append(s+U)
            visited[s+U]=1
        if s-> 0 and visited[s-D]==0:
            temp.append(s-D)
            visited[s-D]=1
    answer+=1
    if G in temp:
        correct=True
        state=[]
    else:
        state=temp
 
if correct:
    print(answer)
else:
    print("use the stairs")
            
cs

문제링크:

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

 

5014번: 스타트링크

문제 강호는 코딩 교육을 하는 스타트업 스타트링크에 지원했다. 오늘은 강호의 면접날이다. 하지만, 늦잠을 잔 강호는 스타트링크가 있는 건물에 늦게 도착하고 말았다. 스타트링크는 총 F층으로 이루어진 고층 건물에 사무실이 있고, 스타트링크가 있는 곳의 위치는 G층이다. 강호가 지금 있는 곳은 S층이고, 이제 엘리베이터를 타고 G층으로 이동하려고 한다. 보통 엘리베이터에는 어떤 층으로 이동할 수 있는 버튼이 있지만, 강호가 탄 엘리베이터는 버튼이 2개밖에 없

www.acmicpc.net

 

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

[BOJ]2167. 2차원 배열의 합  (0) 2020.05.14
[BOJ]1350. 진짜 공간  (0) 2020.05.12
[2019 Kakao winter internship]튜플  (0) 2020.04.23
[2019 Kakao winter internship]크레인 인형뽑기 게임  (0) 2020.04.21
[BOJ]2863. 이게 분수?  (0) 2020.04.16

문제:

우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.

 

여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.

입력:

사람들은 1, 2, 3, ..., n (1<=n<=100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘때 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다.

 

각 사람의 부모는 최대 한 명만 주어진다.

출력:

입력에서 요구한 두 사람의 촌수를 나타내는 정수를 출력한다. 어떤 경우에는 두 사람의 친척 관계가 전혀 없어 촌수를 계산할 수 없을 때가 있다. 이 때에는 -1을 출력해야 한다.

풀이방법:

두 사람이 얼마나 긴 간격으로 연결되어 있는지 확인하는 문제이기 때문에 dfs나 bfs로 풀어야 할 것 같다고 생각했다. dfs로도 풀 수 있는지 정확히 모르지만, 두 사람 사이의 몇 level(단계)가 있는지 확인하면 되는 문제 이므로 bfs를 사용하기로 했다.

형제들 같은 경우에는 2촌으로 계산되는데 그 이유가 (나에서 부모님으로 1촌) + (부모님에서 형제로 1촌) 이기 때문이다. 따라서 이러한 관계를 알기 위해서는 양방향으로 이동할 수 있도록 relation을 만들었고, 중복방문을 하지 않기 위해서 visited를 만들었다.

처음 시작해야 하는 사람의 번호로 시작한다. 그리고 그 사람과 관계가 있는 사람들 중 방문하지 않았던 사람만 temp라는 배열에 담고 방문한 것으로 visited를 변경한다. 그리고 이 temp에 나와의 관계가 알고 싶은 사람의 번호가 있는지 확인하고, 있다면 break 없다면 temp의 길이를 재서 탐색할 사람이 있는지 확인한다. temp에 더 탐색할 사람이 있다면 위의 행동을 다시 반복하고, 더 이상 탐색할 사람이 없다면 친척 관계가 전혀 없다는 것으로 출력하면 된다.

그리고 최종 출력에서 +1을 했는데, 이 이유는 temp에 내가 원하는 사람의 번호가 있기 때문에 그 관계로 이동한다는 행동이 빠져있었기 때문에 +1을 해서 출력하도록 했다.

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
N=int(input())
a,b=map(int,input().split())
m=int(input())
 
relation = [[]for _ in range(N+1)]
visited = [0 for _ in range(N+1)]
 
for _ in range(m):
    c,d = map(int,input().split())
    relation[c].append(d)
    relation[d].append(c)
    
answer = 0
re=relation[a]
while True:
    temp=[]
    for i in re:
        for j in relation[i]:
            if visited[j]==0:
                visited[j]=1
                temp.append(j)
    answer+=1
    if b in temp:
        find=True
        break
    if len(temp)==0:
        find=False
        break
    re = temp
if find:
    print(answer+1)
else:
    print(-1)
cs

문제링크:

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

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1≤n≤100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다. 각 사람의 부모는 최대

www.acmicpc.net

 

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

[BOJ]1302 베스트셀러  (0) 2020.04.07
[BOJ]1051. 숫자 정사각형  (0) 2020.03.26
[BOJ]2352. 반도체 설계  (0) 2020.03.19
[BOJ]1748. 수 이어 쓰기 1  (0) 2020.03.17
[BOJ]1267. 핸드폰 요금  (0) 2020.03.12

문제:

해커 김지민은 잘 알려진 어느 회사를 해킹하려고 한다. 이 회사는 N개의 컴퓨터로 이루어져 있다. 김지민은 귀찮기 때문에, 한 번의 해킹으로 여러 개의 컴퓨터를 해킹 할 수 있는 컴퓨터를 해킹하려고 한다.

이 회사의 컴퓨터는 신뢰하는 관계와, 신뢰하지 않는 관계로 이루어져 있는데, A가 B를 신뢰하는 경우에는 B를 해킹하면, A도 해킹할 수 있다는 소리다.

이 회사의 컴퓨터의 신뢰하는 관계가 주어졌을 때, 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에, N과 M이 들어온다. N은 10,000보다 작거나 같은 자연수, M은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에 신뢰하는 관계까 A B와 같은 형식으로 들어오며, "A가 B를 신뢰한다."를 의미한다. 컴퓨터는 1번부터 N번까지 번호가 하나씩 매겨져 있다.

출력:

첫째 줄에, 김지민이 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 오름차순으로 출력한다.

풀이방법:

bfs를 사용해서 이 문제를 풀었다. 이 문제에서는 신뢰 관계가 양방향으로 존재한다는 가정이 없기 때문에 신뢰 관계를 정리 할 때, 단방향으로만 해야 한다. 일반적인 리스트를 사용해도 상관이 없지만 python의 시간 초과를 해결하기 위해 deque를 사용하고자 하였다. 하지만 그래도 python으로는 시간초과가 발생하였고,(한 명도 python으로 통과한 사람이 아직 없다.)그래서 결국 pypy3으로 통과했다.

 그 외의 특이사항으로는 방문했는지 확인하는 배열인 conti가 존재한다는 것이다. 아직 방문하지 않는 컴퓨터일 때에만 값을 갱신하며 count가 증가하도록 했다.

 

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
import sys
from collections import deque
n,m=map(int,sys.stdin.readline().split())
computers=[[]for i in range(n+1)]
for _ in range(m):
    a,b=map(int,sys.stdin.readline().split())
    computers[b].append(a)
counts=[0]*(n+1)
maxC=0
for i in range(1,n+1):
    count=1
    q = deque()
    q.append(i)
    conti=[0]*(n+1)
    conti[i]=1
    while q:
        j=q.popleft()
        for k in computers[j]:
            if conti[k]==0:
                count+=1
                q.append(k)
                conti[k]=1
    if count > maxC:
        maxC=count
    counts[i]=count
for i,e in enumerate(counts):
    if e==maxC:
        print(i,end=' ')
cs

 

문제링크:

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

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

[BOJ]1495. 기타리스트  (0) 2019.11.05
[BOJ]14848. 정수 게임  (0) 2019.11.04
[BOJ]7569. 토마토  (0) 2019.10.30
[BOJ]7576. 토마토  (0) 2019.10.29
[BOJ]1049. 기타줄  (0) 2019.10.18

문제:

2019/10/29 - [Algorithm/Python] - [BOJ]7576. 토마토

 

 위 문제에서 더 발전한 문제로 이제 한 층이 아닌 여러 층에 대해서 토마토가 익는 것이 전이된다.

입력:

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2<=M<=100,2<=N<=100,1<=H<=100이다. 둘째 줄부터는 가장 밑의 상자부터 가장 위의 상자까지에 저장된 토마토들의 정보가 주어진다. 즉, 둘째줄부터 N개의 줄에는 하나의 상자에 담긴 토마토의 정보가 주어진다. 각 줄에는 상자 가로줄에 들어있는 토마토들의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다. 이러한 N개의 줄이 H번 반복하여 주어진다.

출력: 

여러분은 토마토가 모두 익을 때까지 최소 며칠이 걸리는지를 계산하여 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

풀이방법:

 이전문제에선 2차원 배열로 받았지만, 이번에는 3차원 배열로 작성한다. 또한 위, 아래로도 이동해야 하기 때문에 dx,dy,dn 세 가지 변수를 사용했다. 이외에는 이전문제와 동일한 풀이로 풀었다.

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
import sys
m,n,h=map(int,sys.stdin.readline().split())
tomatos=[]
for j in range(h):
    temp=[]
    for i in range(n):
        t=list(map(int,sys.stdin.readline().split()))
        temp.append(t)
    tomatos.append(temp)
queue=[]
for k in range(h):
    for i in range(n):
        for j in range(m):
            if tomatos[k][i][j]==1:
                queue.append((k,i,j))
dx=[0,0,0,0,-1,1]
dy=[0,1,0,-1,0,0]
dh=[1,0,-1,0,0,0]
count=0
while len(queue)!=0:
    count+=1
    temp=[]
    change=False
    for k,i,j in queue[:]:
        for c in range(6):
            nx=j+dx[c]
            ny=i+dy[c]
            nh=k+dh[c]
            if 0<= ny < n and 0<= nx < m and 0<=nh < h:
                if tomatos[nh][ny][nx]==0:
                    tomatos[nh][ny][nx]=1
                    temp.append((nh,ny,nx))
                    change=True
    queue.pop(0)
    queue=temp
    if not change:
        break
        
remain=False
for k in range(h):
    for i in range(n):
        for j in range(m):
            if tomatos[k][i][j]==0:
                remain=True
                break
if not remain:
    print(count-1
else:
    print(-1)
cs

문제링크:

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

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

[BOJ]14848. 정수 게임  (0) 2019.11.04
[BOJ] 1325. 효율적인 해킹  (0) 2019.10.31
[BOJ]7576. 토마토  (0) 2019.10.29
[BOJ]1049. 기타줄  (0) 2019.10.18
[BOJ]5567. 결혼식  (0) 2019.10.17

문제:

철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자 모양 상자의 칸에 하나씩 넣어서 창고에 보관한다.

 

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토의 인접한 곳은 왼쪽, 오른쪽, 앞, 뒤 네 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익에 되는지, 그 최소 일수를 알고 싶어 한다.

 

토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 탄에는 토마토가 들어있지 않을 수도 있다.

입력:

첫 줄에는 상자의 크기를 나타내는 두 정수 M, N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단 2<=M,N<=1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 상자에 담긴 토마토의 정보가 주어진다. 하나의 줄에는 상자 가로줄에 들어있는 토마토의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0은 잊지 않는 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다.

출력:

여러분은 토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지 못하는 상황이면 -1을 출력해야 한다.

풀이방법:

BFS를 사용해서 풀어야 하는 문제이다. 우선 1이 있는 위치를 파악을 하고 이를 queue에 넣어 준다. 그 뒤에 1을 하나씩 빼면서 옆에 있는 토마토를 익게 만들 수 있는지 계산을 한다. 이 때 change라는 bool 변수를 만들어서 하나의 토마토라도 queue 진행 중에 익게 된다면 True로 바뀌어서 다음 진행을 계속해서 하도록 한다. 만약 익게 되는 토마토가 없어서 False로 남아 있다면 다 익어서 종료가 된 것인지, 혹은 모두 익지 못하는 상황인지 전체를 한 번 탐색하여 파악한다.

처음부터 모두가 익어 있으면 0을 출력해야 하지만 첫 count는 항상 1부터 시작하기 때문에 count-1을 한 값을 출력하면 답을 얻을 수 있다.

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
m,n=map(int,input().split())
tomatos=[]
for i in range(n):
    t=list(map(int,input().split()))
    tomatos.append(t)
queue=[]
for i in range(n):
    for j in range(m):
        if tomatos[i][j]==1:
            queue.append((i,j))
dx=[0,0,-1,1]
dy=[-1,1,0,0]
count=0
while len(queue)!=0:
    count+=1
    temp=[]
    change=False
    for i,j in queue[:]:
        for c in range(4):
            nx=j+dx[c]
            ny=i+dy[c]
            if 0<= ny < n and 0<= nx < m:
                if tomatos[ny][nx]==0:
                    tomatos[ny][nx]=1
                    temp.append((ny,nx))
                    change=True
    queue.pop(0)
    queue=temp
    if not change:
        break
        
remain=False
for i in range(n):
    for j in range(m):
        if tomatos[i][j]==0:
            remain=True
            break
if not remain:
    print(count-1
else:
    print(-1)
cs

문제링크:

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

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

[BOJ] 1325. 효율적인 해킹  (0) 2019.10.31
[BOJ]7569. 토마토  (0) 2019.10.30
[BOJ]1049. 기타줄  (0) 2019.10.18
[BOJ]5567. 결혼식  (0) 2019.10.17
[BOJ]1159. 농구 경기  (1) 2019.10.16

문제:

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N()<=N<=100,000)에 있고, 동생은 점 K(0<=K<=100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.

 

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.

 

입력:

첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.

 

출력:

수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.

 

풀이 방법:

 여러 행위를 할 수 있는데 가장 빠른 방법을 찾는 문제는 대부분 BFS로 풀리는 경우가 많다. 따라서 이 문제도 X-1, X+1, 2X로 이동할 수 있는데 가장 빠른 시간을 찾기 때문에 BFS로 풀어야 한다.

 한 layer마다 Queue의 값에 따라 이동할 수 있는 위치를 새로 queue에 넣는다. 이 과정을 반복하다가 원하는 위치로 이동했다면(dist[k]의 값이 갱신 되었다면) queue를 종료하도록 해서 답을 출력하도록 했다.

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
import queue
n,k=map(int,input().split())
check=[0]*200000
dist=[0]*200000
check[n]=1
q=queue.Queue()
q.put(n)
while q.qsize():
    number=q.get()
    if number-1 >=0:
        if check[number-1]==0:
            q.put(number-1)
            check[number-1]=1
            dist[number-1]=dist[number]+1
    if number+1 < 200000:
        if check[number+1]==0:
            q.put(number+1)
            check[number+1]=1
            dist[number+1]=dist[number]+1
    if 2*number < 200000:
        if check[2*number]==0:
            q.put(2*number)
            check[2*number]=1
            dist[2*number]=dist[number]+1
    if dist[k]:
        break
print(dist[k])
cs

 

문제 링크:

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

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

[BOJ]1759. 암호 만들기  (0) 2019.09.24
[BOJ]14889. 스타트와 링크  (0) 2019.09.23
[BOJ]2022. 사다리  (0) 2019.09.21
[BOJ]1561. 놀이공원  (0) 2019.09.20
[BOJ]1080. 행렬  (0) 2019.09.19

문제:

N x M 크기의 배열로 표현되는 미로가 있다.

미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1,1)에서 출발하여 (N,M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.

 

입력:

첫째 줄에 두 정수 N,M(2<=N,M<=100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

 

출력:

첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.

 

풀이방법:

 최소의 칸 수를 구해야 하는 문제에서는 DFS가 적합하지 않은 경우가 많다. 따라서 이 문제는 BFS를 사용해서 풀어야 하는 문제다.

BFS(queue)를 사용해서 1이 있는 위치에다가 check에 거리를 할당하며 (1,1)에서 (N,M)으로 가도록 하면 된다. 예제 입력2를 통해 설명하면 다음과 같다.

초기 check 배열은 다음과 같이 모두 0이며 (1,1)에서 출발해야 하므로 0,0은 1으로 할당해두도록 한다. 또한 (1,1)를 queue에 넣어두도록 한다.


queue에서 (1,1)을 빼고 이 값을 기준으로 (1,2)와(2,1)가 1로 이동할 수 있으므로 2로 할당한다. 이 값들을 queue에 넣어준다.

 


(1,2)와 (2,1)를 빼고 이 값에서는 (2,2),(1,3)이 이동 가능하므로 3으로 할당하고 이 값들을 queue에 넣어준다.

 

따라서 이 방식대로 계속해서 queue에서 빼고, 넣는 작업을 반복한다

 

count=5일 때,

count=6일 때,


count=7일 때,

count=8일 때,


count=9일 때,

이렇게 계속하다보면 더 이상 queue에 남아 있는 값이 없게 되는데 이 것이 탐색의 끝을 의미한다. 따라서 탐색을 마치고 난 뒤에 (n,m) 값이 정답이다.

 

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
import queue
 
n,m=map(int,input().split())
miro=[]
dx=[0,0,1,-1]
dy=[1,-1,0,0]
for i in range(n):
    miro.append(list(map(int,list(input()))))
check=[[0 for i in range(m)]for j in range(n)]
 
q=queue.Queue()
q.put((0,0))
check[0][0]=1
temp=queue.Queue()
count=2
while q.qsize():
    x,y=q.get()
    for i in range(4):
        newX=x+dx[i]
        newY=y+dy[i]
        if 0<=newX<and 0<=newY<m:
            if miro[newX][newY]==1 and check[newX][newY]==0:
                temp.put((newX,newY))
                check[newX][newY]=count
    if q.qsize()==0:
        q=temp
        count+=1
        temp=queue.Queue()
print(check[n-1][m-1])
cs

문제링크:

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

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

[BOJ]1371. 가장 많은 글자  (0) 2019.09.10
[BOJ]9933. 민균이의 비밀번호  (0) 2019.09.09
[BOJ]2667. 단지번호붙이기  (0) 2019.09.07
[BOJ]2331. 반복 수열  (6) 2019.09.06
[BOJ] 10451.순열 사이클  (0) 2019.09.05

문제:

케빈 베이컨의 6단계 법칙에 의하면 지구에 있는 모든 사람들은 최대 6단계 이내에서 서로 아는 사람으로 연결될 수 있다. 케빈 베이컨 게임은 임의의 두 사람의 최소 몇 단계 만에 이어질 수 있는지 계산하는 게임이다.

 

예를 들면, 전혀 상관없을 것 같은 인하대학교의 이강호와 서강대학교의 민세희는 몇 단계만에 이어질 수 있을까?

 

천민호는 이강호와 같은 학교에 다니는 사이이다. 천민호와 최백준은 Backjoon Online Judge를 통해 알게 되었다. 최백준과 김선영은 같이 Startlink를 창업했다. 김선영과 김도현은 같은 학교 동아리 소속이다. 김도현과 민세희는 같은 학교에 다니는 사이로 서로 알고 있다. 즉, 이강호-천민호-최백준-김선영-김도현-민세희 와 같이 5단계만 거치면 된다.

 

케빈 베이컨은 미국 헐리우드 영화배우들끼리 케빈 베이컨 게임을 했을 때 나오는 단계의 총 합이 가장 적은 사람이라고 한다.

 

오늘은 Baekjoon Online Judge의 유저 중에서 케빈 베이컨의 수가 가장 적은 사람을 찾으려고 한다. 케빈 베이컨 수는 모든 사람과 케빈 베이컨 게임을 했을 때, 나오는 단계의 합이다.

 

예를 들어, BOJ의 유저가 5명이고, 1과 3, 1과 4, 2와 3, 3과 4, 4와 5가 친구인 경우를 생각해보자.

 

1은 2까지 3을 토해 2단계 만에, 3까지 1단계, 4까지 1단계, 5까지 4를 통해서 2단계 만에 알 수 있다. 따라서, 케빈 베이컨의 수는 2+1+1+2 = 6 이다.

 

2는 1까지 3을 통해서 2단계 만에, 3까지 1단계 만에, 4까지 3을 통해서 2단계 만에, 5까지 3과 4를 통해서 3단계 만에 알 수 있다. 따라서, 케빈 베이컨의 수는 2+1+2+3 = 8이다.

 

3은 1까지 1단계, 2까지 1단계, 4까지 1단계, 5까지 4를 통해 2단계 만에 알 수 있다. 따라서, 케빈 베이컨의 수는 1+1+1+2 =5 이다.

 

4는 1까지 1단계, 2까지 3을 통해 2단계, 3까지 1단계, 5까지 1단계 만에 알 수 있다. 4의 케빈 베이컨의 수는 1+2+1+1 = 5가 된다.

 

마지막으로 5는 1까지 4를 통해 2단계, 2까지 4와 3을 통해 3단계, 3까지 4를 통해 2단계, 4까지 1단계 만에 알 수 있다. 5의 케빈 베이컨의 수는 2+3+2+1 = 8이다.

 

5명의 유저 중에서 케빈 베이컨의 수가 가장 작은 사람은 3과 4이다.

 

BOJ 유저의 수와 친구 관계 입력으로 주어졌을 때, 케빈 베이컨의 수가 가장 작은 사람을 구하는 프로그램을 작성하시오.

 

입력:

첫째 줄에 유저의 수 N(2<=N<=100)과 친구 관계의 수 M(1<=M<=5,000)이 주어진다. 둘째 줄부터 M

개의 줄에는 친구 관계가 주어진다. 친구 관계는 A와 B로 이루어져 있으며, A와 B가 친구라는 뜻이다. A와 B가 친구이면, B와 A도 친구이며, A와 B가 같은 경우는 없다. 친구 관계는 중복되어 들어올 수도 있으며, 친구가 한 명도 없는 사람은 없다. 또, 모든 사람은 친구 관계로 연결되어져 있다.

 

출력:

첫째 줄에 BOJ의 유저 중에서 케빈 베이컨의 수가 가장 적은 사람을 출력한다. 그런 사람이 여러 명일 경우에는 번호가 가장 작은 사람을 출력한다.

 

풀이방법:

일단 모든 사람들에 대해서 케빈 베이컨의 수를 계산해야 하므로 BFS로 값을 탐색해야 한다고 생각했다.  for를 사용한 반복문은 입력값을 정리하기 위한 반복문이다. (보통 저는 bfs, dfs는 이와 같이 입력값들을 정리합니다.) answer는 각 사람 별로 count의 값을 담아주는 배열이고, 인덱스를 편리하기 관리하기 위해 1번 사람이 1번째 인덱스를 가지도록 하였다. person은 인덱스 값으로 교체해줘도 괜찮을 것 같지만 bfs 내에서 한 단계 이상 넘어간다면 여러 개의 값을 가져야 할 것 같아서 애초에 배열 값으로 넣게 되었다. 그리고 또한 자기 자신의 값을 탐색하지 않도록 자신의 값은 -1로 초기화 한 상태로 값을 넣었다.

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
def bfs(counts,person,friends,count):
    temp=[]
    for pe in person:
        for i in friends[pe]:
            if counts[i]==0:
                counts[i]=count
                temp.append(i)
    if len(temp):
        count+=1
        bfs(counts,temp,friends,count)
 
 
n,m=map(int,input().split())
friends=[[] for i in range(n+1)]
for i in range(m):
    a,b=map(int,input().split())
    if not a in friends[b]:
        friends[b].append(a)
        friends[b].sort()
    if not b in friends[a]:
        friends[a].append(b)
        friends[a].sort()
answers=[0]*(n+1)
answers[0]= -1
person=[1]
while not all(answers):
    counts=[0]*(n+1)
    count=1
    counts[person[0]]=-1
    bfs(counts,person,friends,count)
    answers[person[0]]=sum(counts)+1
    person[0]+=1
print(answers.index(min(answers[1:])))
cs

 

문제링크:

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

 

 

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

[BOJ]1406. 에디터  (0) 2019.08.23
[BOJ]11053. 가장 긴 증가하는 부분 수열  (0) 2019.08.22
[BOJ]4307. 개미  (0) 2019.08.06
[BOJ]1309. 동물원  (0) 2019.08.05
[BOJ]5430. AC  (0) 2019.08.04

문제:

 n개의 노드가 있는 그래프가 있습니다. 각 노드는 1부터 n까지 번호가 적혀있습니다. 1번 노드에서 가장 멀리 떨어진 노드의 갯수를 구하려고 합니다. 가장 멀리 떨어진 노드란 최단경로로 이동했을 때 간선의 개수가 가장 많은 노드들을 의미합니다. 

 노드의 개수 n, 간선의 대한 정보가 담신 2차우너 배열 vertex가 매개변수로 주어질 때, 1번 노드로부터 가장 멀리 떨어진 노드가 몇 개인지를 return 하도록 solution 함수를 작성해주세요.

풀이 방법:

 노드들의 최소경로 값을 나타내는 answer를 만든 뒤에 BFS 방식으로 노드들을 검사한다. 노드를 방문할 때마다 해당 node의 answer 값이 0이면 count로 초기화 해주고, count는 한 층을 더 들어갈 때 마다 1씩 증가하도록 했다. 이렇게 모든 answer가 0이 아닌 값으로 변하면(all) answer의 max값을 찾아서 max로 count를 해 답을 얻을 수 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def solution(n, edge):
    answer = [0]*(n+1)
    newedge=[[] for i in range(len(edge)+1)]
    for i in range(len(edge)):
        if not edge[i][1in newedge[edge[i][0]]:
            newedge[edge[i][0]].append(edge[i][1])
            newedge[edge[i][0]].sort()
        if not edge[i][0in newedge[edge[i][1]]:
            newedge[edge[i][1]].append(edge[i][0])
            newedge[edge[i][1]].sort()
    answer[0],answer[1]= -1,-1
    queue=[1]
    count=1
    while not all(answer):
        temp=[]
        for start in queue:
            for i in newedge[start]:
                if answer[i] ==0:
                    answer[i]+=count
                    temp.append(i)
        queue=temp
        count+=1
    ans=answer.count(max(answer))
    return ans
cs

문제 링크:


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

[Programmers]Lv 3.배달  (3) 2019.07.31
[Programmers]Lv 3. 순위  (0) 2019.07.30
[Programmers]Lv 4. 3xn 타일링  (2) 2019.07.28
[BOJ]2805. 나무 자르기  (0) 2019.07.27
[BOJ]1654.랜선 자르기  (0) 2019.07.26

+ Recent posts