# 1937 욕심쟁이 판다 실패(Fail)
def dfs(x,y):
    global N
    stack = [(x,y,0)]
    last_direction = []
    while stack:
        cx,cy,distance = stack.pop()
        flag = True
        for i in range(4):
            nx = cx + dx[i]
            ny = cy + dy[i]
            if 0 <= nx<N and 0<=ny<N:
                if bamboo[cx][cy] < bamboo[nx][ny]:
                    if dp[nx][ny] == -1:
                        stack.append((nx,ny,distance+1))
                    else:
                        if distance + dp[nx][ny] + 1 > dp[x][y]:
                            dp[x][y] = dp[nx][ny] + distance + 1
                           
                    flag = False
        if flag:
            if dp[x][y] < distance + 1:
                dp[x][y] = distance + 1



N = int(input())
dx = [-1,1,0,0]
dy = [0,0,-1,1]
bamboo = [list(map(int,input().split())) for _ in range(N)]
dp = [[-1]*N for _ in range(N)]

result = - 1
for x in range(N):
    for y in range(N):
        if dp[x][y] == -1:
            dfs(x,y)
print(max(map(max,dp)))

이 문제를 단순하게 DFS로 풀면 시간 초과가 날수 밖에 없다. 왜냐하면 입력이 최대가 500*500 이므로, dp를 통해 이미 탐색한 값들을 저장해놓는 과정이 필요하다. 위의 코드는 시간초과가 난 코드이다. 

dp를 사용하긴 했지만, 각 (x,y) 축에서 dfs를 하지만, 이 이동경로에 있는 좌표들에 대해서 이미 한번 측정한 값인데, 다시 한번 dp를 측정해야하는 것이다.

 

 

import sys


def dfs(x,y):
    if dp[x][y] != -1:
        return dp[x][y]
    else:
        dp[x][y] = 1
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<N and 0<=ny<N:
                if bamboo[nx][ny]>bamboo[x][y]:
                    distance = dfs(nx,ny) + 1
                    dp[x][y] = max(distance,dp[x][y])
        return dp[x][y]







N = int(input())
dx = [-1,1,0,0]
dy = [0,0,-1,1]
bamboo = [list(map(int,input().split())) for _ in range(N)]
dp = [[-1]*N for _ in range(N)]
result = - 1
for x in range(N):
    for y in range(N):
        if dp[x][y] == -1:
            dfs(x,y)

print(max(map(max,dp)))

재귀를 이용한, 이동 경로에 대해서 전부 한번에 업데이트를 해주는 것이다.

 

최초 이동경로에서 (x0,y0) = > (x1,y1) => (x2,y2) => ...=>(xn,yn) 각 경로마다 최대로 갈수 있는 이동경로들을 저장해준다. 그리고 return된 값에 + 1을 해줘 해당 칸에 갔을때의 이동거리를 측정해주고, 최대값을 갱신해주면 된다.

 

이렇게 하면 장점은 어느 곳에서 한번 방문했던 곳은 더 이상 dfs를 하지않고 해당 위치에서의 최대값을 반환해주는 것이다.

 

이 문제는 각 위치마다의 최대경로를 구하는 로직과, 그걸 이용해서 시간복잡도를 줄이는게 중요한 문제였다.

# # # 9466 텀 프로젝트
import sys
sys.setrecursionlimit(100000)



def dfs(node):
    global result
    visited[node] = False
    total.append(node)
    next_node = graph[node]
    if not visited[next_node]:
        if next_node in total:
            find_index = total.index(next_node)
    
            result +=total[find_index:]
        return
    else:
        dfs(next_node)


for _ in range(int(input())):
    N = int(input())
    graph = [0]+list(map(int,sys.stdin.readline().split()))
    visited = [True] *(N+1)
    result = []
    for ind in range(1,N+1):
        if visited[ind]:
            total = []
            dfs(ind)
    print(N-len(result))

 

문제를 풀때, 어떻게 풀어야할지 고민을 했던 문제이다. 문제를 읽어보면, 사이클을 이루는 경우에만, 팀이 될수 있다는 것을 알 수 있다. 

그래서 DFS 재귀를 통해서, 내가 방문한 곳을 다시 방문하게 된다면, 사이클을 이루게 되는 것이기 때문에, 결과값에 추가해주었다. 중간의 find_index 같은 경우 사이클을 이루어지는 최초지점을 찾아서 저장해주기 위함이다.

 

