백준 21608 - 상어 초등학교
Updated:
Java
21608 번 - 상어 초등학교
문제
접근 방법
학생마다 좋아하는 학생을 ArrayList와 Set으로 구현하였다.
차후에, 현재 자리에 인접한 학생이 좋아하는지 알기 위해서 Set.contains
로 빠르게 접근하여 파악하도록 한다.
인접한 자리에서 좋아하는 학생이면 5점, 빈자리면 1점을 부여하여 가장 높은 자리에 학생을 한 명씩 배치한다.
(0,0)에서 (n-1, n-1)으로 왼쪽 위에서 부터 탐색하므로 자동적으로 의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정해진다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, result;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
n = stoi(br.readLine());
int size = (int) Math.pow(n, 2);
ArrayList<Set<Integer>> like = new ArrayList<>();
for(int i = 0; i <= size; i++)
like.add(new HashSet<Integer>());
// 조건 값 세팅
int idx;
int[] order = new int[size];
for(int i = 0; i < size; i++) {
stk = new StringTokenizer(br.readLine());
idx = stoi(stk.nextToken());
order[i] = idx;
for(int j = 0; j < 4; j++) {
like.get(idx).add(stoi(stk.nextToken()));
}
}
int[][] sit = new int[n][n];
int[] dy = {-1,1,0,0};
int[] dx = {0,0,-1,1};
int y,x, score = 0, maxS, ty = -1, tx = -1;
// 학생의 순서대로 한명씩 좌석에 배치한다
for(idx = 0; idx < size; idx++) {
maxS = -1; // 처음 비교 값을 -1로 하여, 나중에 인접한 좋은 학생이 0명일 때를 대비한다.
// 0,0 부터 n-1, n-1까지 탐색한다.
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(sit[i][j] != 0)
continue;
score = 0;
// 현재 좌석의 상 하 좌 우를 탐색하여 점수를 매긴다.
for(int k = 0; k < 4; k++) {
y = i + dy[k];
x = j + dx[k];
// 해당하는 좌석에 선호하는 학생이 있으면
if(isIn(y,x) && like.get(order[idx]).contains(sit[y][x]))
score += 5;
else if(isIn(y,x) && sit[y][x] == 0)
score += 1;
}
// 해당 좌석의 점수가 높으면, 차후에 그 위치에 배치하도록 위치를 저장한다.
if(score > maxS) {
ty = i;
tx = j;
maxS = score;
}
}
}
sit[ty][tx] = order[idx];
}
int result = 0, cnt;
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
cnt = 0;
for(int k = 0; k < 4; k++) {
y = i + dy[k];
x = j + dx[k];
// 각 좌석의 상하좌우에 선호하는 학생이 앉아 있으면
if(isIn(y,x) && like.get(sit[i][j]).contains(sit[y][x])) {
cnt++;
}
}
// 인접한 학생의 수가 0이면, 10^-1이 0.1이다.
if(cnt != 0)
result += (int) Math.pow(10, cnt - 1);
}
}
System.out.println(result);
br.close();
}
// 주어진 범위 안에 있는가
public static boolean isIn(int y, int x){
if(y < 0 || y >= n || x < 0 || x >= n)
return false;
return true;
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
간단한 구현 문제였지만, maxS = -1;
에서 실수가 있었다.
처음에 maxS = 0;
으로 두고 계산하였는데,
이는 만약 인접한 학생 중, 빈자리가 없고 좋아하는 학생도 없으면 score
가 0이다.
따라서 maxS = 0;
이면 조건에 걸려져서 그 자리에 착석을 하지 못하는 경우가 생긴다.
비교 할 때, 이런 점을 조심해야 겠다.