https://www.acmicpc.net/problem/21608
21608번: 상어 초등학교
상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호
www.acmicpc.net
걸린 시간 : 1시간 4분
복잡한 문제같지만 자리를 주어진 조건에 맞게 정렬해서 한 명 한 명 자리에 앉히면 된다.
정렬
Java에서 복잡한 정렬을 하는 방법은 여러가지가 있다.
- Comparator 인터페이스의 compare 함수를 직접 구현하기
- 람다식을 활용해 익명 객체 사용해 구현하기
- 메서드 참조와 유틸리티 메서드 사용하기
나는 2번을 이용해 문제를 풀었다.
아래는 int 형 변수 r, c를 가지는 클래스 Pos가 있을 때, posList를 정렬하는 코드이다. 이 때, r에 대해서 내림차순, 그 후 c에 대해서 올림차순 정렬하는 경우이다.
posList.sort((p1, p2) ->
p1.r != p2.r ? p2.r - p1.r :
p1.c - p2.c);
내림차순 정렬할 경우 p2에서 p1을 빼고, 올림차순의 경우 반대로 하면 된다.
알고리즘
- (1, 1) 부터 (N, N) 까지의 Pos 형 인스턴스를 담는 리스트를 하나 만든다.
- 학생을 차례대로 입력받으면서 어디에 앉힐 지 주어진 조건에 따라 리스트를 정렬시키며 결정한다. 앉힌 Pos 는 리스트에서 제거한다.
이 때, 주변의 좋아하는 사람을 세는 메소드와 주변의 빈 칸을 세는 메소드를 따로 구현해 사용한다. - 모든 배치가 완료되면 학생마다 만족도를 계산해 출력한다.
정답 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class BOJ21608 {
static int N;
static int score;
static List<Pos> posList = new ArrayList<>();
static int[][] loveList = new int[401][4];
static int[][] students = new int[21][21];
static int[] dr = {-1, 0, 0, 1};
static int[] dc = {0, -1, 1, 0};
static int[] scoreUtil = {0, 1, 10, 100, 1000};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
posList.add(new Pos(i, j));
}
}
for (int i = 0; i < N*N; i++) {
int[] love = new int[4];
StringTokenizer st = new StringTokenizer(br.readLine());
int studentNum = Integer.parseInt(st.nextToken());
for (int j = 0; j < 4; j++) {
love[j] = Integer.parseInt(st.nextToken());
}
loveList[studentNum] = love;
posList.sort((p1, p2) ->
cntLove(p1, love) != cntLove(p2, love) ? cntLove(p2, love) - cntLove(p1, love) :
cntBlank(p1) != cntBlank(p2) ? cntBlank(p2) - cntBlank(p1) :
p1.r != p2.r ? p1.r - p2.r :
p1.c - p2.c);
students[posList.get(0).r][posList.get(0).c] = studentNum;
posList.remove(0);
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int studentNum = students[i][j];
score += scoreUtil[cntLove(new Pos(i, j), loveList[studentNum])];
}
}
System.out.println(score);
}
private static int cntBlank(Pos p1) {
int cnt = 0;
for (int k = 0; k < 4; k++) {
int nr = p1.r + dr[k];
int nc = p1.c + dc[k];
if (nr <= 0 || nr > N || nc <= 0 || nc > N) continue;
for (int i = 0; i < 4; i++) {
if (students[nr][nc] == 0) cnt++;
}
}
return cnt;
}
private static int cntLove(Pos p1, int[] love) {
int cnt = 0;
for (int k = 0; k < 4; k++) {
int nr = p1.r + dr[k];
int nc = p1.c + dc[k];
if (nr <= 0 || nr > N || nc <= 0 || nc > N) continue;
for (int i = 0; i < 4; i++) {
if (students[nr][nc] == love[i]) cnt++;
}
}
return cnt;
}
static class Pos {
public int r, c;
public Pos (int r, int c) {
this.r = r;
this.c = c;
}
}
}
'Baekjoon Online Judge' 카테고리의 다른 글
[BOJ] 1987 : 알파벳 (Java) (1) | 2023.10.26 |
---|---|
[BOJ] 1744 : 수 묶기 (Java) (1) | 2023.10.26 |
[BOJ] 1941: 영역 구하기 (Java) (0) | 2023.10.19 |
[BOJ] 1941: 소문난 칠공주 (Java) with 조합 (0) | 2023.10.19 |
[BOJ] 1520 : 내리막 길 (C++) with Top Down DP (1) | 2023.10.05 |