만약 1,2,3,4,5 가 있고, 각각 2,3,4,5,2를 선택했다고 하면 dfs를 했을때 total에는 [1,2,3,4,5]가 저장되어있을 것이다. 하지만, 1은 문제에 주어진 조건을 만족하지 못하고, 팀이 되지 못한다. 그래서 사이클이 최초로 시작되는 2를 기준으로 잘라주기 위함이다.

 

for _ in range(int(input())):
    N = int(input())
    graph = list(map(int,input().split()))
    visited = [0]*N
    cnt = 0
    for current_node in range(N):
        if not visited[current_node]:
            next_node = current_node
            while visited[next_node] == 0:
                visited[next_node] = 1
                next_node = graph[next_node] - 1
            cycle_index = current_node
            while cycle_index != next_node:
                cnt += 1
                cycle_index = graph[cycle_index] - 1

    print(cnt)

            

좀 더 깔끔한 풀이다. 위와 비슷하지만, 최초로 사이클이 시작되는 노드는 중간의 while문을 통과하고 나온 next_node일것이다.

그러면 처음 노드인 current_node를 복사해, cycle_index라고 하고, 이 cycle_index가 next_node와 같지 못하면, 사이클에 포함되지 않는 노드임을 알 수 있다. 이 next_node는 사이클이 최초로 발생하는 노드의 위치이기 때문에, 만약 current_node에서 사이클이 시작됬다면 cycle_node와 next_node는 동일할 것이다. 

그래서, 이 cycle_node를 똑같이 반복문을 돌리면서 next_node와 같아질때까지 반복을 한다. 그게 곧 팀에 포함되지 않는 사람의 수를 나타내는 것임을 알 수 있다.

# 매출하락 최소화

def solution(sales,links):
    N = len(sales)
    sales = [0]+sales
    tree = [[] for _ in range(N+1)]
    for parents,child in links:
        tree[parents].append(child)
    loss_sale = [[0]*2 for _ in range(N+1)]
    # loss_sale[x][0] = x번 노드가 참석하는 경우
    # loss_sale[x][1] = x번 노드가 불참석하는 경우
    def dfs(node):
        nonlocal loss_sale,tree,sales
        if not tree[node]:
            loss_sale[node][0] = sales[node]
            return

        for child_node in tree[node]:
            dfs(child_node)
            loss_sale[node][0] += min(loss_sale[child_node][0],loss_sale[child_node][1])

        
        loss_sale[node][0] += sales[node]
        atamp_loss = float('inf')
        for child_node in tree[node]:
            atamp_loss = min(loss_sale[child_node][0]-loss_sale[child_node][1],atamp_loss)
        loss_sale[node][1] = max(0,atamp_loss) + loss_sale[node][0] - sales[node]
    dfs(1)
    return min(loss_sale[1])

www.youtube.com/watch?v=FX9n1PFv2K4

BaaarkingDog 님의 풀이와 

 

카카오 공식블로그에 있는, tech.kakao.com/2021/01/25/2021-kakao-recruitment-round-1/를 참조하여 푼 문제이다.

 

그러니 실질적으로, 내힘으로 푼 문제라 할순 없지만, 내가 잘 모르는 Tree-dp에 관련된 문제이고, 코드를 분석하면서, 이러한 문제 유형에 대해서 경험해보기 위해서 풀었다.

 

자세한 설명을 원하시는 분은 상단에 링크된 유튜브와 카카오 공식 블로그를 참조하길 바란다.

 

기본적인 풀이는 tree-dp에 관련된 문제였다. dp를 tree에 적용시킨 거고, dfs를 재귀방식으로 해서 푼 문제로 생각했다..

 

먼저 들어온 links에 대해서 부모노드에 자식노드를 추가해주는 작업을 했다.

 

그리고 index가 전부 1부터 시작하기 때문에 풀이의 용이함을 위해, sales 앞에 0을 추가해주었다.

 

이 상태에서 dfs를 통해, 매출하락 최소화를 구하는 작업을 해줬다.

 

loss_sale 이란 변수는 해당 노드가 워크샵에 참여유무에 따른 매출하락을 저장해놓은 변수이다.

ex ) loss_sale[x][0] 은 x번 노드가 워크샵에 참석하는 경우

      loss_sale[x][1] 은 x번 노드가 워크샵에 참석하지 않는 경우

 

dp는 작은단위부터 해야된다고 생각해서, 가장 끝단부터 하겠다.

 

