[백준 2668] - 숫자 고르기(C++)

2022. 11. 17. 17:45· CodingTest/Baekjoon
목차
  1. 🔎문제 해석
  2. 📃코드 단계
  3. 💻코드
  4. ✔느낀 점

📕문제


세로 두 줄, 가로로 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로 풀어야 한다는 것을 감을 잡았다면 여러분은 DFS, BFS를 많이 풀어봤다는 뜻입니다.

하지만 다른 DFS문제랑은 조금은(?) 다르다는 것을 알아야 합니다. 

 

예시를 testcase로 잡고 설명해보겠습니다.

아래의 입력이 Testcase입니다.

1 2 3 4 5 6 7
3 1 1 5 5 4 6
  1. 조합이 일치하는 최대의 수를 뽑아야 하는 것이 문제의 목표입니다. (1번부터 시작한다고 가정)
  2. 1번은 아래의 숫자가 3이다.
  3. 그럼 우리는 위의 숫자중 3번을 타고 들어가서 3번 아래의 숫자가 1인지를 확인해야 한다. 
    • 1이라면 다시 되돌아갈수 있으므로, 조합에 1과 3을 추가하면 된다.
    • 만약 1이 아니라 다른 숫자라면? 2번과 3번 과정을 다시 거쳐서 확인을 해야 한다.

즉 쉽게 설명하면 배열[i] -> 배열[배열[i]] -> 배열[배열[배열[i] ] ] -> 쭉쭉 가다 보면 방문했던 숫자에 다시 방문하게 되는 경우가 발생할 것입니다. 방문했던 숫자에 다시 방문한다면 그때가 적절한 조합입니다.

 

💡예를 들어서

  1. 1번 시작 :1->3->1->3 == (1,3)은 적절한 조합입니다!
  2. 2번 시작:  2->1->3->1->3->1 == 2번으로 되돌아가지 못하고, 1,3번은 각각 되돌아가기에 (1,3)이 추가됩니다.
  3. 3번 시작 : 3->1->3->1이기 때문에 (1,3)이 추가
  4. 4번 시작 : 4->5->5->5이기 때문에 (5) 추가
  5. 5번 시작 : 5->5이기 때문에 (5) 추가
  6. 6번 시작 : 6->4->5->5->5이기 때문에 (5) 추가
  7. 7번 시작 : 7->6->4->5->5->5이기 때문에 (5) 추가 

💡또 다른 예로는 

1 2 3
2 3 1
  1. 1번 시작 : 1->2->3->1->2->3  (1,2,3) 추가
  2. 2번 시작 : 2->3->1->2->3->1 (1,2,3) 추가
  3. 3번 시작 : 3->1->2->3->1->2 (1,2,3) 추가

추가할 때는 중복을 원하지 않았기 때문에 map에다 각 원소를 넣어줬다.

(지금 생각해보면 굳이 map 아니고 set에 넣어도 됐을 거은,,,)

 

📃코드 단계

  • 모든 좌표에 대해서 dfs를 실행합니다.
  • 출발 좌표에서 dfs로 탐색하여 방문했던 숫자에 다시 방문했을 경우, 다시 출발 좌표로 되돌아 오는지를 체크한다.
    • 다시 출발 좌표로 돌아왔다면 따로 check해서, 그때 호출 내에서 방문했던 숫자들을 map에 추가한다.
    • 다시 출발좌표로 돌아오지 못한 경우는 같은 조합을 만들어내지 못하는 숫자 조합이기에 추가하지 않는다.

 

💻코드

/*
골드5 2688 숫자 고르기
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
using namespace std;
int n, C = 0, result = 0;
vector<int> graph;
vector<int> visit;
map<int, int> m;
bool check;
void dfs(int x, int fx);
int main()
{
cin >> n;
graph.resize(n + 1, 0);
visit.resize(n + 1, 0);
for (int i = 1; i <= n; i++)
{
cin>>graph[i];
}
for (int i = 1; i <= n; i++)
{
visit[i] = 1; //현재 탐색 좌표 방문 처리
dfs(i, graph[i]);
visit.assign(n + 1, 0); //방문 초기화
check = false; // 초기화
}
cout << m.size() << endl;
for (auto a : m)
{
cout << a.first << endl;
}
}
void dfs(int x, int fx)
{
if (visit[fx])
{ //이미 방문했다면
if (x == fx) //다시 되돌아갔다면
{
check = true; //check를 true로 바꿔줌
m.insert(make_pair(fx, 0)); //그때의 값을 map에다 넣어줌.
}
return; //다시 돌아가지 않았따면
}
//방문안햇다면
visit[fx] = 1;
dfs(x, graph[fx]);
if (check) //만약 dfs를 탈출했을때 check가 true라면, 두 좌표는 조합이 일치하기 때문에 넣어줌.
{
m.insert(make_pair(fx, 0));
m.insert(make_pair(graph[fx], 0));
}
}

 

 

✔느낀 점

  1. 이때까지 풀었던 DFS랑은 조금 달라서 많이 헷갈리고 오래 걸렸습니다.
  2. 문제가 너무 이해하기 어렵고 재귀 과정에서 엄청 복잡했다.
  3. 손으로 ㅈㄴ그렸다.
  4. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  5. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  6. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  7. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  8. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  9. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
  10. 중복을 허용하지 않는다면 더 효율적인 자료형은 set이야 재한아. 기억해!!
저작자표시 (새창열림)

'CodingTest > Baekjoon' 카테고리의 다른 글

[백준 1261] - 알고스팟(C++)  (0) 2022.11.21
[백준 18352] - 특정 거리의 도시 찾기(C++)  (1) 2022.11.19
[백준 1987] - 알파벳(C++)  (0) 2022.11.17
[백준 15900] - 나무 탈출(C++)  (0) 2022.11.13
[백준 16174] - 점프왕 쩰리(Large)  (1) 2022.11.12
  1. 🔎문제 해석
  2. 📃코드 단계
  3. 💻코드
  4. ✔느낀 점
'CodingTest/Baekjoon' 카테고리의 다른 글
  • [백준 1261] - 알고스팟(C++)
  • [백준 18352] - 특정 거리의 도시 찾기(C++)
  • [백준 1987] - 알파벳(C++)
  • [백준 15900] - 나무 탈출(C++)
재한
재한
안녕하세요 💻
재한
짜이한
전체
오늘
어제
  • 분류 전체보기 (504)
    • Skils (118)
      • Android (52)
      • C++ (5)
      • Kotlin (36)
      • Algorithm (24)
      • Server (1)
    • CodingTest (228)
      • Programmers (45)
      • Baekjoon (183)
    • Experience (8)
      • 후기(코딩테스트,프로그램,프로젝트) (8)
    • Computer Science (70)
      • Design Pattern (2)
      • OOP (2)
      • Computer Architecture (14)
      • OS (2)
      • Software Engineering (3)
      • DataBase (8)
      • Network (39)
    • 학교 (75)
      • R프로그래밍 (26)
      • 회계와 사회생활 (17)
      • 컴퓨터학개론 (20)
      • it기술경영개론 (12)

블로그 메뉴

  • 홈
  • 태그
  • 카테고리
  • 글쓰기
  • 설정

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
재한
[백준 2668] - 숫자 고르기(C++)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.