본문 바로가기

알고리즘/Baekjoon

[BOJ] 2668 숫자고르기 Python (복습 필요)

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

 

2668번: 숫자고르기

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

www.acmicpc.net

숫자고르기

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 13024 5660 4469 45.260%

문제

세로 두 줄, 가로로 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)을 나타내는 정수 하나가 주어진다. 그 다음 줄부터는 표의 둘째 줄에 들어가는 정수들이 순서대로 한 줄에 하나씩 입력된다.

출력

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

예제 입력 1 복사

7
3
1
1
5
5
4
6

예제 출력 1 복사

3
1
3
5

풀이 (틀린 풀이 _ 백트래킹)

import sys
input = sys.stdin.readline

n = int(input())
# 2차원 리스트 (인덱스 0은 윗줄, 1은 아랫줄)
graph = [[i] for i in range(n+1)]
for i in range(1, n+1):
    graph[i].append(int(input()))

visited = [False]*(n+1)
answer = -1e9
answer_list = []
def dfs(upper, lower):
    global answer, answer_list

    if len(upper) != 0:
        flag = True
        for i in range(0, len(upper)):
            if upper[i] not in lower:
                flag = False
                break

        if flag == True:
            if answer < len(upper):
                answer_list = upper
            answer = max(len(upper), answer)

    for i in range(1, n+1):
        if not visited[i]:
            visited[i] = True
            dfs(upper+[i], lower+[graph[i][1]])
            visited[i] = False

dfs([], [])
print(answer)
answer_list.sort()
for i in answer_list:
    print(i)

처음에 단순 백트래킹으로 풀었다.

하지만 시간초과로 실패 ㅠㅠ

 

풀이 (정답 참고 _ 사이틀 이용)

첫째줄, 둘째줄의 연결된 그래프로 생각하고 정답 후보들을 살펴보면 사이클을 형성하는 것을 알 수 있다.

 

참고 : https://jjunohj.github.io/boj/boj-2668/

 

[BOJ] 백준 2668번 - 숫자고르기 (Python)

Gold 5

jjunohj.github.io

참고 : https://jjunohj.github.io/boj/boj-2668/
참고 : https://jjunohj.github.io/boj/boj-2668/
참고 : https://jjunohj.github.io/boj/boj-2668/

# 입력
n = int(input())
graph = [[] for i in range(n + 1)]

for i in range(1, n + 1):
  graph[i].append(int(input()))


def dfs(s):
  global result, cnt

  visited[s] = True # 방문 처리
  for now in graph[s]:
    # 방문 안했을 경우 방문, 재귀
    if visited[now] == False:
      dfs(now)
    # 방문했는데 안끝났을 경우, 역방향 간선 확인
    elif visited[now] == True and finished[now] == False:
      if now not in result: # result에 중복 삽입 방지
        cnt += 1
        result.append(now)
        return
    else:
      return
  finished[s] = True # 함수 종료


result = []
cnt = 0

# 각각의 노드마다 루트 노드로서 반복해주어야 한다.
for i in range(1, n + 1):
  visited = [False] * (n + 1)
  finished = [False] * (n + 1)
  dfs(i)

result.sort()
print(cnt)
for i in result:
  print(i)

(코드 복습 필요)

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

[BOJ] 18111 마인크래프트 Python (복습 필요)  (0) 2023.02.14
[BOJ] 2468 안전 영역 Python  (0) 2023.02.12
[programmers] 여행경로 Python  (0) 2023.02.08
[BOJ] 상범 빌딩 Python  (0) 2023.02.08
[BOJ] 2660 회장뽑기 Python  (0) 2023.02.07