from collections import deque
N,M = map(int,input().split())
graph = [[] for _ in range (0,N+1)]
ind = [0 for _ in range (0,N+1)]
for _ in range (0,M):
a,b = map(int,input().split())
graph[a].append(b)
ind[b] += 1
deq = deque()
for i in range (0,N+1): #진입차수가 0인 친구들 먼저 추가 (끝에 있는 친구들부터)
if ind[i] == 0:
deq.appendleft(i)
ans = []
while deq:
x = deq.popleft()
if x == 0:
break
ans.append(x)
for j in range (0,len(graph[x])):
ind[graph[x][j]] -= 1
if ind[graph[x][j]] == 0:
deq.appendleft(graph[x][j])
answer = " ".join(str(s) for s in ans)
print(answer)
역시 주요한 아이디어는, Indegree가 0인 노드를 추가하면서 (이 친구가 시작점이 되기 때문)
그 노드에서 이어진 Node들의 indegree를 1씩 줄여가며 찾아내가는 방법이 되겠다.
from collections import defaultdict
N = int(input())
d = defaultdict(int)
for i in range (0,12):
d[chr(i + 65)] = 0 #각각의 인덱스 저장
cant_zero = []
for i in range (0,N):
s = input() #입력되는 문자
n = len(s)
for j in range (0,n):
if j == 0:
cant_zero.append(s[j])
d[s[j]] += 10 ** (n - 1 - j)
spell = []
for i in range (0,12):
if d[chr(i + 65)] != 0:
spell.append([chr(i+65) , d[chr(i + 65)]])
spell.sort(reverse = True, key = lambda x: x[1])
can_zero = []
revised = []
for i in range (0,len(spell)):
if spell[i][0] in cant_zero:
revised.append(spell[i])
else:
can_zero.append(spell[i])
if len(revised) <= 9:
for i in range (0,len(can_zero)):
revised.append(can_zero[i])
if len(revised) <= 9:
for j in range (0,9):
revised.append([0,0])
revised = revised[0:9]
revised.sort(reverse= True, key = lambda x : x[1])
ans = 0
for i in range (0,9):
ans += revised[i][1] * (9-i)
print(ans)
골드 3 문제였는데, 꽤 그래도 재밌게 풀은 느낌이 든다.
도중 몇가지 작업이 필요가 없을 수도 있었는데, 일단은 굉장히 빠르게 해결할 수 있었으니 ... 일단은 만족하는 것으로.
가장 중요한 아이디어 중 하나는, 0이 될 수 없는 문자들을 미리 분류해두고 우선순위에 둘 필요가 있는 것이다.
이 알고리즘에서는 알파뱃들을 총 2번에 걸쳐서 필터링을 하였다.
첫번째로, spell 리스트에서의 for문인데, 여기서 0이 될 수 없는 것들을 우선적으로 revised라는 리스트에 넣어줄 필요성이 있었다.
두번째로, if len(revised)에서, 길이를 강제로 9로 만들어주는 방법을 취하였다.
from collections import deque
from itertools import combinations
import copy
N,M = map(int,input().split())
block = []
empty = []
virus = []
for i in range (0,N):
A = list(map(int,input().split()))
for j in range (0,M):
if A[j] == 0:
empty.append([i,j])
if A[j] == 2:
virus.append([i,j])
block.append(A)
ans = 0
for x in combinations(empty,3):
cnt = 0
x = list(x)
B = copy.deepcopy(block)
B[x[0][0]][x[0][1]],B[x[1][0]][x[1][1]], B[x[2][0]][x[2][1]] = 1,1,1
dx,dy = [0,0,-1,1],[1,-1,0,0]
deq = deque()
for i in range (0,len(virus)):
deq.appendleft(virus[i])
while deq:
y = deq.popleft()
for i in range (0,4):
z = y[0] + dx[i]
w = y[1] + dy[i]
if 0 <= z < N and 0 <= w < M and B[z][w] == 0:
B[z][w] = 2
deq.append([z,w])
for i in range (0,N):
for j in range (0,M):
if B[i][j] == 0:
cnt += 1
ans = max(ans,cnt)
print(ans)
생각보다 클린코드가 나와서 좋았던 것 같습니다.
바이러스가 옮겨질 조건은, 아무것도 없는 0인 공간에 한하므로, B[z][w]에서 적절하게 이용하면 좋을 것 같습니다.
결국 벽 3개라는 조건이 주어졌으므로, 브루트포스를 통해서 문제를 해결할 수 있었습니다.
문제를 살짝 응용한다면, 벽 하나를 세우는데 cost가 들 때, 최적의 cost - safety area를 컨트롤 하는 방법도 있겠습니다.
오히려 이쪽이 더 재밌을 것 같은 느낌이네요. 대신 이렇게 된다면 난이도는 조금 더 올라갈지도 ... ?
from collections import deque
N,K = map(int,input().split())
deq = deque()
for i in range (1,N+1):
deq.append(i)
cnt = 1
ans = []
while deq:
x = deq.popleft()
if cnt % K == 0:
ans.append(x)
else:
deq.append(x)
cnt += 1
s = "<" + ", ".join(str(t) for t in ans) + ">"
print(s)
여기서 키워드인것은 인원수가 각각 100,000이므로, 아무리 봐도 O(log N)에서 해결해야한다는 것을 알 수 있다.
아이디어로 사용한 것은
hi / arc 팀을 점수로 정렬한 뒤, 점수별 인원을 defaultdict에 저장해서 나중에 불러오는 형식으로 알고리즘을 짰습니다.
점수로 정렬한 이유는, 이진탐색을 하기 위함입니다.
i) 기본적인 셋팅
먼저, hi, arc에 주어진 list를 아래와 같이 둡니다.
hi = [1,3,7,1,7], arc = [2,2,6,10,6]
#28449 누가 이길까
import sys
from collections import defaultdict
N,M = map(int,input().split())
total = N * M
hi = list(map(int,input().split()))
arc = list(map(int,input().split()))
hi_dict = defaultdict(int)
arc_dict = defaultdict(int)
for i in range (0,N):
hi_dict[hi[i]] += 1
for i in range (0,M):
arc_dict[arc[i]] += 1
#hi, arc로 덮어 씌우기
hi = list(hi_dict.keys())
arc = list(arc_dict.keys())
#크기로 조절하기
hi.sort()
arc.sort()
#arc팀의 인원 순서대로 카운팅하기
N,M = len(hi),len(arc)
arc_people = [0]
for i in range (0,M):
x = arc_people[i] + arc_dict[arc[i]]
arc_people.append(x)
그렇다면 arc_people의 리스트는
arc_people = [0,2,4,5] 가 되겠군요 !
문제에서 활용할 이진 탐색은 이하와 같습니다.
#위치 찾는 인덱스 변환
def binary_search(x,A):
start,end = 0,len(A)-1
while start <= end:
mid = (start + end) // 2
if A[mid] == x:
return mid
elif A[mid] < x:
if A[mid] <= x < A[mid + 1]:
return mid
else:
start = mid
else:
if A[mid -1] <= x < A[mid]:
return mid - 1
else:
end = mid
아이디어는 이하와 같습니다.
hi[i]가 arc[j]에서 몇번째 인덱스에 있을까? 라는 것입니다
즉, arc[j] <= hi[i] < arc[j+1] 꼴이 되는 j는 무엇인가? 라는 알고리즘이 되겠습니다.
물론, 일부 경우를 제거해야합니다.
예를 들어, hi[i] <= arc[0] 이거나, hi[i] >= arc[-1]라면 위의 이진탐색 알고리즘을 사용하지 못하겠습니다.
이 경우는, 따로 케이스를 구분해서 계산해주도록 합니다.
#이진탐색 알고리즘 적용
win,draw = 0,0
for i in range (0,N):
if hi[i] < arc[0]:
#아무것도 못함
continue
elif hi[i] == arc[0]:
#비기는 것만 가능
draw += hi_dict[hi[i]] * (arc_people[1] - arc_people[0])
elif hi[i] == arc[-1]:
#마지막 인덱스를 제외하고 전부 승리, 마지막 인덱스에서는 비김
draw += hi_dict[hi[i]] * (arc_people[-1] - arc_people[-2])
win += hi_dict[hi[i]] * arc_people[-2]
elif hi[i] > arc[-1]:
#모든 인원들을 이길 수 있다는 뜻
win += hi_dict[hi[i]] * arc_people[-1]
else:
#hi 값이 arc내에서 부등식 꼴로 나타낼 수 있다는 것
x = binary_search(hi[i],arc)
if arc[x] < hi[i]:
win += hi_dict[hi[i]] * arc_people[x+1]
else:
win += hi_dict[hi[i]] * arc_people[x]
draw += hi_dict[hi[i]] * (arc_people[x+1] - arc_people[x])
print(win,total -(win + draw),draw)
마지막 알고리즘으로 들어왔습니다.
hi[i]가 이기는게 몇번인지, 비기는게 몇번인지 카운팅 해줍니다. 지는 것은 전체 경우에는 앞의 두개를 빼주면 나옵니다. (total - win - draw)
i) hi[i]가 "arc[0]보다 작은 경우"
hi[i]는 아무도 코딩으로 이길 수 없습니다. pass 합니다.
ii) hi[i]가 "arc[0]과 같은 경우"
hi[i]는 arc[0]과 비기는 방법 밖에 없습니다.
draw만 추가가 되겠습니다.
iii) hi[i]가 "arc[-1] 보다 큰 경우"
hi[i]는 arc팀의 모든 인원들을 이길 수 있습니다.
win에만 추가가 되겠습니다.
iv) hi[i]가 "arc[-1]과 같은 경우"
hi[i]는 arc[-1] - arc[-2]명의 사람들에게는 비기지만, 그 외에 사람들에게는 전부 이깁니다.
win, draw 같이 올라갑니다.
v) 그 외
arc[j] <= hi[i] < arc[j +1]가 되는 j를 이분탐색을 통해 찾았습니다.
만약 arc[j] = hi[i]라면, win과 draw가 같이 올라가겠습니다
arc[j] < hi[i]라면, win에만 인원수를 추가해주면 되겠습니다.
전체 코드는 이하와 같습니다.
#28449 누가 이길까
import sys
from collections import defaultdict
N,M = map(int,input().split())
total = N * M
hi = list(map(int,input().split()))
arc = list(map(int,input().split()))
hi_dict = defaultdict(int)
arc_dict = defaultdict(int)
for i in range (0,N):
hi_dict[hi[i]] += 1
for i in range (0,M):
arc_dict[arc[i]] += 1
#hi, arc로 덮어 씌우기
hi = list(hi_dict.keys())
arc = list(arc_dict.keys())
#크기로 조절하기
hi.sort()
arc.sort()
#hi,arc팀의 인원 순서대로 카운팅하기
N,M = len(hi),len(arc)
arc_people = [0]
for i in range (0,M):
x = arc_people[i] + arc_dict[arc[i]]
arc_people.append(x)
#위치 찾는 인덱스 변환
def binary_search(x,A):
start,end = 0,len(A)-1
while start <= end:
mid = (start + end) // 2
if A[mid] == x:
return mid
elif A[mid] < x:
if A[mid] <= x < A[mid + 1]:
return mid
else:
start = mid
else:
if A[mid -1] <= x < A[mid]:
return mid - 1
else:
end = mid
#이진탐색 알고리즘 적용
win,draw = 0,0
for i in range (0,N):
if hi[i] < arc[0]:
#아무것도 못함
continue
elif hi[i] == arc[0]:
#비기는 것만 가능
draw += hi_dict[hi[i]] * (arc_people[1] - arc_people[0])
elif hi[i] == arc[-1]:
#마지막 인덱스를 제외하고 전부 승리, 마지막 인덱스에서는 비김
draw += hi_dict[hi[i]] * (arc_people[-1] - arc_people[-2])
win += hi_dict[hi[i]] * arc_people[-2]
elif hi[i] > arc[-1]:
#모든 인원들을 이길 수 있다는 뜻
win += hi_dict[hi[i]] * arc_people[-1]
else:
#hi 값이 arc내에서 부등식 꼴로 나타낼 수 있다는 것
x = binary_search(hi[i],arc)
if arc[x] < hi[i]:
win += hi_dict[hi[i]] * arc_people[x+1]
else:
win += hi_dict[hi[i]] * arc_people[x]
draw += hi_dict[hi[i]] * (arc_people[x+1] - arc_people[x])
print(win,total -(win + draw),draw)
import math
N,M = map(int,input().split())
A = list(map(int,input().split()))
num = []
for i in range (1,1050):
if i not in A:
num.append(i)
m = len(num)
val = 1e9
for i in range (0,m):
if num[i] ** 3 > N + val:
break
for j in range (i,m):
for k in range (j,m):
val = min(val, int(math.fabs(N - num[i] * num[j] * num[k])))
print(val)
브루트포스로 계산하지만, 시간을 어떻게 더 단축할 수 있을지가 관건이었던 문제
추가 기재)
import math
N,M = map(int,input().split())
A = list(map(int,input().split()))
num = []
for i in range (1,1050):
if i not in A:
num.append(i)
m = len(num)
val = 1e9
for i in range (0,m):
if num[i] ** 3 > N + val:
break
for j in range (i,m):
if num[i] * num[j] * num[j] > N + val:
break
for k in range (j,m):
val = min(val, int(math.fabs(N - num[i] * num[j] * num[k])))
print(val)
for j 에 있어서도 같이 제한 조건을 넣어줌으로서 훨씬 연산이 빨라진 것을 확인할 수 있었다 !
from collections import deque
N= int(input())
picture1 = [[] for _ in range (0,N)]
picture2 = [[] for _ in range (0,N)]
for i in range (0,N):
a = list(input())
for j in range (0,N):
if a[j] == "B":
picture1[i].append(a[j])
picture2[i].append(a[j])
else:
picture1[i].append(a[j])
picture2[i].append("G") #R이 G가 된다고 생각하자.
visited1 = [[False for _ in range (0,N)] for _ in range (0,N)]
visited2 = [[False for _ in range (0,N)] for _ in range (0,N)]
dx,dy = [0,0,1,-1],[1,-1,0,0]
cnt1,cnt2 = 0,0
for i in range (0,N):
for j in range (0,N):
if visited1[i][j] == False:
cnt1 += 1
deq = deque()
deq.appendleft([i,j])
while deq:
x = deq.popleft()
visited1[x[0]][x[1]] = True
for k in range (0,4):
a = x[0] + dx[k]
b = x[1] + dy[k]
if 0 <= a < N and 0 <= b < N and visited1[a][b] == False and picture1[a][b] == picture1[x[0]][x[1]]:
deq.appendleft([a,b])
if visited2[i][j] == False:
cnt2 += 1
deq = deque()
deq.appendleft([i,j])
while deq:
x = deq.popleft()
visited2[x[0]][x[1]] = True
for k in range (0,4):
a = x[0] + dx[k]
b = x[1] + dy[k]
if 0 <= a < N and 0 <= b < N and visited2[a][b] == False and picture2[a][b] == picture2[x[0]][x[1]]:
deq.appendleft([a,b])
print(cnt1,cnt2)
from collections import deque
M,N,H = map(int,input().split())
cnt = 0
deq = deque() #다 익은 애들 deq에 넣어서 해결
box = [[[0 for _ in range (0,M)] for _ in range (0,N)] for _ in range (0,H)]
for i in range (0,H): #높이 정보
floor_box = []
for j in range (0,N): #가로 정보
A = list(map(int,input().split()))
for k in range (0,len(A)):
box[i][j][k] = A[k]
if A[k] == 0: #안 익은애들
cnt += 1
if A[k] == 1:
deq.append([i,j,k])
dx,dy,dz = [1,-1,0,0,0,0], [0,0,1,-1,0,0], [0,0,0,0,1,-1]
if cnt == 0:
print(0)
if cnt != 0:
day = 0
while True:
if cnt == 0:
print(day)
break
if len(deq) == 0:
print(-1)
break
day += 1
tomato = []
while deq:
a = deq.popleft() #list의 형태로 출력됨
for i in range (0,6):
z,y,x = a[0] + dx[i], a[1] + dy[i], a[2] + dz[i]
if 0 <= x < M and 0 <= y < N and 0 <= z < H and box[z][y][x] == 0:
box[z][y][x] = 1
tomato.append([z,y,x])
cnt -= 1
for i in range (0,len(tomato)):
deq.append(tomato[i])