SWExpertAcademy의 키순서(5643 / D4) 문제이다.
[ 문제풀이 ]
일부의 키 결과를 통해서 정확하게 자신의 키를 알 수 있는 학생이 몇 명이 구해야 하는 문제이다.
먼저, 자신의 키가 몇 번째인지 정확하게 알기 위한 방법에 대해서 부터 알아보자.
예를 들어서 3명의 학생이 있다고 가정해보자. [ 1번학생 , 2번학생 , 3번학생 ]
입력으로는 "1번학생은 2번학생보다 작습니다." , "2번학생은 3번학생보다 작습니다." 가 주어졌다고 생각해보자.
너무나 단순한 상황이라서 딱 봐도 3명 모두 자신이 몇 번째 인지 알 수 있을 거라는 결론이 나올 것이다.
그럼 왜 그렇게 되는지 알아보자. 분명히 2번학생은 모든 학생과 비교를 했지만, 1번학생과 3번학생은 비교하지 않았음에도
1번학생이 3번학생보다 더 작다는 것을 알 수 있다.
왜냐하면, 1번 학생은 2번학생보다 작은데, 2번학생은 3번학생보다 작기 때문에 당연하게 1번학생은 3번학생보다 작은 것이다.
굉장히 당연한 이야기지만 본인은 이 방법을 통해서 문제를 해결하였다.
문제에서 입력으로 일부 학생들의 키를 비교한 결과가 주어진다.
예를 들어서 A학생이 B학생보다 작다. 라는 식으로 입력이 주어지는데, 우리는 이 입력을 통해서 2가지 정보를 더 알 수 있다.
1. A학생보다 키가 작은 학생은, B학생보다 더 작다.
2. B학생보다 키가 큰 학생은, A학생보다 더 크다.
이를 구현하기 위해서 본인은, 2개의 Vector 배열을 사용해주었다.
하나는, 나보다 키가 작은 사람들을 저장해 놓는 Vector
또 하나는 나보다 키가 큰 사람들을 저장해 놓는 Vector
이 후, 재귀를 이용해서 위에서 말한 2가지 정보들을 저장해주었다. 이 과정에서 중복된 탐색이 발생할 수 있다.
따라서, 두 학생의 키 관계를 비교한 적이 있는지 없는지 판단해주기 위해서 Compare[][] 이라는 2차원 bool형 배열을 만들어서
관계를 비교한적에 대한 여부를 판단해 주었다.
재귀에 대한 부분을 코드로 보면 다음과 같다.
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 | void Make_State(int A, int B) { for (int i = 0; i < Small_Person[A].size(); i++) { int NA = Small_Person[A][i]; if (Compare[NA][B] == false) { Compare[NA][B] = true; Compare[B][NA] = true; Big_Person[NA].push_back(B); Small_Person[B].push_back(NA); Make_State(NA, B); } } for (int i = 0; i < Big_Person[B].size(); i++) { int NB = Big_Person[B][i]; if (Compare[NB][A] == false) { Compare[NB][A] = true; Compare[A][NB] = true; Big_Person[A].push_back(NB); Small_Person[NB].push_back(A); Make_State(A, NB); } } } | cs |
위의 코드는 매개변수(A , B)가 주어지는데 이는 "A학생이 B학생보다 키가 더 작습니다" 라는 입력이 주어졌을 때
두 학생을 매개변수로 호출하는 코드이다.
위에서도 말했듯이 우리는 이 하나의 정보를 통해서 2가지 정보를 더 얻을 수 있다.
line3 ~ line15) 를 보게되면 "A학생보다 키가 작은 학생은 B학생보다 작습니다." 를 구현한 것이고
line16 ~ line 28) 을 보게되면 "B학생보다 키가 큰 학생은 A학생보다 큽니다." 를 구현한 것이다.
이런식으로 구현을 하게 되면, "현재 나보다 키가 작은사람은 Small_Person[] 이라는 Vector에, 나보다 키가 더 큰 사람은
Big_Person[] 이라는 Vector에 저장" 되어 있을 것이다.
그럼 총 학생수가 N명이기 때문에, Small_Person의 Size()와 Big_Person의 Size()를 비교해서 N - 1이 된다면,
즉, 나보다 키가 작은사람의 사람수 + 나보다 키가 큰 사람의 사람수를 더한 값이 전체 N명중, 나를 제외한 N - 1명이 된다면
자신의 키가 정확히 몇 번쨰인지 알 수 있게 된다.
[ 소스코드 ]
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include<iostream> #include<vector> #include<cstring> #define endl "\n" #define MAX 510 using namespace std; int N, M, Answer; bool Compare[MAX][MAX]; vector<int> Big_Person[MAX], Small_Person[MAX]; vector<pair<int, int>> Cmd; void Initialize() { memset(Compare, false, sizeof(Compare)); for (int i = 0; i < MAX; i++) { Big_Person[i].clear(); Small_Person[i].clear(); } Cmd.clear(); Answer = 0; } void Input() { cin >> N >> M; for (int i = 0; i < M; i++) { int a, b; cin >> a >> b; Cmd.push_back(make_pair(a, b)); } } void Make_State(int A, int B) { for (int i = 0; i < Small_Person[A].size(); i++) { int NA = Small_Person[A][i]; if (Compare[NA][B] == false) { Compare[NA][B] = true; Compare[B][NA] = true; Big_Person[NA].push_back(B); Small_Person[B].push_back(NA); Make_State(NA, B); } } for (int i = 0; i < Big_Person[B].size(); i++) { int NB = Big_Person[B][i]; if (Compare[NB][A] == false) { Compare[NB][A] = true; Compare[A][NB] = true; Big_Person[A].push_back(NB); Small_Person[NB].push_back(A); Make_State(A, NB); } } } void Solution() { for (int i = 0; i < M; i++) { int A = Cmd[i].first; int B = Cmd[i].second; if (Compare[A][B] == false) { Big_Person[A].push_back(B); Small_Person[B].push_back(A); Compare[A][B] = Compare[B][A] = true; Make_State(A, B); } } for (int i = 1; i <= N; i++) { int Cnt = Big_Person[i].size() + Small_Person[i].size(); if (Cnt == N - 1) Answer++; } } void Solve() { int Tc; cin >> Tc; for (int T = 1; T <= Tc; T++) { Initialize(); Input(); Solution(); cout << "#" << T << " " << Answer << endl; } } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("Input.txt", "r", stdin); Solve(); return 0; } | cs |
'[ SWEA Code ] > # SWEA - ' 카테고리의 다른 글
[ SWEA 9282 ] 초콜릿과 건포도 (C++) (0) | 2020.05.01 |
---|---|
[ SWEA 6731 ] 홍익이의 오델로 게임 (C++) (0) | 2020.04.27 |
[ SWEA 9088 ] 다이아몬드 (C++) (0) | 2020.04.24 |
[ SWEA 1907 ] 모래성 쌓기 (C++) (0) | 2020.04.21 |
[ SWEA 5684 ] 운동 (C++) (0) | 2020.04.19 |