1) 리프노드일 경우

  리프노드 일 경우엔, 자기자신이 참석하는 거 외에는 loss_sale을 갱신해줄만한 요소가 없다.

   loss_sale[leaf_node][0] = sales[leaf_node] 를 넣어주고 return 해주면 된다.

 

 

2) 리프노드가 아닐 경우

   리프노드가 아닐경우, 그 노드들은 팀원이면서 팀장이다. 여기서는 dfs를 들어갔을때, 팀장노드인 시점에서 들어가므로, 팀장노드라고 부르겠다.

   2-1) 팀장노드가 참석하는 경우

      > 팀장노드가 참석하는 경우에는 팀원노드들이 어떤 상태인지 상관 없기 때문에, 각 자식노드들의 참석 불참석했을          때 둘 중 최소값을 더해주면 된다.

      > 그리고 마지막으로 팀장노드의 매출 값을 저장해주면 된다.

      즉, 각 팀원노드마다  min(loss_sale[팀원노드][0],loss_sale[팀원노드][1]) 를 구해서 더해주고, 마지막에 팀장의 sales를 더해주면 된다.

 

   2-2) 팀장노드가 참석하지 않는 경우

       > 팀장 노드가 참석하지 않는 경우엔, 팀원 노드들 중에 한명이 무조건 참석을 해야한다. 그렇다면 매출하락폭이 최소화가 될려면 불참이었을때와 참여했을때의 loss_sale을 비교해서 그 차이가 최소값인 것을 찾아서 그 팀원노드을 선택하면 된다. 그 팀원이 불참이였다가, 참여로 전환시키는 것이기때문에 그 값을 더해주면 된다.

 

       > 여기서 max(0,atamp_loss)라고 해준 이유는 카카오 공식문서에서 나온 설명 마지막 부분과 부합된다.

          만약 팀원노드 A가 있다고 했을때,

          팀원노드 A가 팀장인 팀에서 최소가 되는 경우가, 팀원노드 A가 참석을 했을 때라고, 하면,

          위에서 구한, loss_sale[팀원노드 A의 부모노드][0]에 포함이 되어있을것이고, 이미 A라는 팀원이 참석한것이기

          때문에, 더해줄 필요성이 없다.

          그래서 팀원노드 A의 loss_sale은 참석했을때 loss_sale[팀원노드A][0] 보다 loss_sale[팀원노드A][1]이

           더 클 것이기 때문에 음수가 나오므로, max를 통해 0과 비교하여 음수를 방지해 주는 것이다.

 

        > 이렇게 참석과 불참석의 차이가 최소가 되는 노드를 선택하고 그 값에 팀장노드가 참석했을때의 값에서

           팀장노드가 참석을 안하기 때문에, 팀장노드의 매출을 빼주면 된다.

 

 

위와 같은 과정을 거친 후 CEO인 1번노드의 loss_sale의 최소값을 출력해주면 된다.

 

 

 

 

이 문제는 풀이를 보면서 풀었지만, tree와 dp에 대한 개념이 잡히지 않고서는 쉽게 풀 수 없는 문제 인것같다.

 

평소에도 가장 어려워하는 알고리즘이 dp와 tree이기때문에, 어려웠고, 그 2개가 합쳐진거라 더 나에게 어려움으로 느껴졌다.

 

이 풀이를 보면서 느낀점은 dp를 풀때에는 소분화해서 풀어야 하고, 점화식을 찾아서 동적으로 해야한다.

 

상반기까지 남은기간이 얼마 안남았는데,

내가 평소에 약점인 tree, dp, 플로이드, prefix_sum, 투포인터,segement tree (거의 대부분이지만) 에 대해서 더 공부해야겠다.

# 1987 알파벳

def dfs(x,y,visited,cnt):
    global result,const,ccs
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0 <= nx< R and 0<= ny<C and visited[ord(arr[nx][ny])-const]:
            visited[ord(arr[nx][ny])-const] = False
            dfs(nx,ny,visited,cnt+1)
            visited[ord(arr[nx][ny])-const] = True
    if cnt > result:
        result = cnt
ccs = 0
R,C = map(int,input().split())
dx = [-1,1,0,0]
dy = [0,0,-1,1]
arr = [list(input()) for _ in range(R)]
result = 1
visit = [True]*26
const = ord('A')
visit[ord(arr[0][0])-const] = False
dfs(0,0,visit,1)

print(result)

