평이한 수준의 문제였으나 웜홀에 대한 처리가 미숙했다. (44번 case 에서 fail)
아래의 웜홀 검사에서 break를 사용하지 않아, 좌표가 업데이트된 이후, 또다시 원래의 웜홀로 돌아오게 되었다..
무언가를 탐색하고 업데이트를 하면 반드시 루프를 종료할 것.
이런 부분은 정말 찾기가 힘든것 같다. 평소에 주의하여 코딩하는 수 밖에 없다.
for (P p : wh) {
if (p.id == brick && (p.x != x || p.y != y)) {// 웜홀 이동.
update(p.x, p.y);
break;
}
}
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Solution {
static int N, ans;
static boolean DBG = false;
static int[][] map;
static int[] dx = { -1, 1, 0, 0 };
static int[] dy = { 0, 0, -1, 1 };
private static int max;
static final int UP = 0;
static final int DOWN = 1;
static final int LEFT = 2;
static final int RIGHT = 3;
static class Ball {
int x, y;
int d;// direction
int cnt;
Ball(int x, int y, int d) {
this.x = x;
this.y = y;
this.d = d;
this.cnt = 0;
}
void process(int brick) {
switch (brick) {
case 1:
if (d == UP)
d = DOWN;
else if (d == DOWN)
d = RIGHT;
else if (d == LEFT)
d = UP;
else if (d == RIGHT)
d = LEFT;
count();
break;
case 2:
if (d == UP)
d = RIGHT;
else if (d == DOWN)
d = UP;
else if (d == LEFT)
d = DOWN;
else if (d == RIGHT)
d = LEFT;
count();
break;
case 3:
if (d == UP)
d = LEFT;
else if (d == DOWN)
d = UP;
else if (d == LEFT)
d = RIGHT;
else if (d == RIGHT)
d = DOWN;
count();
break;
case 4:
if (d == UP)
d = DOWN;
else if (d == DOWN)
d = LEFT;
else if (d == LEFT)
d = RIGHT;
else if (d == RIGHT)
d = UP;
count();
break;
case 5:
if (d == UP)
d = DOWN;
else if (d == DOWN)
d = UP;
else if (d == LEFT)
d = RIGHT;
else if (d == RIGHT)
d = LEFT;
count();
break;
case 6:
case 7:
case 8:
case 9:
case 10:
for (P p : wh) {
if (p.id == brick && (p.x != x || p.y != y)) {// 웜홀 이동.
update(p.x, p.y);
break;
}
}
break;
}
}
public void count() {
cnt++;
}
public void update(int x, int y) {
this.x = x;
this.y = y;
}
}
static ArrayList<P> bh, wh;
static class P {
public int x, y;
public int id;
P(int x, int y) {
this.x = x;
this.y = y;
this.id = -1;
}
P(int x, int y, int id) {
this.x = x;
this.y = y;
this.id = id;
}
}
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int T;
T = Integer.parseInt(br.readLine());
for (int test_case = 1; test_case <= T; test_case++) {
N = Integer.parseInt(br.readLine());
max = 0;
map = new int[N][N];
wh = new ArrayList<>();
bh = new ArrayList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if (map[i][j] >= 6 && map[i][j] <= 10) {
wh.add(new P(i, j, map[i][j]));
}
if (map[i][j] == -1) {
bh.add(new P(i, j));
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 0) {
int value = simulation(i, j);
max = Math.max(value, max);
}
}
}
System.out.println("#" + test_case + " " + max);
}
}
private static int simulation(int r, int c) {
int max = 0;
Ball ball;
// 한지점에서 상하좌우의 이동경우 중, 최대값을 구하여 리턴
for (int i = 0; i < 4; i++) {
int nr = r;
int nc = c;
ball = new Ball(nr, nc, i);
while (true) {
nr = ball.x + dx[ball.d];
nc = ball.y + dy[ball.d];
// 경계선인 경우,
if (nr < 0 || nr >= N || nc < 0 || nc >= N) {
// 방향을 변경
ball.d = reverseDirection(ball.d);
ball.update(nr, nc);
ball.count();
continue;
}
// 블랙홀 또는 시작위치인 경우,
if (map[nr][nc] == -1 || (nr == r && nc == c)) {
// 종료
max = Math.max(max, ball.cnt);
break;
}
// 빈공간인 경우.
if (map[nr][nc] == 0) {
// 전진
ball.update(nr, nc);
} else {
// 이동 후, 기타 블럭 처리
ball.update(nr, nc);
ball.process(map[nr][nc]);
}
}
}
return max;
}
static int reverseDirection(int d) {
if (d == UP)
return DOWN;
if (d == DOWN)
return UP;
if (d == RIGHT)
return LEFT;
return RIGHT;
}
}
'PS > BOJ' 카테고리의 다른 글
5648 원자소멸 시뮬레이션 (0) | 2022.05.20 |
---|---|
5656 벽돌깨기 (0) | 2022.05.17 |
5658 보물상자 비밀번호 (0) | 2022.05.16 |
5644 무선 충전 (0) | 2022.05.16 |
4014 활주로 탐색 (0) | 2022.05.15 |