[java]스타트와 링크 - 백준14889
문제
풀이
문제 해석을 하자면,
- 두 팀의 점수 차이가 가장 작은(ex:0) 값을 구하라
풀이
- 크게 2가지를 구현하면 된다.
- 팀나누기 -> 재귀 (N개 중 N/2개 택)
- 재귀로 안하면 for문을 수도없이 사용하게 되어서 재귀로 돌렸다.
- 그런데, 다른사람 풀이가 궁금해서 찾아보니 “조합론”을 사용하였다.
- “조합” 으로 구현하면 딱히 visited도 필요없어서 더 간단하다.
- 하고싶은대로 구현하자.
- 계산하기 -> 2중 for (N/2개 중 2개 택)
- 팀나누기 -> 재귀 (N개 중 N/2개 택)
- 단, 타입 조심 및 좌표 조심하자
코드
public static int[][] inArr = new int[22][22];
public static boolean[] visited = new boolean[22];
public static int[] outArr = new int[22];
public static int N;
public static int result = Integer.MAX_VALUE;
public static void cal() {
// 먼저, 반대팀 숫자 구하기
int[] outArr2 = new int[22]; // outArr에 없는 숫자들 -> 즉, 반대 팀의 숫자
boolean[] visited2 = new boolean[22];
for(int i=0; i<N/2; i++) { // 한팀의 크기 : N/2
for(int j=1; j<=N; j++) { // 번호는 총 N
if(outArr[i]==j) visited2[j]=true;
}
}
int idx = 0;
for(int i=1; i<=N; i++) {
if(visited2[i]) continue;
outArr2[idx++] = i;
}
// debug -> 숫자 출력 해보기
// for(int i=0; i<N/2; i++) {
// System.out.print(outArr[i]+" ");
// }
// System.out.println();
// for(int i=0; i<N/2; i++) {
// System.out.print(outArr2[i]+" ");
// }
//System.out.println();
// 2. 계산하기
int cal1 = 0;
int cal2 = 0;
for(int i=0; i<(N/2)-1; i++) {
for(int j=i+1; j<N/2; j++) {
int idx1 = outArr[i]-1;
int idx2 = outArr[j]-1;
cal1 += inArr[idx1][idx2] + inArr[idx2][idx1];
}
}
for(int i=0; i<(N/2)-1; i++) {
for(int j=i+1; j<N/2; j++) {
int idx1 = outArr2[i]-1;
int idx2 = outArr2[j]-1;
cal2 += inArr[idx1][idx2] + inArr[idx2][idx1];
}
}
int diff = Math.abs(cal1-cal2);
result = Math.min(result, diff);
}
// dfs. 숫자쌍 출력 -> 재귀로 구현하려면 idx, 백트래킹 필수
public static void dfs(int depth, int idx) {
//base condition -> visited
if(depth == N/2) {
cal();
return;
}
//recursion
// 1. 팀나누기
for(int i=idx; i<=N; i++) {
if(visited[i]) continue;
visited[i]=true;
outArr[depth] = i;
dfs(depth+1, i);
visited[i]=false; // backtracking
}
}
public static void main(String[] args) throws Exception {
//init
//input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
for(int i=0; i<N; i++) {
StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
for(int j=0; j<N; j++) {
inArr[i][j] = Integer.parseInt(stk.nextToken());
}
}
//run
visited[1]=true; // 1은 미리 넣고 시작
outArr[0] = 1;
dfs(1,1);
//output
System.out.println(result);
}
느낀점
생략
댓글남기기