시간 초과의 늪에 빠졌던 문제이다. 기본적인 원리는 찾았으나, 문제를 해결하기 위한 방안을 찾기위해 노력했던 문제이다.

처음으로 풀었던 방식은 원래는 visited를 하나의 집합으로 해서 있는지 없는지 체크를 했다면, 알파벳에 해당되는 visited 리스트를 만들어주고 check 해주는 방식으로 풀었다.

 

 

# 1987 알파벳


R,C = map(int,input().split())

arr = [list(input()) for _ in range(R)]
check = [['']*C for _ in range(R)]

stack = [(0,0,1,arr[0][0])]
result = 0
dx = [-1,1,0,0]
dy = [0,0,1,-1]
while stack:
    x,y,cnt,total = stack.pop()
    if result < cnt:
        result = cnt
    if result == 26:
        break
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0 <= nx < R and 0<= ny <C:
            if arr[nx][ny] not in total:
                temp = total + arr[nx][ny]
                if check[nx][ny] != temp:
                    check[nx][ny] = temp
                    stack.append((nx,ny,cnt+1,temp))
print(result)

시간이 빠른 방식은 다음과 같다. visited를 체크하는 것은 하나의 스트링을 통해 그 안에 있는지 없는지 확인하는 것이다.

여기까지는 동일하다. 하지만 결정적으로 다른것은 check라는 행렬을 통해 또 체크 하는 것이다.

지금까지 온 이동경로를 넣어놓는 check라는 행렬이다. 이 행렬에 존재하는 값과 같으면, 이미 그에 대해서 전부 탐색을 한 것이기 때문에 또 다시 탐색할 필요가 없다.

 

탐색한 경로들을 캐싱해놓은것과 같다. 서로다른 루트로 왔다 하더라도 다음위치에 똑같은 값으로 들어오는 거면 굳이 한번 더 검색을 할 필요가 없다.

 

이 방법은 dfs나 bfs 상관은 없으나 bfs를 할 시, collections의 deque를 쓰도록 하자. 안 그러면 시간 초과가 난다.

 

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

[BOJ/백준] 1107 리모컨  (0) 2021.02.13
[BOJ/백준] 15591 MooTube(Silver)  (0) 2021.02.13
[BOJ/백준] 1655 가운데로 말해요  (0) 2021.02.02
[BOJ/백준] 3197 백조의 호수  (0) 2021.02.01
[BOJ/백준] 1309 동물원  (0) 2021.01.31
# 11403 경로 찾기



N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
for k in range(N):
    for x in range(N):
        for y in range(N):
            if arr[x][k] + arr[k][y] == 2:
                arr[x][y] = 1

for i in range(N):
    print(*arr[i])

풀고보니 플로이드 와샬 문제였다.

 

중간 경로를 통해서 두개가 연결이 되는 경우 arr를 갱신해주는 방식으로 했다.

 

이 방식 말고도 BFS,DFS를 통해 node들을 탐색해서 푸는 방식도 있다.

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

[BOJ/백준] 3197 백조의 호수  (0) 2021.02.01
[BOJ/백준] 1309 동물원  (0) 2021.01.31
[BOJ/백준] 9251 LCS  (0) 2021.01.29
[BOJ/백준] 14499 주사위 굴리기  (0) 2021.01.29
[BOJ/백준] 9633 N-queen  (0) 2021.01.28
# 2251 물통
#  A,B,C 
#  앞의 두 물통은 비어 있고, 세번째 물통은 가득 차 있다.
# A 물통이 비어있을때 세번째 물통에 담겨 있을 수 있는 물의 양을 구해내시오.
import collections 
max_Bowl = list(map(int,input().split()))
current_bowl = [0,0,max_Bowl[2]]
visited = [[[False]*(max_Bowl[2]+1) for _ in range(max_Bowl[1]+1)] for _ in range(max_Bowl[0]+1)]
# A,B,C
que = collections.deque()
que.appendleft((0,0,max_Bowl[2]))
result = set()
result.add(max_Bowl[2])
while que:
    cureent_water = que.popleft()
    if visited[cureent_water[0]][cureent_water[1]][cureent_water[2]]:
        continue
    if cureent_water[0] == 0:
        result.add(cureent_water[2])
    visited[cureent_water[0]][cureent_water[1]][cureent_water[2]] = True
    # A->B
    if cureent_water[0]+cureent_water[1] >= max_Bowl[1]:
        que.append((cureent_water[0]+cureent_water[1]-max_Bowl[1],max_Bowl[1],cureent_water[2]))
    else:
        que.append((0,cureent_water[0]+cureent_water[1],cureent_water[2]))
    # A->C
    if cureent_water[0]+cureent_water[2] >= max_Bowl[2]:
        que.append((cureent_water[0]+cureent_water[2]-max_Bowl[2],cureent_water[1],max_Bowl[2]))
    else:
        que.append((0,cureent_water[1],cureent_water[0]+cureent_water[2]))
    # B->C
    if cureent_water[1]+cureent_water[2] >= max_Bowl[2]:
        que.append((cureent_water[0],cureent_water[1]+cureent_water[2]-max_Bowl[2],max_Bowl[2]))
    else:
        que.append((cureent_water[0],0,cureent_water[1]+cureent_water[2]))
    # B->A
    if cureent_water[1]+cureent_water[0] >= max_Bowl[0]:
        que.append((max_Bowl[0],cureent_water[1]+cureent_water[0]-max_Bowl[0],cureent_water[2]))
    else:
        que.append((cureent_water[1]+cureent_water[0],0,cureent_water[2]))
    # C->A
    if cureent_water[2] + cureent_water[0] >= max_Bowl[0]:
        que.append((max_Bowl[0],cureent_water[1],cureent_water[2]+cureent_water[0]-max_Bowl[0]))
    else:
        que.append((cureent_water[2]+cureent_water[0],cureent_water[1],0))
    # C->B
    if cureent_water[2] + cureent_water[1] >= max_Bowl[1]:
        que.append((cureent_water[0],max_Bowl[1],cureent_water[2]+cureent_water[1]-max_Bowl[1]))
    else:
        que.append((cureent_water[0],cureent_water[2]+cureent_water[1],0))

result = sorted(list(result))
print(*result)

처음에 풀때 난잡하다. 똑같이 반복되는것을 계쏙 반복해주었다.

A->B,

A->C

B->C

B->A

C->A

C->B

의 과정을 거쳐주면서 방문하지 않은 경우에만 하는 방식으로 했다.

이렇게 하니 단순반복을 계속해서 쓰면서도 알아보기 힘들었다.

 

A,B,C = map(int,input().split())
def custom_append(a,b,c):
    global visited,stack,result
    if (a,b,c) not in visited:
        visited.add((a,b,c))
        stack.append((a,b,c))
        if a == 0:
            result.add(c)




def move_bowl(origin,target,target_max):
    if origin+target >= target_max:
        origin = origin+target- target_max
        target = target_max
    else:
        target = origin + target
        origin = 0
    return (origin,target)
visited = set()
visited.add((0,0,C))
stack = [(0,0,C)]
result = set()
result.add(C)

while stack:
    ca,cb,cc = stack.pop()
    if ca:
        # A->B
        na,nb = move_bowl(ca,cb,B)
        custom_append(na,nb,cc)
        # A->C
        na,nc = move_bowl(ca,cc,C)
        custom_append(na,cb,nc)
    if cb:
        # B->C
        nb,nc = move_bowl(cb,cc,C)
        custom_append(ca,nb,nc)
        # B->A
        nb,na = move_bowl(cb,ca,A)
        custom_append(na,nb,cc)
    if cc:
        # C->A
        nc,na = move_bowl(cc,ca,A)
        custom_append(na,cb,nc)
        # C->B
        nc,nb = move_bowl(cc,cb,B)
        custom_append(ca,nb,nc)

result = sorted(list(result))
print(*result)

좀 더 깔끔하게 바뀐 풀이방식이다.

 

물을 옮기는 과정을 하나의 함수로 만들어주었고, stack에 추가해주고 방문표시를 해주는것도 하나의 함수로 만들어줬다.

 

이렇게 하니, 본문에는 간단하게 남았고, 불필요한 코드를 반복해서 쓸필요성이 없어졌다.

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

[BOJ/백준] 12851 숨바꼭질 2  (0) 2021.01.25
[BOJ/백준] 2133 타일 채우기  (0) 2021.01.24
[BOJ/백준] 2624 동전 바꿔주기  (0) 2021.01.22
[BOJ/백준] 17142 연구소3  (0) 2021.01.22
[BOJ/백준] 1946 신입 사원  (0) 2021.01.22
# 1058 친구

