문제:

BOJ 알고리즘 캠프에는 총 N명이 참가하고 있다. 사람들은 0번부터 N-1번으로 번호가 매겨져 있고, 일부 사람들은 친구이다.

오늘은 다음과 같은 친구 관계를 가진 사람 A, B, C, D, E가 존재하는지 구해보려고 한다.

  • A는 B와 친구다.
  • B는 C와 친구다.
  • C는 D와 친구다.
  • D는 E와 친구다.

위와 같은 친구 관계가 존재하는지 안하는지 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 사람의 수 N (5 ≤ N ≤ 2000)과 친구 관계의 수 M (1 ≤ M ≤ 2000)이 주어진다.

둘째 줄부터 M개의 줄에는 정수 a와 b가 주어지며, a와 b가 친구라는 뜻이다. (0 ≤ a, b ≤ N-1, a ≠ b) 같은 친구 관계가 두 번 이상 주어지는 경우는 없다.

출력:

문제의 조건에 맞는 A, B, C, D, E가 존재하면 1을 없으면 0을 출력한다.

풀이방법:

 처음에는 문제를 조금 이해하는 것이 어려웠다. 주어진 모든 사람의 관계가 조건과 같이 구성되어야 하는줄 알았는데, 일부 사람들만 관계를 유지하면 된다. 따라서 N명의 사람들의 관계를 트리 형태로 구성했을 때, 하나의 노드로부터 깊이가 4인 경우가 있는지 확인하면 된다.

 따라서 처음에는 주어진 관계들을 양방향 그래프로 정리를 한다. 그 다음에는 각 노드로부터 dfs를 수행했을 때, 깊이가 4인 경우가 있는지 확인한다. 깊이가 4인 경우가 한 개라도 있으면 되기 때문에 찾았다면 탐색을 중지하고 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
def dfs(node, depth):
    global answer
    if depth==4:
        answer = 1
        return
    for f in friends[node]:
        if f in relationship:
            continue
        relationship.append(f)
        dfs(f,depth+1)
        relationship.pop()
 
N, M = map(int,input().split())
 
friends = [[] for _ in range(N)]
for _ in range(M):
    a, b = map(int, input().split())
    friends[a].append(b)
    friends[b].append(a)
 
answer = 0
for i in range(N):
    relationship = [i]
    dfs(i, 0)
    if answer:
        break
print(answer)
cs

문제링크:

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

 

13023번: ABCDE

문제의 조건에 맞는 A, B, C, D, E가 존재하면 1을 없으면 0을 출력한다.

www.acmicpc.net

 

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

[BOJ] 2251. 물통  (0) 2021.10.28
[BOJ] 15988. 1, 2, 3 더하기  (0) 2021.10.25
[BOJ]1339. 단어 수학  (0) 2021.10.21
[BOJ] 15658. 연산자 끼워넣기 (2)  (0) 2021.10.20
[BOJ] 17140. 이차원 배열과 연산  (0) 2021.10.19

문제:

세로 두 줄, 가로로 N개의 칸으로 이루어진 표가 있다. 첫째 줄의 각 칸에는 정수 1, 2, …, N이 차례대로 들어 있고 둘째 줄의 각 칸에는 1이상 N이하인 정수가 들어 있다. 첫째 줄에서 숫자를 적절히 뽑으면, 그 뽑힌 정수들이 이루는 집합과, 뽑힌 정수들의 바로 밑의 둘째 줄에 들어있는 정수들이 이루는 집합이 일치한다. 이러한 조건을 만족시키도록 정수들을 뽑되, 최대로 많이 뽑는 방법을 찾는 프로그램을 작성하시오. 예를 들어, N=7인 경우 아래와 같이 표가 주어졌다고 하자.

이 경우에는 첫째 줄에서 1, 3, 5를 뽑는 것이 답이다. 첫째 줄의 1, 3, 5밑에는 각각 3, 1, 5가 있으며 두 집합은 일치한다. 이때 집합의 크기는 3이다. 만약 첫째 줄에서 1과 3을 뽑으면, 이들 바로 밑에는 정수 3과 1이 있으므로 두 집합이 일치한다. 그러나, 이 경우에 뽑힌 정수의 개수는 최대가 아니므로 답이 될 수 없다.

입력:

첫째 줄에는 N(1≤N≤100)을 나타내는 정수 하나가 주어진다. 그 다음 줄부터는 표의 둘째 줄에 들어가는 정수들이 순서대로 한 줄에 하나씩 입력된다.

