목차
- 문제
- 내가 푼 방법
- 자바 코드
- 결과 및 회고
1. 문제
https://www.acmicpc.net/problem/2615
2. 내가 푼 방법
전형적인 BFS 문제이다. 3차원 배열인 visit을 선언해 이미 방문한 적 있는 위치일 경우에는 뛰어넘도록 코드를 작성했다.
상+하, 좌+우, 대각선 2개로 뻗어나가는 방향을 합쳐서 카운팅해야하기 때문에, bfs 함수 안에서 cntArr 배열에 각 방향으로 뻗어나가는 위치를 카운팅해줬다. cntArr 배열을 PriorityQueue로 선언해 준 이유는 x가 가장 작은 위치(x가 같을 경우 y가 가장 작은 위치)를 반환해주기 위해서이다.
큐가 돌아갈 때 direction은 상/하/좌/우/대각선 4개 포함해서 0~7을 갖고 있고, oneDirection은 상하/좌우/대각선 2개를 포함해서 0~3을 갖고 있다. direction을 통해 oneDirection을 구해주는 getOneDirection함수를 작성했다.
public static void solution() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (arr[i][j] != 0) bfs(i, j);
}
}
}
public static void bfs(int i, int j) {
Queue<Tuple> queue = new LinkedList<>();
for (int dir = 0; dir < 8; dir++) {
queue.add(new Tuple(i, j, dir));
}
PriorityQueue<Tuple>[] cntArr = new PriorityQueue[4];
for (int q = 0; q < 4; q++) {
cntArr[q] = new PriorityQueue<>();
cntArr[q].add(new Tuple(i, j, q));
}
while (!queue.isEmpty()) {
Tuple tuple = queue.poll();
int x = tuple.x;
int y = tuple.y;
int direction = tuple.direction;
int oneDirection = getOneDirection(direction);
if (x <= 0 || y <= 0 || x > N || y > N) continue;
if (visit[x][y][oneDirection]) continue;
if (arr[i][j] != arr[x][y]) continue;
if (x != i || y != j) {
cntArr[oneDirection].add(new Tuple(x, y, direction));
}
queue.add(move(x, y, direction));
}
for (PriorityQueue<Tuple> cnt : cntArr) {
if (cnt.size() == 5) {
win = arr[i][j];
Tuple first = cnt.poll();
winSite[0] = first.x;
winSite[1] = first.y;
visit[first.x][first.y][getOneDirection(first.direction)] = true;
}
for (Tuple t : cnt) {
visit[t.x][t.y][getOneDirection(t.direction)] = true;
}
}
}
public static Tuple move(int x, int y, int direction) {
if (direction == 0) return new Tuple(x-1, y, direction);
else if (direction == 1) return new Tuple(x-1, y+1, direction);
else if (direction == 2) return new Tuple(x, y+1, direction);
else if (direction == 3) return new Tuple(x+1, y+1, direction);
else if (direction == 4) return new Tuple(x+1, y, direction);
else if (direction == 5) return new Tuple(x+1, y-1, direction);
else if (direction == 6) return new Tuple(x, y-1, direction);
else return new Tuple(x-1, y-1, direction);
}
public static int getOneDirection(int direction) {
if (direction == 0 || direction == 4) return 0;
else if (direction == 1 || direction == 5) return 1;
else if (direction == 2 || direction == 6) return 2;
else return 3;
}
3. 자바 코드
깃허브 풀이 주소 : https://github.com/geujeog/BOJ/blob/main/B2615.java
import java.util.*;
import java.io.*;
class Main {
static int N = 19;
static int[][] arr;
static int win;
static int[] winSite;
static boolean[][][] visit;
public static void main (String[] args) throws IOException {
init();
solution();
print();
}
public static void solution() {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (arr[i][j] != 0) bfs(i, j);
}
}
}
public static void bfs(int i, int j) {
Queue<Tuple> queue = new LinkedList<>();
for (int dir = 0; dir < 8; dir++) {
queue.add(new Tuple(i, j, dir));
}
PriorityQueue<Tuple>[] cntArr = new PriorityQueue[4];
for (int q = 0; q < 4; q++) {
cntArr[q] = new PriorityQueue<>();
cntArr[q].add(new Tuple(i, j, q));
}
while (!queue.isEmpty()) {
Tuple tuple = queue.poll();
int x = tuple.x;
int y = tuple.y;
int direction = tuple.direction;
int oneDirection = getOneDirection(direction);
if (x <= 0 || y <= 0 || x > N || y > N) continue;
if (visit[x][y][oneDirection]) continue;
if (arr[i][j] != arr[x][y]) continue;
if (x != i || y != j) {
cntArr[oneDirection].add(new Tuple(x, y, direction));
}
queue.add(move(x, y, direction));
}
for (PriorityQueue<Tuple> cnt : cntArr) {
if (cnt.size() == 5) {
win = arr[i][j];
Tuple first = cnt.poll();
winSite[0] = first.x;
winSite[1] = first.y;
visit[first.x][first.y][getOneDirection(first.direction)] = true;
}
for (Tuple t : cnt) {
visit[t.x][t.y][getOneDirection(t.direction)] = true;
}
}
}
public static Tuple move(int x, int y, int direction) {
if (direction == 0) return new Tuple(x-1, y, direction);
else if (direction == 1) return new Tuple(x-1, y+1, direction);
else if (direction == 2) return new Tuple(x, y+1, direction);
else if (direction == 3) return new Tuple(x+1, y+1, direction);
else if (direction == 4) return new Tuple(x+1, y, direction);
else if (direction == 5) return new Tuple(x+1, y-1, direction);
else if (direction == 6) return new Tuple(x, y-1, direction);
else return new Tuple(x-1, y-1, direction);
}
public static int getOneDirection(int direction) {
if (direction == 0 || direction == 4) return 0;
else if (direction == 1 || direction == 5) return 1;
else if (direction == 2 || direction == 6) return 2;
else return 3;
}
public static class Tuple implements Comparable<Tuple>{
int x;
int y;
int direction;
public Tuple(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
@Override
public int compareTo(Tuple t) {
if (this.y == t.y) {
return this.x - t.x;
}
return this.y - t.y;
}
}
public static void print() throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(win+"\n");
if (win != 0) {
bw.write(winSite[0]+" "+winSite[1]);
}
bw.flush();
bw.close();
}
public static void init() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
arr = new int[N+1][N+1];
visit = new boolean[N+1][N+1][4];
winSite = new int[2];
for (int i = 1; i <= N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 1; j <= N; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
br.close();
}
}
4. 결과 및 회고
이미 방문했던 위치에서 동일한 방향으로 뻗어나갔을 경우에는 다시 방문하지 않도록 visit 배열을 3차원 배열로 선언해주었다. 시간 초과 날까봐 3차원 배열로 선언했는데,, 근데 이렇게 안해도 시간초과 안날거같다. ㅎㅎ
'문제풀이 > 백준' 카테고리의 다른 글
[JAVA] BOJ 백준 9328번 - 열쇠 (1) | 2023.10.29 |
---|---|
[JAVA] BOJ 백준 1103번 - 게임 (1) | 2023.10.29 |
[JAVA] BOJ 백준 5525번 - IOIOI (1) | 2023.10.01 |
[JAVA] BOJ 백준 17135번 - 캐슬 디펜스 (0) | 2023.10.01 |
[JAVA] BOJ 백준 2011번 - 암호코드 (0) | 2023.09.27 |
댓글