728x90
안녕하세요 Coding-Knowjam입니다.
오늘은 백준 온라인 저지에 있는 14889번 스타트와 링크 문제를 풀어보겠습니다.
문제에 대한 링크는 아래에 있으니 문제를 먼저 읽고 와주시길 바랍니다.
https://www.acmicpc.net/problem/14889
1. 문제 설명
해당 문제는 구현 문제이면서 백트래킹으로 접근해서 풀 수 있습니다.
대부분의 완전 탐색의 문제는 재귀 메서드로 통해서 해결할 수 있습니다.
한 가지 유의사항은 팀을 나누는 모든 경우의 수를 구할 때, [0,1,2], [2,0,1], [1,0,2] 이 3개의 팀은 모두 같은 능력치의 결과를 가지기 때문에 중복을 제외해야 합니다.
그럼 코드를 살펴보겠습니다.
2. Java로 문제 풀이
package study.blog.codingnojam.algorithm.boj;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
// 백준온라인저지 14889번 스타트와 링크 문제 풀이
public class BOJ_14889 {
// 직원들 능력치 저장하는 2차원 배열
static int[][] status;
// 팀 나누기 위해서 사용하는 체크배열
static boolean[] teamChk;
// 팀을 저장할 링크드리스트
static LinkedList<Integer> team = new LinkedList<>();
// 최소 능력치 차이 결과 값 저장할 변수
static int result = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception{
// 정보 받기위한 객체
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 총 사람수
int N = Integer.parseInt(br.readLine());
// 총 사람 수로 배열 길이주고 생성
status = new int[N][N];
teamChk = new boolean[N];
// 능력치 배열 초기화
for (int i = 0; i < N; i++) {
String[] info = br.readLine().split(" ");
for (int j = 0; j < info.length; j++) {
status[i][j] = Integer.parseInt(info[j]);
}
}
// 모든 경우의 수 판단 (재귀함수 사용)
recursion(0, N/2, N);
// 결과 출력
System.out.println(result);
}
/**
* 팀을 나누는 모든 경우의 수 체크를 위한 재귀메서드
* @param index 재귀호출 시 마다 1씩 증가하면서 리스트에 저장할 팀원을 가리키는 변수
* @param limit 팀별 가져야하는 팀원의 수(재귀 종료를 위해 사용)
* @param N 전체 인원 수
*/
public static void recursion(int index, int limit, int N){
// 필요한 팀원 만큼 팀에 배정이 끝난 경우
if (team.size() == limit) {
// 팀의 능력치 저장을 위한 변수
int teamResult = 0;
// 다른 팀을 저장하기 위한 리스트
ArrayList<Integer> otherTeam = new ArrayList<>();
// 다른 팀 팀원 저장
for (int i = 0; i < teamChk.length; i++) {
// 처음 팀에 들어갔던 팀원들 제외한 나머지 다른팀에 저장
if (!teamChk[i]) {
otherTeam.add(i);
}
}
// 다른팀의 능력치 저장을 위한 변수
int otherTeamResult = 0;
// 팀의 능력치 계산 및 저장
for (int i = 0; i < team.size()-1; i++) {
int teamFst = team.get(i);
for (int j = i+1; j < team.size(); j++) {
int teamSec = team.get(j);
teamResult += status[teamFst][teamSec];
teamResult += status[teamSec][teamFst];
}
}
// 다른팀의 능력치 계산 및 저장
for (int i = 0; i < otherTeam.size()-1; i++) {
int otherTeamFst = otherTeam.get(i);
for (int j = i+1; j < otherTeam.size(); j++) {
int otherTeamSec = otherTeam.get(j);
otherTeamResult += status[otherTeamFst][otherTeamSec];
otherTeamResult += status[otherTeamSec][otherTeamFst];
}
}
// 팀과 다른팀의 능력치 차이가 제일 작은 값으로 result 갱신
result = Math.min(result ,Math.abs(teamResult - otherTeamResult));
// 재귀 종료
return;
}
// 전체 직원 수 만큼 반복
// index값을 i로 줘서 중복 안나게 방지 (0,1,2랑 2,1,0은 같은거임)
// i가 팀원의 인덱스랑 같은것(0번 팀원, 1번 팀원 등등)
for (int i = index; i < N; i++) {
// 팀에 팀원 추가
team.add(i);
// 추가된 팀원 체크
teamChk[i] = true;
// 다음 팀원 배정을 위해 재귀호출
recursion(i +1, limit, N);
// 추가된 팀원 팀에서 제외한 걸로 체크
teamChk[i] = false;
// 팀에서 팀원 제거
team.removeLast();
}
}
}
작성한 코드의 라인마다 주석을 달아놓았습니다.
재귀 메서드라서 한 번에 이해가 안 되실 수도 있는데 예시를 하나 넣어보면서 값을 추적하면서 보면 충분히 이해하실 수 있을 겁니다.
감사합니다.
728x90
'Algorithm & Data Structure > 문제풀이' 카테고리의 다른 글
[Algorithm] 백준 16234번(BOJ 16234) 인구 이동 문제풀이!! (Java) (0) | 2021.09.21 |
---|---|
[Algorithm] 백준 16236(BOJ 16236) 아기상어 문제 풀이!!(Java) (0) | 2021.09.12 |
[Algorithm] 백준 17140(BOJ 17140) 이차원 배열과 연산 문제풀이!! (Java) (0) | 2021.08.28 |
[Algorithm] 백준 3190번(BOJ 3190) 뱀 문제풀이!! (java) (0) | 2021.08.25 |
[Algorithm] 백준 12100번(BOJ 12100) 2048(easy) 문제 풀이(Java) (0) | 2021.08.22 |
댓글