def dfs(idx):
    global N
    visited = [True]*N
    visited[idx] = False
    stack = [(idx,0)]
    cnt = -1

    while stack:
        cu_x,both_person = stack.pop()
        for x in range(N):
            if arr[cu_x][x] == 'Y':
                if visited[x] and both_person <= 1:
                    visited[x] = False
                    stack.append((x,both_person+1))
        cnt += 1
    return cnt
N = int(input())

arr = [list(input()) for _ in range(N)]
max_number = 0
for i in range(N):
    temp = dfs(i)
    max_number = max(max_number,temp)

print(max_number)

이 문제는 DFS를 이용해서 풀었다.

 

이 문제에서 2-친구가 되는 경우는 2종류이다.

1. 직접적인 친구인 경우

2. 한 다리를 건너서 친구가 되는 경우

 

총 2가지이다.

 

이것을 구분해주기 위해 both_person이라는 변수로 징검다리 친구가 되는 경우를 찾아줬따.

 

이 변수 없이 진행 시, 연결된 모든 친구들이 출력되기 때문에, 최대 거리가 2이하인 경우만 구분해줄려고 썼다.

 

이 문제를 풀고 난뒤에 대부분의 사람들이 플로이드 와샬로 풀었다는 경우가 많지만,

 

아직 플로이드 와샬 알고리즘에 대해 잘 모르기 때문에 그 방법은 나중에 알고리즘을 배우면 시도 해봐야겠다.

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

[BOJ] 5569 출근 경로  (0) 2021.01.15
[BOJ] 2140 지뢰찾기  (0) 2021.01.15
[BOJ] 10884 쉬운 계단 수  (0) 2021.01.14
[BOJ] 1149 RGB 거리  (0) 2021.01.14
[BOJ] 12865 평범한 배낭  (0) 2021.01.14
import collections
dx=[1,-1,0,0]
dy=[0,0,1,-1]
def bfs(n):
    que=collections.deque()
    que.append(n)
    while que:
        t=que.popleft()
        ax=t//1000000
        ay=t%1000000
        visit[ax][ay]=0
        for i in range(4):
            nx=ax+dx[i]
            ny=ay+dy[i]
            if 0<=nx<M and 0<=ny<N:
                if arr[nx][ny]==1 and visit[nx][ny]==-1:
                    que.append(1000000*nx+ny)
                    visit[nx][ny]=0
    return


T=int(input())

for tc in range(1,T+1):
    N,M,K=list(map(int,input().split()))
    arr=[[0 for j in range(N)] for i in range(M)]
    visit=[[-1]*N for i in range(M)]
    
    for _ in range(K):
        y,x=list(map(int,input().split()))
        arr[x][y]=1
    cnt=0
    for i in range(M):
        for j in range(N):
            if arr[i][j]==1 and visit[i][j]==-1:
                cnt+=1
                bfs(i*1000000+j)
    print(cnt)
    

 

 

 

위의 방식은 BFS를 이용해서 푼 방식이다.

 

 

dx=[1,-1,0,0]
dy=[0,0,1,-1]
import sys
sys.setrecursionlimit(10**6)
def dfs(x,y,_cnt):
    dist[x][y]=_cnt

    for k in range(4):
        nx=x+dx[k]
        ny=y+dy[k]
        if 0<=nx<N and 0<=ny<M:
            if arr[nx][ny] and dist[nx][ny]==-1:
                dfs(nx,ny,_cnt)




t=int(input())
for _ in range(t):
    M,N,K=map(int,input().split())
    arr=[[0 for col in range(M)] for row in range(N)]
    dist=[[-1 for col in range(M)] for row in range(N)]
    for _ in range(K):
        y,x=map(int,input().split())
        arr[x][y]=1
    
    cnt=0

    for i in range(N):
        for j in range(M):
            if arr[i][j]==1 and dist[i][j]==-1:
                cnt+=1
                dfs(i,j,cnt)
    print(cnt)

    

DFS를 이용한 방식이다.

 

BFS나 DFS로 풀면 되는 문제이다. 방문한적이 없고 서로 연결된 것들의 개수를 구하면 되는 문제이다.

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

[BOJ] 1149 RGB 거리  (0) 2021.01.14
[BOJ] 12865 평범한 배낭  (0) 2021.01.14
[BOJ] 1010 다리 놓기  (0) 2021.01.13
[BOJ] 1002 터렛  (0) 2021.01.13
[BOJ] 5014 스타트링크  (0) 2021.01.13

+ Recent posts