출력:

첫째 줄에 뽑힌 정수들의 개수를 출력하고, 그 다음 줄부터는 뽑힌 정수들을 작은 수부터 큰 수의 순서로 한 줄에 하나씩 출력한다.

풀이방법:

 뽑힌 정수들이 이루는 집학과 뽑힌 정수들의 바로 밑의 둘째 줄에 들어있는 정수들이 이루는 집합이 일치한다는 것은 그 해당 정수들로 사이클이 이뤄진다는 것과 동일하다. 즉, 이 문제는 숫자 배열들 중에서 가장 큰 사이클을 찾으면 된다.

 따라서 사이클을 찾기 위해 DFS를 사용하여 문제를 풀도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from collections import defaultdict
 
def dfs(now,start):
    visited[now] = 1
    
    for n in numbers[now]:
        if not visited[n]:
            dfs(n,start)
        elif visited[n] and n==start:
            answer.append(n)
 
= int(input())
numbers = defaultdict(list)
for i in range(1,N+1):
    numbers[i].append(int(input()))
    
answer = []
for i in range(1,N+1):
    visited = [0 for _ in range(N+1)]
    dfs(i,i)
    
print(len(answer))
for i in range(len(answer)):
    print(answer[i])  
cs

문제링크:

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

 

2668번: 숫자고르기

세로 두 줄, 가로로 N개의 칸으로 이루어진 표가 있다. 첫째 줄의 각 칸에는 정수 1, 2, …, N이 차례대로 들어 있고 둘째 줄의 각 칸에는 1이상 N이하인 정수가 들어 있다. 첫째 줄에서 숫자를 적절

www.acmicpc.net

 

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

[BOJ] 17140. 이차원 배열과 연산  (0) 2021.10.19
[BOJ]2659. 십자카드 문제  (0) 2021.10.18
[BOJ] 16918. 봄버맨  (0) 2021.10.14
[BOJ] 16236. 아기 상어  (0) 2021.10.13
[BOJ] 15683. 감시  (0) 2021.10.12

문제:

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다.

 

크기가 NxN인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은 색상이라 한다.)

 

예를 들어, 그림이 아래와 같은 경우에

 

RRRBB

GGBBB

BBBRR

BBRRR

RRRRR

 

적록색약이 아닌 사람이 봤을 때 구역의 수는 총 4개이다. (빨강 2, 파랑 1, 초록 1)하지만, 적록색약인 사람은 구역을 3개 볼 수 있다. (빨강, 초록 2, 파랑 1)

 

그림이 입력으로 주어졌을 때, 적록색약인 사람이 봤을 때와 아닌 사람이 봤을 때 구역의 수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 N이 주어진다. (1<=N<=100)

둘째 줄부터 N개 줄에는 그림이 주어진다.

출력:

적록색약이 아닌 사람이 봤을 때의 구역의 개수와 적록색약인 사람이 봤을 때의 구역의 수를 공백으로 구분해서 출력한다.

풀이방법:

dfs를 사용해서 구역을 구분하는 문제인데, 적록색약인 사람과 그렇지 않은 사람을 구분하기 위해 각각 dfs 함수를 구현해 주면 된다. 그리고 또한 입력을 받을 때 G나 R을 R이나 G로 바꿔주어 적록색약인 사람들을 구분하면 된다. 이번 풀이에서는 G를 R로 바꾸었다.

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
56
import sys
sys.setrecursionlimit(100000)
 
n=int(input())
visited=[[0 for _ in range(n)] for _ in range(n)]
cvisited=[[0 for _ in range(n)] for _ in range(n)]
picture=[]
cPicture=[]
 
for _ in range(n):
    line=list(input())
    picture.append(line)
    temp=[]
    for c in line:
        if c=="G":
            c="R"
        temp.append(c)
    cPicture.append(temp)
 
dx=[1,-1,0,0]
dy=[0,0,1,-1]
def dfs1(x,y,color):
    for i in range(4):
        nx=x+dx[i]
        ny=y+dy[i]
        if 0<=nx<and 0<=ny<and picture[nx][ny]==color:
            if visited[nx][ny]==0:
                visited[nx][ny]=1
                dfs1(nx,ny,color)
 
def dfs2(x,y,color):
    for i in range(4):
        nx=x+dx[i]
        ny=y+dy[i]
        if 0<=nx<and 0<=ny<and cPicture[nx][ny]==color:
            if cvisited[nx][ny]==0:
                cvisited[nx][ny]=1
                dfs2(nx,ny,color)                
