티스토리 뷰
1) 생각
항상 짝수로 주어지는 N명의 사람이 2개의 팀으로 나뉘어 경기를 할 때 팀이 되는 사람들은 서로에게 시너지 효과를 불어넣어 능력치를 향상시킨다. 이때 양팀의 능력치가 최소값이 되도록 팀을 꾸려라.
처음 생각
처음에는 탐색에서 left 팀과 right 팀을 각각 더해가면서 left의 개수와 right의 개수가 둘 다 n/2개가 되면 두 값을 - 시켜서 그 값의 최소값을 구하는 방향으로 시도하였다. => 탐색을 할 때마다 2개의 반복문을 돌면서 계속적으로 더하였기에 값을 구하기가 쉽지 않았다.
다음 생각
두 팀의 숫자가 n/2로 같으므로 한 팀이 꾸려지면 다른 팀은 자연스럽게 꾸려질 수 있다. 따라서 한 쪽 팀만 체크를 하면서 탐색을 하고 n/2 가 되면 미리 구해둔 배열의 합 값에서 해당 값을 빼주었다.
=> 미리 구해둔 배열의 합 값은 모든 경우의 수를 더한 것이라 잘 못된 값이였다.
다음 생각
한 팀을 미리 더한값으로는 다른 팀의 더한 값을 구할 수 없기에 탐색 과정에서는 누구를 선발 한 것인지만 방문 표시로 체크하고 개수가 n/2가 되었을 때, 방문 표시가 되어있는 사람과 되어있지 않은 사람들로 팀을 꾸리고 그 꾸린 팀을 가지고 시너지 효과의 합계를 구해 답을 구하였다.
=> 시간초과
2) 방안
모든 Case를 따지려고하니 '시간 초과'가 나왔기 때문에 각각의 선수들의 능력치 합을 구하는 과정을 1개로 통합하였고, 한 팀을 꾸릴때 즉, 탐색할 때 이전 선수를 뽑았으면 다시 그 선수를 뽑지 않아도 되기때문에 현재까지 돈 반복문의 Index를 다음 재귀의 변수로 넘겨주어 그 이후부터 탐색할 수 있도록 하였다.
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 | import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main{ static int[][] arr; static int n,sum; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); n = Integer.parseInt(br.readLine()); arr = new int[n][n]; for(int i=0;i<n;i++) { StringTokenizer st = new StringTokenizer(br.readLine()); for(int j=0;j<n;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); } } visited = new boolean[n]; min = Integer.MAX_VALUE; solve("",0,0); System.out.println(min); } static boolean[] visited; static int min; private static void solve(String left,int lCnt,int idx) { if(lCnt==n/2) { int leftSum = 0; int rightSum = 0; int[] arr2 = new int[n/2]; int[] arr3 = new int[n/2]; int idxL = 0; int idxR = 0; for(int i=0;i<n;i++) { if(visited[i]) arr2[idxL++] = i; else arr3[idxR++] = i; } for(int i=0;i<n/2;i++) { for(int j=i+1;j<n/2;j++) { leftSum += arr[arr2[i]][arr2[j]]; leftSum += arr[arr2[j]][arr2[i]]; rightSum += arr[arr3[i]][arr3[j]]; rightSum += arr[arr3[j]][arr3[i]]; } } min = Math.min(min, Math.abs(rightSum-leftSum)); return; } if(lCnt>n/2) return; for(int i=idx;i<n;i++) { if(visited[i]) continue; visited[i] = true; solve(left+" "+i,lCnt+1,i); visited[i] = false; } } } | cs |
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 14501번 퇴사 (4) | 2018.08.22 |
---|---|
[백준] 9095번 1, 2, 3 더하기 (0) | 2018.08.22 |
[백준] 14888번 연산자 끼워넣기 (4) | 2018.08.22 |
[백준] 6603번 로또 (0) | 2018.08.21 |
[백준] 10971번 외판원 순회 2 (0) | 2018.08.21 |
- Total
- Today
- Yesterday