#include <iostream>
#include <memory.h>
#include <vector>
#include <queue>
#include <algorithm>
#define MAX_N 100
#define MAX_WORM 11
#define BLACK_HOLE -1
#define EMPTY 0
#define BLOCK_ONE 1
#define BLOCK_TWO 2
#define BLOCK_THREE 3
#define BLOCK_FOUR 4
#define BLOCK_FIVE 5
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
using namespace std;
int N;
int board[MAX_N][MAX_N];
int dx[4] = { -1, 1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };
vector<pair<int, int>> startPoints;
vector<pair<int, int>> wormTable[MAX_WORM];
int startX, startY;
int ans = 0;
void init()
{
memset(board, 0, sizeof(board));
startPoints.clear();
ans = 0;
for (int i = 0; i < MAX_WORM; i++) {
wormTable[i].clear();
}
}
void input()
{
init();
cin >> N;
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
cin >> board[r][c];
if (board[r][c] == EMPTY) startPoints.push_back(make_pair(r, c));
else if (board[r][c] > BLOCK_FIVE) wormTable[board[r][c]].push_back(make_pair(r, c));
}
}
}
int getReverseDir(int dir)
{
if (dir == UP) return DOWN;
if (dir == DOWN) return UP;
if (dir == LEFT) return RIGHT;
if (dir == RIGHT) return LEFT;
}
int getDirBlockOne(int dir)
{
if (dir == DOWN) return RIGHT;
if (dir == LEFT) return UP;
return getReverseDir(dir);
}
int getDirBlockTwo(int dir)
{
if (dir == UP) return RIGHT;
if (dir == LEFT) return DOWN;
return getReverseDir(dir);
}
int getDirBlockThree(int dir)
{
if (dir == UP) return LEFT;
if (dir == RIGHT) return DOWN;
return getReverseDir(dir);
}
int getDirBlockFour(int dir)
{
if (dir == RIGHT) return UP;
if (dir == DOWN) return LEFT;
return getReverseDir(dir);
}
int getDirBlockFive(int dir)
{
return getReverseDir(dir);
}
void passWormHole(int wormNum, int cx, int cy, int& nx, int& ny)
{
for (int i = 0; i < wormTable[wormNum].size(); i++) {
pair<int, int> wormPos = wormTable[wormNum][i];
if (cx == wormPos.first && cy == wormPos.second) continue;
nx = wormPos.first;
ny = wormPos.second;
}
}
void playGame(int xpos, int ypos, int dir)
{
int score = 0;
int cx = xpos;
int cy = ypos;
int cdir = dir;
int nx, ny;
int cnt = 0;
while (true) {
ans = max(ans, score);
nx = cx + dx[cdir];
ny = cy + dy[cdir];
if (nx < 0 || nx >= N || ny < 0 || ny >= N) {
cdir = getReverseDir(cdir);
cx = nx;
cy = ny;
score++;
continue;
}
if (nx == startX && ny == startY) break;
if (board[nx][ny] == BLACK_HOLE) break;
if (board[nx][ny] <= BLOCK_FIVE && board[nx][ny] >= BLOCK_ONE) {
score++;
if (board[nx][ny] == BLOCK_ONE) cdir = getDirBlockOne(cdir);
else if (board[nx][ny] == BLOCK_TWO) cdir = getDirBlockTwo(cdir);
else if (board[nx][ny] == BLOCK_THREE) cdir = getDirBlockThree(cdir);
else if (board[nx][ny] == BLOCK_FOUR) cdir = getDirBlockFour(cdir);
else if (board[nx][ny] == BLOCK_FIVE) cdir = getDirBlockFive(cdir);
}
else if (board[nx][ny] > BLOCK_FIVE) { // 웜홀
int wormNum = board[nx][ny];
int wormX = nx;
int wormY = ny;
passWormHole(wormNum, wormX, wormY, nx, ny);
}
cx = nx;
cy = ny;
}
}
void solution()
{
for (auto ele : startPoints) {
startX = ele.first;
startY = ele.second;
for (int dir = 0; dir < 4; dir++) {
playGame(ele.first, ele.second, dir);
}
}
}
void test()
{
input();
for (auto ele : startPoints) {
startX = ele.first;
startY = ele.second;
for (int dir = 0; dir < 4; dir++) {
playGame(ele.first, ele.second, dir);
cout << ans << endl;
}
break;
}
}
int main(int argc, char** argv)
{
int test_case;
int T = 0;
// freopen("input.txt", "r", stdin);
cin >> T;
// test();
for (test_case = 1; test_case <= T; ++test_case)
{
input();
solution();
cout << "#" << test_case << " " << ans << endl;
}
return 0;//정상종료시 반드시 0을 리턴해야합니다.
}
Leave a comment