실버 2
https://www.acmicpc.net/problem/14889
백트래킹으로 문제를 해결했다.
팀조합을 만든다. (한 팀의 인원수는 n/2)
for문을 실행해 방문하지 않은 팀원이면 방문하고 백트래킹 수행 재귀가 끝나면 비방문으로 변경
여기 반복문에서 i=0으로 할경우 시간초과가 나온다. 경우를 잘 따지고 순열이 아닌 조합일 땐,
i=idx로 해서 가지치기를 수행하여 시간을 절약해야한다. 
	for(int i = idx; i < N; i++) {
		// 방문하지 않았다면?
		if(!visit[i]) {
			visit[i] = true;	// 방문으로 변경
			combi(i + 1, count + 1);	// 재귀 호출
			visit[i] = false;	// 재귀가 끝나면 비방문으로 변경
		}
	}
팀조합이 완성된 경우 팀 당 능력치의 합을 구해서 최솟값을 찾는다.
	static void diff() {
        int start = 0;
        int link = 0;
        for (int i = 0; i < n - 1; i++) {
            for (int j = i; j < n; j++) {
                if (visit[i] == true && visit[j] == true) {
                    start += map[i][j];
                    start += map[j][i];
                } else if (visit[i] == false && visit[j] == false) {
                    link += map[i][j];
                    link += map[j][i];
                }
            }
        }
        int val = Math.abs(start - link);
        min = Math.min(val, min);
    }
코드1)
package 백트래킹;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ14889 {
   static int n;
   static int[][] map;
   static int min = Integer.MAX_VALUE;
   static boolean[] visit;
   public static void main(String[] args) throws IOException {
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       n = Integer.parseInt(br.readLine());
       map = new int[n][n];
       for (int i = 0; i < n; i++) {
           StringTokenizer st = new StringTokenizer(br.readLine());
           for (int j = 0; j < n; j++) {
               map[i][j] = Integer.parseInt(st.nextToken());
           }
       }
       visit = new boolean[n];
       back(0, 0);
       System.out.println(min);
   }
   static void back(int idx, int depth) {
       if (depth == n/2) {
           diff();
           return;
       }
       for (int i = idx; i < n; i++) { //
           if (!visit[i]) {
               visit[i] = true;
               back(i + 1, depth + 1);
               visit[i] = false;
           }
       }
   }
   static void diff() {
       int start = 0;
       int link = 0;
       for (int i = 0; i < n - 1; i++) {
           for (int j = i; j < n; j++) {
               if (visit[i] == true && visit[j] == true) {
                   start += map[i][j];
                   start += map[j][i];
               } else if (visit[i] == false && visit[j] == false) {
                   link += map[i][j];
                   link += map[j][i];
               }
           }
       }
       int val = Math.abs(start - link);
       min = Math.min(val, min);
   }
}
 코드2)
능력치 구하는 부분이 조금 다르지만 같은 의미이다.
코드 1보다 복잡하지만 직관적이다. 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BOJ14889 {
	static int n;
	static int[][] map;
	static int min = Integer.MAX_VALUE;
	static boolean[] visit;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		st = new StringTokenizer(br.readLine());
		n = Integer.parseInt(st.nextToken());
		visit = new boolean[n];
		map = new int[n][n];
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < n; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		back(0,0);
		System.out.println(min);
	}
	private static void back(int depth,int start) {
		// TODO Auto-generated method stub
		if (depth == n / 2) {
			int[] arr = new int[n / 2];
			int[] arr2 = new int[n / 2];
			int j = 0, k = 0;
			for (int i = 0; i < n; i++) {
				if (visit[i]) {
					arr[j++] = i;
				} else {
					arr2[k++] = i;
				}
			}
			int s = start(arr);
			int l = link(arr2);
			min = Math.min(min, Math.abs(s - l));
			return;
		}
		for (int i = start; i < n; i++) {
			if (!visit[i]) {
				visit[i] = true;
				back(depth + 1,i+1);
				visit[i] = false;
			}
		}
	}
	private static int start(int[] start) {
		int sum = 0;
		for (int i = 0; i < start.length; i++) {
			for (int j = 0; j < start.length; j++) {
				if (i == j)
					continue;
				int x = start[i];
				int y = start[j];
				sum += map[x][y];
			}
		}
		return sum;
	}
	private static int link(int[] link) {
		int sum = 0;
		for (int i = 0; i < link.length; i++) {
			for (int j = 0; j < link.length; j++) {
				if (i == j)
					continue;
				int x = link[i];
				int y = link[j];
				sum += map[x][y];
			}
		}
		return sum;
	}
}