count=0
count2=0
 
for i in range(n):
    for j in range(n):
        if visited[i][j]==0:
            visited[i][j]=1
            dfs1(i,j,picture[i][j])
            count+=1
 
for i in range(n):
    for j in range(n):
        if cvisited[i][j]==0:
            cvisited[i][j]=1
            dfs2(i,j,cPicture[i][j])
            count2+=1            
        
print(count,count2)
cs

문제링크:

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

 

10026번: 적록색약

문제 적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은

www.acmicpc.net

 

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

[BOJ]6603. 로또  (0) 2020.02.11
[BOJ]1297. TV 크기  (0) 2020.02.06
[Programmers]Lv 4. 카드 게임  (0) 2020.01.23
[BOJ]1012. 유기농 배추  (0) 2020.01.21
[BOJ]10815. 숫자카드  (0) 2019.12.13

문제:

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약은 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다.

 

(한 배추의 상하좌우 네 방향에 다른 배추가 위치한 경우에 서로 인접해있다고 간주한다.)

 

한나가 배추를 재배하는 땅은 고르지 못해서 배추를 군데군데 심어놓았다. 배추들이 모여있는 곳에는 배추흰지렁이가 한 마리만 있으면 되므로 서로 인접해있는 배추들이 몇 군데에 퍼져있는지 조사하면 총 몇 마리의 지렁이가 필요한지 알 수 있다.

 

예를 들어 배추밭이 아래와 같이 구성되어 있으면 최소 5마리의 배추흰지렁이가 필요하다.

(0은 배추가 심어져 있지 않는 땅이고, 1은 배추가 심어져 있는 땅을 나타낸다.)

입력:

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 첫째 줄에는 배추를 심은 배추밭의 가로길이 M(1<=M<=50)과 세로길이 N(1<=N<=50), 그리고 배추가 심어져 있는 위치의 개수 K(1<=K<=2500)이 주어진다. 그 다음 K줄에는 배추의 위치(0<=X<=M-1),Y(0<=Y<=N-1)가 주어진다.

출력:

각 테스트 케이스에 대해 필요한 최소의 배추흰지렁이 마리 수를 출력한다.

풀이방법:

dfs를 전형적인 문제이다. 탐색을 진행하다가 1인 점을 만나게 되면(그리고 이전에 방문을 하지 않았다면) dfs 함수에 들어가서 주위에 있는 1의 위치들을 모두 방문하는 방식으로 진행하면 된다. 주위의 1을 모두 방문한 뒤에 answer를 1증가 시키며 다시 탐색을 진행하여 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
import sys
sys.setrecursionlimit(10000)
 
dx=[0,0,1,-1]
dy=[1,-1,0,0]
 
def dfs(x,y):
    for i in range(4):
        nx=x+dx[i]
        ny=y+dy[i]
        
        if 0 <= nx < M and 0 <= ny < N:
            if worm[nx][ny] and not visited[nx][ny]:
                visited[nx][ny] = True
                dfs(nx,ny)
                
T=int(input())
for _ in range(T):
    M,N,K=map(int,input().split())
    worm = [[0 for _ in range(N)]for _ in range(M)]
    visited = [[False for _ in range(N)]for _ in range(M)]
    answer = 0
    for _ in range(K):
        x,y=map(int,input().split())
        worm[x][y] = 1
 
    for i in range(M):
        for j in range(N):
            if worm[i][j] and not visited[i][j]:
                answer+=1
                visited[i][j]=True
                dfs(i,j)
 
    print(answer)
cs

문제링크:

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

 

