첫 줄에 n, m이 주어지고 m은 입력으로 주어지는 연산의 개수를 의미한다. 합집합은 0 a b로 입력이 주어지고 이는 a가 포함된 집합과 b가 포함된 집합을 합친다는 의미이다.
두 원소가 같은 집합에 포함되어 있는지 확인하는 연산은 1 a b로 주어지고 a와 b가 같은 집합에 포함되었으면 yes를 아니면 no를 출력하는 문제
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
n, m = map(int, input().split())
parent = [i for i in range(n+1)]
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(a, b):
a = find(a)
b = find(b)
if a < b:
parent[b] = a
else:
parent[a] = b
for i in range(m):
value, a, b = map(int, input().split())
if value == 0:
union(a, b)
else:
if find(a) == find(b):
print('yes')
else:
print('no')
< 풀이 과정 >
주어진 m개의 연산에 0의 개수만큼 집합을 생성해야 하는데 같은 집합인지 여부를 판단해주기 위해 union - find 알고리즘을 사용하였다.
n개의 탑이 주어지고 각 탑을 기준으로 왼쪽에 있는 현재 탑보다 크다면 해당 탑이 몇번째 탑인지 출력하는 문제
import sys
input = sys.stdin.readline
n = int(input())
tower = list(map(int, input().split()))
stack = []
answer = []
for i in range(n):
while stack:
if stack[-1][1] > tower[i]:
answer.append(stack[-1][0] + 1)
break
else:
stack.pop()
if not stack:
answer.append(0)
stack.append((i, tower[i]))
print(*answer)
< 풀이 과정 >
주어진 n의 범위가 1 이상 500,000 이하이므로, 2중 for문은 사용하게 되면 시간 복잡도를 해결하지 못해 stack으로 구현하였다.
stack과 answer를 빈 리스트로 만들어주고 for문으로 타워의 인덱스를 돌며 stack에 타워인덱스, 타워 높이를 append해준다.
while 문으로 스택이 비어있지 않으면 타워 기준 왼쪽이 더 높으면 answer에 타워 인덱스 + 1을 넣어준다. 아닌 경우 stack 원소를 pop한다.
만일 stack이 비어있지 않으면 answer에 0을 넣어준다.
첫 줄에 N이 주어지고 N줄에 0 이상 9 이하 숫자가 세개씩 적혀있다. 즉 NX3 크기의 그래프에서 맨 윗줄에서 시작해 아래 줄로 내려가면서 값을 더해줄 때 맨 아래줄의 최대값과 최소값을 구하는 문제. 이때 내려가는 조건은 다음 2가지이다.
- 바로 아래 수로 넘어가기 or 아래 수와 붙어있는 수로만 이동이 가능하다.
import sys
input = sys.stdin.readline
n = int(input())
graph = list(map(int, input().split()))
max_dp = graph
min_dp = graph
for _ in range(n-1):
a, b, c = map(int, input().split())
max_dp = [a + max(max_dp[0], max_dp[1]), b + max(max_dp), c + max(max_dp[1], max_dp[2])]
min_dp = [a + min(min_dp[0], min_dp[1]), b + min(min_dp), c + min(min_dp[1], min_dp[2])]
print(max(max_dp), min(min_dp))
< 풀이 과정 >
주어진 graph를 타고 내려가서 가장 아래 줄의 최대값을 찾기 위한 그래프 max_dp와 최소값을 찾기 위한 그래프 min_dp를 2차원으로 미리 만들고 시작하면 메모리 초과가 발생하는 문제.
따라서 주어진 초기값만 저장하기 위해 graph로 첫 행만 입력받고 max_dp와 min_dp를 graph로 저장을 한다.
이후 for문으로 나머지 행 길이 n-1만큼 돌며 a, b, c 3개의 값을 입력받아 max_dp와 min_dp를 주어진 조건에 맞게 update하면 해결된다.
새 집의 크기는 nXn의 격자판으로 나타낼 수 있고 r은 행 번호, c는 열 번호를 뜻하고 파이프는 2칸을 차지한다. 파이프는 항상 빈 칸만을 차지해야 하며 파이프를 밀 수 있는 방향은 →, ↘, ↓ 로 3가지이다. 가장 첫 파이프는 (1,1), (1,2)를 차지하고 있을 때 파이프의 한 쪽 끝을 n,n으로 이동시키는 방법의 개수를 구하는 문제
주어진 그래프에서 빈 칸은 0, 벽은 1로 주어지고 가능한 방법의 개수가 없으면 0을 출력한다.
추가로 다음과 같은 경우에만 파이프를 밀 수 있다.
- → : →, ↘
- ↓ : ↓, ↘
- ↘ : →, ↓, ↘
import sys
input = sys.stdin.readline
n = int(input())
graph = [list(map(int, input().split())) for _ in range(n)]
answer = 0
def solution(i, j, direction):
global answer
# 도착 여부
if i == n-1 and j == n-1:
answer += 1
return answer
# 현재 파이프 상태 가로
if direction == 0 or direction == 2:
if j+1 < n and graph[i][j+1] == 0:
solution(i, j+1, 0)
# 현재 파이프 상태 세로
if direction == 1 or direction == 2:
if i+1 < n and graph[i+1][j] == 0:
solution(i+1, j, 1)
# 파이프 상태 대각선
if i+1 < n and j+1 < n:
if graph[i+1][j] == 0 and graph[i][j+1] == 0 and graph[i+1][j+1] == 0:
solution(i+1, j+1, 2)
if graph[n-1][n-1] == 1:
print(0)
else:
solution(0, 1, 0)
print(answer)
< 풀이 과정 >
bfs로는 도저히 시간초과를 벗어날 수 없고, dfs 재귀를 이용하여 해결한 풀이 (pypy)
문제 해결 방법은 DP이지만 DP로는 대각선을 어떤 방식으로 표현해야 해결할 지 모르겠어서 dfs를 활용하였다.
최종적으로 현재 파이프의 끝점이 (1,2)이므로 pipe(0, 1, 0)을 넣어 answer를 리턴한다.