[백준/BOJ] 14889 스타트와 링크 - JAVA - 실버1

2025. 4. 26. 18:30·알고리즘/문제풀이

[백준/BOJ] 14889 스타트와 링크 - JAVA - 실버1

문제

https://www.acmicpc.net/problem/14889

문제 분석

조건

  • 짝수인 N명을 2팀으로 나누고, 각 팀의 시너지 차이를 최소화하는 문제이다.

풀이방법

  • 비트마스킹을 사용하여 팀을 나누어주었다.
  • 시작 조합은 각 팀에 N/2명만큼 있어야하므로 조합의 시작 부분을`1 << (N / 2) - 1`로 하고, 가장 앞 부호가 1이 되는 순간 기존과 팀원이 중복되기때문에 마지막 팀원은 2팀으로 고정되게 설정하였다.
    • `for (int i = 1 << (N / 2) - 1; i < 1 << (N - 1); i++)`
  •  조합을 구하고 팀원수가 맞는다면 각 팀의 시너지를 구해주었다.

+

  • 마지막 팀원을 고정하고 첫 부분도 고정은 했지만 비트마스킹 특성상 어쩔수없이 `1 << (N / 2) - 1` 부터 ` i < 1 << (N - 1)`까지 모든 수를 탐색하게 된다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static int[][] board;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int N = Integer.parseInt(br.readLine());
        board = new int[N + 1][N + 1];
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= N; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        int answer = Integer.MAX_VALUE;
        List<Integer> team1;
        List<Integer> team2;

        for (int i = 1 << (N / 2) - 1; i < 1 << (N - 1); i++) {
            team1 = new ArrayList<>();
            team2 = new ArrayList<>();
            for (int j = 0; j < N; j++) {
                if (((1 << j) & i) > 0) {
                    team1.add(j + 1);
                } else {
                    team2.add(j + 1);
                }
            }
            if (team1.size() != N / 2) {
                continue;
            }
            answer = Math.min(answer, Math.abs(getSynergy(team1) - getSynergy(team2)));
        }
        System.out.println(answer);
    }

    private static int getSynergy(List<Integer> team) {
        int count = 0;
        for (int member1 : team) {
            for (int member2 : team) {
                if (member1 == member2) {
                    continue;
                }
                count += board[member1][member2];
            }
        }
        return count;
    }
}

결과

++

2년 전 풀었던 문제를 스터디를 하며 다시 풀게 되었다. 그때는 재귀로 풀었는데 요즘은 조합 문제만 보면 비트마스킹을 이용해서 문제를 풀고싶어진다.

비트마스킹으로 구현은 더 쉽게 했지만 시간복잡도에서 모든 경우의 수를 탐색하느라 손해를 봤다. 또한 리스트를 반복적으로 초기화하면서 메모리면에서도 손해를 봤다. 정답을 맞았긴했지만 다음에는 정확한 경우의 수가 정해진다면 `Next Combination`을 사용해서 풀어야겠다.

728x90
저작자표시 비영리 변경금지 (새창열림)
'알고리즘/문제풀이' 카테고리의 다른 글
  • [프로그래머스] 92343 양과 늑대 - JAVA - Lv3
  • [프로그래머스] 43162 네트워크 - JAVA - Lv3
  • [프로그래머스] 255900 외톨이 알파벳 - JAVA - PCCP 모의고사
  • [프로그래머스] 43165 타겟 넘버 - JAVA - Lv.2
LIRI
LIRI
  • LIRI
    기록
    LIRI
  • 전체
    오늘
    어제
    • 분류 전체보기 (74)
      • 블로그 꾸미기 (0)
      • Spring (6)
      • 바이브코딩 (1)
      • React (3)
      • CS (0)
      • 알고리즘 (57)
        • 개념 (2)
        • 문제풀이 (54)
      • Java (1)
      • DB (1)
      • log (4)
        • SSAFY (3)
        • 궁금 (1)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    Springsecurity
    커서ai
    SSAFY 9기
    BOJ
    백준
    Spring
    Java
    알고리즘 문제풀이
    springboot
    dfs
    그리디
    ssafy 합격 후기
    리액트
    알고리즘
    최장증가부분수열
    LIS
    너비우선탐색
    lv3
    dp
    JWT
    바이브코딩
    LV2
    비트마스킹
    느좋코딩
    싸피
    프로그래머스
    BFS
    Security
    pccp모의고사
    SSAFY
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
LIRI
[백준/BOJ] 14889 스타트와 링크 - JAVA - 실버1
상단으로

티스토리툴바