1012번: 유기농 배추

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 효과적인 배추흰지렁이를 구입하기로 결심한다. 이 지렁이는 배추근처에 서식하며 해충을 잡아 먹음으로써 배추를 보호한다. 특히, 어떤 배추에 배추흰지렁이가 한 마리라도 살고 있으면 이 지렁이는 인접한 다른 배추로 이동할 수 있어, 그 배추들 역시 해충으로부터 보호받을 수 있다. (

www.acmicpc.net

 

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

[BOJ]10026. 적록색약  (0) 2020.02.04
[Programmers]Lv 4. 카드 게임  (0) 2020.01.23
[BOJ]10815. 숫자카드  (0) 2019.12.13
[BOJ]2033. 반올림  (0) 2019.12.12
[BOJ]10409. 서버  (0) 2019.12.09

문제:

 신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.

 예를 들어 7대의 컴퓨터가 <그림1>과 같이 네트워크 상에서 연결되어 있따고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2,3,5,6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.

  어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서  서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오,

입력:

 첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터의 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다.

출력:

 1번 컴퓨터가 웜 바이러스에 걸렸을 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 첫째 줄에 출력한다.

풀이 방법:

 1에 연결되어 있는 네트워크를 다 찾아야 하므로 깊게 계속 파고 들어가는 것 보다 너비를 우선 해서 탐색하는 편이 더 좋다. 우선 양방향으로 퍼질 수 있으므로 인덱스를 컴퓨터의 번호로 해서 리스트로 이동할 수 있는 컴퓨터를 담아두었다. 그 다음에는 answer리스트를 만들어두고 answer에는 없지만 갈 수 있는 곳이면 answer에 담고 이동을 하는 방식으로 답을 구하였다. 1번 컴퓨터를 제외한 컴퓨터의 수가 정답이므로 마지막에 1을 뺐다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
n=int(input())
virus=int(input())
computer=[[] for i in range(n+1)]
for i in range(virus):
    a,b=map(int,input().split())
    if not a in computer[b]:
        computer[b].append(a)
    if not b in computer[a]:
        computer[a].append(b)
answer=[1]
def bfs(now):
    global answer
    for i in computer[now]:
        if not i in answer:
            answer.append(i)
            bfs(i)
bfs(1)
print(len(answer)-1)
cs


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

[BOJ]2075. N번째 큰 수  (0) 2019.07.23
[BOJ] 11279,1927,11286 최대힙,최소힙,절대값 힙  (0) 2019.07.21
[BOJ]1260. DFS와 BFS  (0) 2019.07.19
[BOJ]2164. 카드2  (0) 2019.07.18
[BOJ]4949. 균형잡힌 세상  (0) 2019.07.17

문제:

그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문하고, 더 이상 방문할 수 있는 점이 없는 경우 종료한다. 정점 번호는 1번부터 N번까지이다.

입력:

첫째 줄에 정점의 개수 N(1<=N<=1,000), 간선의 개수 M(1<=M<=10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.

출력:

첫째 줄에 DFS를 수행한 결과를, 그 다음 줄에는 BFS를 수행한 결과를 출력한다. V부터 방문된 점을 순서대로 출력하면 된다.

풀이 방법:

양방향으로 이동가능이 하므로 2중배열로 만들어서 경로를 저장했다. 인덱스가 출발하는 정점이고 그 안에 들어있는 값들은 도착하는 정점이다.
DFS는 지금 마지막으로 들어온 정점이 중요하므로 그 정점이 가지고 있는 경로 중에 지나지 않은 곳으로 다시 들어가는 재귀방식으로 짜주면 된다.
BFS는 계속해서 배열을 누적하는 방식으로 진행했다. BFS에 계속 담아두고 반복문으로 하나하나 탐색하며 방문하지 않은 정점으로 이동하는 방식으로 진행했다. BFS에는 예외처리 구문이 들어가 있다. 왜냐하면 처음에는 없이 했더니 런타임에러가 발생하게 되었고, 그 이유를 알아보니 시작하는 정점이 1이라고 줬지만 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
n,m,V=map(int,input().split())
path=[[]for i in range(n+1)]
for i in range(m):
    a,b=map(int,input().split())
    if not a in path[b]:
        path[b].append(a)
    if not b in path[a]:
        path[a].append(b)
for p in path:
    p.sort()
 
DFS=[]
def dfs(now):
    DFS.append(now)
    for i in path[now]:
        if i in DFS:
            continue
        dfs(i)
    return
dfs(V)
print(*DFS)
def bfs(now):
    global BFS
    temp=[]
    if len(now)==n:
        return
    try:
        for i in now:
            for j in path[i]:
                if not j in BFS:
                    BFS.append(j)
        bfs(BFS)
    except:
        return
    return
BFS=[V]
bfs(BFS)
print(*BFS)
cs


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

[BOJ] 11279,1927,11286 최대힙,최소힙,절대값 힙  (0) 2019.07.21
[BOJ]2606. 바이러스  (0) 2019.07.20
[BOJ]2164. 카드2  (0) 2019.07.18
[BOJ]4949. 균형잡힌 세상  (0) 2019.07.17
[BOJ]2004. 조합 0의 개수  (0) 2019.07.16

+ Recent posts