티스토리 뷰

문제
9466번: 텀 프로젝트
이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을
www.acmicpc.net
문제 상황
- 주어진 리스트의 부분 사이클을 구해 팀을 구성하고, 팀이 없는 학생 수를 구한다.
해결 전략
- 재귀보다는 반복을 통해 구한다. 내 방법으로는 조건을 통해 사이클이 되는지 안되는지를 확인하는 알고리즘을 사용하여 만약 부분적으로 사이클을 이룬다면 그 부분만 사이클이 된다고 표시하고 넘어가는 방식을 택한 후 사이클에 포함 안되는 요소의 개수를 찾았다. 하지만 이 방식으로는 속도 이슈가 발생하였다.
- 다른 블로그를 참고하여 얻은 방법은 우선 사이클을 계속 찾아 들어간 후 마지막을 만났을 때, 다시 그 부분부터 역순으로 돌아가며 사이클을 이루는 부분을 찾는다. 즉, 사이클을 이루기 때문에 사이클의 어느 시점에서 시작하여도 한바퀴를 돌 수 있다는 특징을 이용하였다.
코드
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
|
# 통과 코드
from sys import stdin
input = stdin.readline
for _ in range(int(input())):
n = int(input()) # 학생들의 수
n_list = [0] + list(map(int, input().split()))
in_group = [0]*(n+1)
group = 1
for i in range(1, n+1):
if in_group[i] == 0:
while in_group[i] == 0 : # 사이클을 만날 때 까지 반복
in_group[i] = group # 그룹 번호를 부여
i = n_list[i]
while in_group[i] == group : # 완성된 사이클을 역순으로 반복
in_group[i] = -1 # 사이클을 이루면 -1을 할당
i = n_list[i]
group += 1
cnt = 0
for i in range(1, n+1):
if in_group[i] > 0 : cnt+=1
print(cnt)
# 속도 이슈 코드
from sys import stdin
input = stdin.readline
def dfs(start, n_list):
temp = [start]
while True:
check_node = temp[-1]
target_node = n_list[check_node]
if target_node == start: # 연결고리가 돌아서 start와 같다면
for i in range(len(temp)):
in_group[temp[i]] = True
break
elif target_node not in temp:
temp.append(target_node)
elif target_node in temp:
break
for _ in range(int(input())):
n = int(input()) # 학생들의 수
n_list = [0] + list(map(int, input().split()))
in_group = [True] + [False]*(n)
for i in range(1, n+1):
if in_group[i] is False:
dfs(i,n_list)
print(in_group.count(False))
|
cs |
해설
- 속도 이슈 발생은 조건을 확인한 후, 조건에 만족하면 그때 in_group 체크 리스트를 갱신하는 방향으로 하였지만 여기에서 속도 이슈가 발생하는 듯 하다.
- 더 좋은 방법은 사이클의 특성을 이용해 갱신할 때 일일이 목록을 저장해두는 것이 아니라 마지막 시점부터 다시 돌면서 사이클 여부를 갱신하는 것이다.
- 속도 이슈코드는 O(N^3) 이고 통과 코드는 while구문이 병렬로 되어있어 O(N^2)로 해결 가능하다.
새로 학습한 것 & 실수
- 체크를 할 때, 내용을 저장해두고 갱신하는 방법도 있지만 전체 사이클에서 일부분을 찾는 문제의 경우 마킹을 해두고 그 마킹을 검색하며 조건을 만드는 것도 방법이다.
'알고리즘 학습 > 백준 알고리즘' 카테고리의 다른 글
백준 알고리즘 - 토마토 (7576) [Python] (0) | 2020.10.08 |
---|---|
백준 알고리즘 - 섬의 개수 (4963) [Python] (0) | 2020.10.07 |
백준 알고리즘 - 반복수열 (2331) [Python] (0) | 2020.10.07 |
백준 알고리즘 - 순열 사이클 (10451) [Python] (0) | 2020.10.06 |
백준 알고리즘 - 제곱수의 합 (1699) [Python] (0) | 2020.09.21 |
- Total
- Today
- Yesterday
- 파이썬알고리즘인터뷰#4장
- 백준 알고리즘#BackTracking
- API#lazy#
- NumberofDiscIntersections#Codility#Sort#Python
- django#slicing
- 날짜 계산#BOJ#완전탐색#Python
- filter#isalnum#lower
- Distinct#Codility#Python
- 토마토#백준알고리즘#Python
- PassingCars#Codility#Python
- 배열합치기#분할정복#BOJ#Python
- 종이자르기#분할정복#BOJ#Python
- 미로 탐색#백준알고리즘#Python
- 쿼드트리#BOJ#분할정복#Python
- Swift#Tuples#Range
- Brackets#Stacks and Queues#Codility#Python
- django
- 암호코드#dp#BOJ#Python
- N으로 표현#DP#Programmers#Python
- 리모컨#완전탐색#BOJ#Python
- Triangle#Sorting#Codility#Python
- 나무자르기#BOJ#이분탐색#Python
- 병든 나이트#BOJ#탐욕법#Python
- 텀 프로젝트#백준알고리즘#Python
- 섬의개수#백준알고리즘#Python
- 랜선자르기#이분탐색#BOJ#Python
- 순열사이클#BOJ#Python
- 반복수열#백준알고리즘#Python
- 공유기 설치#BOJ#이분탐색#Python
- 터틀비치#리콘#xbox#controller
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |