import java.io.*;
import java.util.*;
/*
사용하는 클래스명이 Solution 이어야 하므로, 가급적 Solution.java 를 사용할 것을 권장합니다.
이러한 상황에서도 동일하게 java Solution 명령으로 프로그램을 수행해볼 수 있습니다.
*/
class Solution
{
private static final int EMPTY = 0, BLACK_HOLE = -1;
private static int[][] blockDir = {{},
{2, 0, 3, 1},
{2, 3, 1, 0},
{1, 3, 0, 2},
{3, 2, 0, 1},
{2, 3, 0, 1}};
private static int[][] map = new int[100][100]; //map we're examining
private static int[][][] wormHoles = new int[5][2][2]; //wormhole start/end position
private static int dirMove[][] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
/* for dir variable
* 0 : East
* 1 : South
* 2 : West
* 3 : North
*/
private static int N;
public static void main(String args[]) throws Exception
{
/*
아래의 메소드 호출은 앞으로 표준 입력(키보드) 대신 input.txt 파일로부터 읽어오겠다는 의미의 코드입니다.
여러분이 작성한 코드를 테스트 할 때, 편의를 위해서 input.txt에 입력을 저장한 후,
이 코드를 프로그램의 처음 부분에 추가하면 이후 입력을 수행할 때 표준 입력 대신 파일로부터 입력을 받아올 수 있습니다.
따라서 테스트를 수행할 때에는 아래 주석을 지우고 이 메소드를 사용하셔도 좋습니다.
단, 채점을 위해 코드를 제출하실 때에는 반드시 이 메소드를 지우거나 주석 처리 하셔야 합니다.
*/
System.setIn(new FileInputStream("res/input.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T;
T=Integer.parseInt(br.readLine().trim());
for(int test_case = 1; test_case <= T; test_case++)
{
int maxScore = 0;
//obtain map input and initialize all metadatas
N = Integer.parseInt(br.readLine().trim());
//visited = new boolean[N][N][4];
for (int idx = 0; idx < 5; ++idx) {
wormHoles[idx][0][0] = -1;
}
for (int row = 0; row < N; ++row) {
StringTokenizer input = new StringTokenizer(br.readLine());
for (int col = 0; col < N; ++col) {
map[row][col] = Integer.parseInt(input.nextToken());
// System.out.printf("%d ", map[row][col]);
if (map[row][col] > 5) { //it's a wormhole.
int idx = wormholeIdx(map[row][col]);
if (wormHoles[idx][0][0] == -1) {
wormHoles[idx][0][0] = row;
wormHoles[idx][0][1] = col;
} else {
wormHoles[idx][1][0] = row;
wormHoles[idx][1][1] = col;
}
}
}
// System.out.printf("\n");
}
//we calculate the score.
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
if (map[row][col] != 0) continue;
for (int dir = 0; dir < 4; ++dir) {
maxScore = Math.max(maxScore, DFS(row, col, dir));
}
}
}
bw.write("#" + test_case + " " + maxScore + '\n');
bw.flush();
}
bw.close();
}
private static int wormholeIdx(int n)
{
return n - 6;
}
//finding score of current position and dir, with saved results...
private static int DFS(int startRow, int startCol, int dir) {
int score = 0;
int curRow = startRow;
int curCol = startCol;
int curDir = dir;
int metBlockCnt = 0;
// int iter = 0; //debugging
while (true) {
// System.out.printf("iter : %d, row : %d, col : %d, dir : %d\n", iter, curRow, curCol, curDir);
// ++iter;
int newRow = curRow + dirMove[curDir][0];
int newCol = curCol + dirMove[curDir][1];
if (!(newRow >= 0 && newRow < N && newCol >= 0 && newCol < N)) {
//we met the wall. Impossible to move.
//we reflect. score is added.
score = metBlockCnt*2 + 1;
break;
}
else if (map[newRow][newCol] == BLACK_HOLE) {
//we met the black hole. finished.
score = metBlockCnt;
break;
}
else if (map[newRow][newCol] >= 6) {
//we met the wormhole.
int idx = wormholeIdx(map[newRow][newCol]);
int pos1r = wormHoles[idx][0][0], pos1c = wormHoles[idx][0][1];
if (pos1r == newRow && pos1c == newCol) {
curRow = wormHoles[idx][1][0];
curCol = wormHoles[idx][1][1];
} else {
curRow = pos1r; curCol = pos1c;
}
}
else if (map[newRow][newCol] != EMPTY) {
//we met the block. update position and continue moving.
//metBlockCnt also increased. we may need to go into record mode.
int newDir = blockDir[map[newRow][newCol]][curDir];
if (newDir == (curDir + 2) % 4) {
//reflected. go into record mode.
score = metBlockCnt*2 + 1;
break;
} else {
++metBlockCnt;
curRow = newRow;
curCol = newCol;
curDir = newDir;
}
}
else if (newRow == startRow && newCol == startCol) {
//returned to original position somehow by teleporting.
score = metBlockCnt;
break;
}
else {
//we just update as usual.
curRow = newRow;
curCol = newCol;
}
}
// System.out.printf("after %d iter for startRow %d and startCol %d and startDir %d, score %d achieved.\n", iter, startRow, startCol, dir, score);
return score;
}
}
시뮬레이션/구현 문제다. DFS랑 유사하다.
100x100이 최대이며 시작점에 다시 도달하거나 블랙홀을 만나면 종료되는 것을 고려시 대략 100 x 100 x 2 x 4 x 100 x 100 = 8 * 10^8이 최악의 테스트케이스 경우이지만 실제로 이 경우에 도달하는 경우가 별로 없어서 생각보다 널널하다...고 볼 수 있지만 유의해야할게 몇가지 있다.
BufferedReader
의 경우 trim()
을 사용하는 것을 습관화할 필요가 있다. (삼성 한정) N read시에 공백이 있어서 br.readLine()
을 그냥 parse하면 runtime error이 발생한다.