백준 2617 - 구슬 찾기
Updated:
Java
2617 번 - 구슬 찾기
문제
모양은 같으나, 무게가 모두 다른 N개의 구슬이 있다. N은 홀수이며, 구슬에는 번호가 1,2,…,N으로 붙어 있다.
이 구슬 중에서 무게가 전체의 중간인 (무게 순서로 (N+1)/2번째) 구슬을 찾기 위해서 아래와 같은 일을 하려 한다.
한 쌍의 구슬을 골라서 양팔 저울의 양쪽에 하나씩 올려 보면 어느 쪽이 무거운가를 알 수 있다.
이렇게 M개의 쌍을 골라서 각각 양팔 저울에 올려서 어느 것이 무거운가를 모두 알아냈다.
이 결과를 이용하여 무게가 중간이 될 가능성이 전혀 없는 구슬들은 먼저 제외한다.
M 개의 쌍에 대한 결과를 보고 무게가 중간인 구슬이 될 수 없는 구슬의 개수를 구하는 프로그램을 작성하시오.
접근 방법
DFS
를 사용하여 그래프 탐색으로 해결하였다.
각 구슬의 무게 대조한 값을 단방향 그래프로 나타낸다.
구슬 2번이 구슬 1번보다 무겁다.
: 2 -> 1
구슬 4번이 구슬 3번보다 무겁다.
: 4 -> 3
1부터 n까지의 구슬 각각을 시작으로 DFS로 타고 들어가 만나는 구슬의 개수를 구한다.
[자신보다 가벼운 구슬의 수]가 [전체 구슬의 수 / 2 + 1] 보다 크다면 무게가 중간이 될 가능성이 전혀 없는 구슬이 된다.
이제 반대 상황인 자신보다 무거운 구슬의 수도 세어, 무게가 중간인 구슬이 될 수 없는 구슬의 총 합을 구한다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result, downCnt, upCnt;
static boolean[][] up, down;
static boolean[] upVis, downVis;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
up = new boolean[n+1][n+1];
down = new boolean[n+1][n+1];
int big, small;
for(int i = 0; i < m; i++) {
stk = new StringTokenizer(br.readLine());
big = stoi(stk.nextToken());
small = stoi(stk.nextToken());
down[big][small] = true; // 무거운 구슬에서 가벼운 구슬로
up[small][big] = true; // 가벼운 구슬에서 무거운 구슬로
}
int bound = (n / 2) + 1; // 중간이 될 수 없는 경계 값
for(int i = 1; i <= n; i++) {
init();
FindDown(i); // 현재 구슬보다 가벼운 구슬을 찾는다.
FindUp(i); // 현재 구슬보다 무거운 구슬을 찾는다.
if(upCnt >= bound || downCnt >= bound)
result++;
}
System.out.println(result);
br.close();
}
// 구슬 방문여부, 개수 초기화
private static void init() {
upVis = new boolean[n+1];
downVis = new boolean[n+1];
upCnt = 0;
downCnt = 0;
}
// 시작 구슬부터 더 가벼운 구슬들을 찾는다
private static void FindDown(int num) {
for(int i = 1; i <= n; i++) {
if(down[num][i] && !downVis[i]) {
downVis[i] = true;
downCnt++;
FindDown(i);
}
}
}
// 시작 구슬부터 더 무거운 구슬들을 찾는다
private static void FindUp(int num) {
for(int i = 1; i <= n; i++) {
if(up[num][i] && !upVis[i]) {
upVis[i] = true;
upCnt++;
FindUp(i);
}
}
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
DFS를 사용하여 그래프를 탐색하는 방법에 대하여 부족하다.
그래프 이론에 대하여 공부를 많이 할 필요가 있다.
개선할 점
플로이드 워셜로도 풀어봐야한다.