[java]가장 가까운 세 사람의 심리적 거리 - 백준20529
문제
풀이
문제 해석을 하자면,
- 오늘이 생일인 종서를 위해 N명의 학생들의 MBTI 유형이 주어질 때, 가장 가까운 세 학생 사이의 심리적인 거리를 구해보자.
- 심리적 거리 공식 : (A와 B 사이의 심리적인 거리) + (B와 C 사이의 심리적인 거리) + (A와 C 사이의 심리적인 거리)
풀이
-
조합을 사용해 N명중 3명을 선택하고 주어진 공식을 사용해 심리적 거리를 구해서 비교하자.
- 단, 일반적으로 조합의 경우의수가 브루트포스 관점으로 보면 시간초과가 자명하다.
- n이 10만일 때 10만C3 의 값은 엄청 크기 때문이다.
- 이때, “비둘기집 원리” 가 필요하다.
- 비둘기집 원리 : n+1개의 물건을 n개의 상자에 넣은 경우, 최소한 한 상자에는 그 물건이 반드시 두 개 이상 들어있다는 원리
- 서로 다른 2개의 MBTI 는 16*2=32개가 한계이다. 그러므로 33개 부터는 무조건 동일한 MBTI 3개인 경우가 존재한다는 것이 핵심!
- 32C3 = 4960 으로 조합 값도 크지않다! -> 시간여유
- 따라서 n이 33개 이상일 경우 0을 출력하면 된다.
코드
static int N;
static int result;
static String[] inArr;
static int outArr[]; // N명중 3명 선택한 inArr의 index를 기록
static void check() {
int diff = 0;
String A = inArr[outArr[0]];
String B = inArr[outArr[1]];
String C = inArr[outArr[2]];
for (int i = 0; i < 4; i++) {
// A, B
if (A.charAt(i) != B.charAt(i)) {
diff++;
}
// B, C
if (B.charAt(i) != C.charAt(i)) {
diff++;
}
// A, C
if (A.charAt(i) != C.charAt(i)) {
diff++;
}
}
result = Math.min(result, diff);
}
static void dfs(int depth, int idx) {
// if (result == 0) return; // 시간초과 방지 -> 이걸로도 해결 가능
//base condition
if (depth == 3) {
check(); // 심리적 거리 계산함수
return;
}
//recursion
for (int i = idx; i < N; i++) {
outArr[depth] = i;
dfs(depth + 1, i + 1);
}
}
public static void main(String[] args) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
for (int t = 0; t < T; t++) {
result = Integer.MAX_VALUE; //init
outArr = new int[3]; //init
N = Integer.parseInt(br.readLine());
inArr = new String[N + 1];
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
for (int i = 0; i < N; i++) {
inArr[i] = stk.nextToken();
}
//run
if(N <= 32)
dfs(0, 0);
//output
if (N <= 32)
sb.append(result).append("\n");
else
sb.append(0).append("\n");
}
System.out.println(sb);
}
느낀점
비둘기집 원리라는 것을 기억해두자.
댓글남기기