[풀이] 정삼각형이 아닌 직삼각형을 2차원 배열에 표시한다고 생각하면 편합니다. 삼각형의 안쪽으로 들어갈수록 삼각형은 변의 길이가 3씩 줄어들기 때문에 n부터 시작해서 변의 길이를 3씩 줄여가며 큰 삼각형에서 작은 삼격으로 배열에 표기를 해나갑니다. y=1,x=1부터 시작해서 ↓ → ↖ 순으로 좌표를 움직여 가면서 숫자를 표기해주면 됩니다.
[풀이] 칼럼의 수 N이 8개, 로우가 20개이므로 모든 키의 조합에 대해 확인해봐도 시간내에 해결이 가능합니다. N이 8이기때문에 bit연산을 이용하였습니다. 예를들어 0101이 후보키라면 0111은 최소성을 만족하지 못하므로 후보키가 될 수 없다는 것을 이용하였습니다.
1) 1~(2^N-1) 까지 키의 조합이 될 수 있는 모든 경우를 돌면서 몇개의 속성을 사용하는지에 따라 각각의 bitmasks 배열에 넣어줍니다. ex) 11010 이라면 3개를 사용하므로 bitmasks[3]에 push 개수별로 나눠서 저장하는 이유는 bitmasks[1]부터 속성을 적게 사용하는 것부터 candidates로 분류해놔야 많은 속성을 사용하는 것들이 최소성을 만족하는지 체크할 수가 있습니다. (다른 풀이를 보니 개수별로 분류하지 않고 1~2^N-1까지 순서대로 체크해도 문제가 없다는 것을 알 수 있었습니다. 예를들면 10101 10001보다 무조건 뒤에 오기 때문입니다.)
2) 가장 작은 속성을 사용하는 bitmasks[1] vector의 값들부터 순회하면서 현재 나온 값이 후보키가 될 수 있는지를 체크합니다.
[최소성 체크] isExist() 함수는 이미 앞에 나온 후보키들에 의해 현재 확인중인 비트마스크가 후보키가 될 수 있는지를 체크합니다. 만약 현재 체크하는 값이 10101인데 후보키를 저장하는 cand에 10001이 들어있다면 isExist는 true를 return하며 종료합니다. 10101과 10001의 bit and 연산으로 간단히 포함관계인지 체크할 수 있습니다. (10101 & 10001) == 10001 -> bit 연산 후에도 10001의 값을 유지한다는 것은 모든 bit가 현재 체크하는 값에서 살아있다는 의미이므로 이 둘은 포함관계입니다.
[유일성 체크] isExist()가 false라면 그다음엔 현재 체크중인 bitmask로 유일성을 만족하는지 체크해야 합니다. check() 함수에서 모든 relation을 순회하면서 masking된 속성의 string을 전부 이어붙힙니다. 주의할점이 그냥 이어붙히면 [A,AA] [AA,A]를 동일하게 인식하므로 "#"를 속성 뒤에 붙혀서 구분을 해주었습니다. 완성된 string을 set에 넣습니다. 만약 이미 string이 들어있다면 유일성을 만족하지 못하는 것이므로 false를 return 합니다.
3. 위 과정에서 !isExist() && check()를 만족하는 것들만 후보키로 등록되게 되며 이 개수를 return하면 정답입니다.
[풀이] 당연히 그냥 구현 문제일줄 알았는데 info의 범위가 50000 query의 범위가 100000이나 되기 때문에 쿼리마다 모든 info를 확인하는 O(query*info)의 시간복잡도로는 효율성 테스트 통과가 불가능합니다.
지원자의 4가지 항목을 4자리 수로 변환해주는 Hashing과 어떤 점수를 넘는 지원자를 찾기 위한 binary search를 사용해주면 문제를 해결할 수 있습니다.
1) 아래와 같이 4가지 항목으로 숫자로 변환해주는 map 테이블을 만듭니다. cpp, java, python => 1,2,3 backend, frontend => 1,2 junior, senior => 1,2 chicken, pizza => 1,2
2) 지원자의 정보 string을 분리하여 hash값을 만든 뒤 map> 타입의 map에 형태로 저장합니다. ex) mp["1111"].push_back(150) 그 뒤 map을 순회하면서 vector들을 정렬해줍니다. (binary search를 사용하기 위함입니다.)
3) query를 순회하면서 string을 쪼개서 만들 수 있는 모든 hash를 만들어줍니다. 저는 vector 4개를 선언하여 "-" 가 아닌 경우에는 그에 맞는 string의 변환값을 넣어주었고, "-"인 경우에는 1,2 (언어의 경우 3까지) 모두 되므로 모두 vector에 넣어준 뒤 4중 for문을 돌려서 만들 수 있는 모든 hash를 만들어주었습니다. query가 -,-,-,- 이어도 최대 3x2x2x2=24개 이기때문에 많은 시간이 들지 않습니다.
각 2)에서 저장한 hash key에 맞는 점수들이 저장되어있는 vector를 map에서 가져와 binary search를 통해 조건을 만족하는 가장 적은 점수의 지원자의 iterator를 가져옵니다. mp[key].end()-it를 통해 조건을 만족하는 모든 지원자를 구할 수 있습니다. 이 값을 cnt 변수에 카운트해주면 최종 cnt 값이 현재 query의 정답입니다.