
이 문제는 각 사람들이 각 계단에 갈 수 있는 모든 경우의 수를 시뮬레이션하고 그 중 가장 적은 시간이 걸리는 경우의 시간을 출력하는 문제이다.
계단을 이용하는 사람들의 걸리는 시간을 계산하는 방법
- 인수로 들어오는 vector 배열을 가지고 각 계단을 이용하는 사람들을 각각 처리한다. 이 때 계단까지 오는 시간을 거리로 계산하여 활용한다.
 - 계단을 이용하는 사람들이 계단까지 오는데 걸리는 시간을 오름차순 정렬한다.
 - 가까운 사람부터 도착하는 것으로 생각하여 처리하는데 이 때 게단을 이용하는 사람이 3명 이하이면 가장 마지막에 오는 사람이 계단을 다 내려가는 시간이 걸리는 시간이 된다. 따라서 이 때는 마지막에 도착한 사람이 내려가는데 걸리는 시간을 계산하면 된다.
 - 계단을 이용하는 사람이 3명보다 많다면 queue를 이용하여 처리한다. 우선 3명을 queue에 넣고 시작한다.
 - queue의 맨앞 사람을 꺼내서 이 사람이 계단을 다 내려간 시간을 계산한다. 그리고 4번째에 계단을 도착한 사람의 시간과 비교한다. 만약 다 내려간 시간보다 도착한 시간이 더 빠르다면 기다려야하므로 이는 기다리는 시간을 더해서 도착한 시간을 갱신하고 queue에 push한다. 그렇지 않다면 도착한 시간을 수정하지 않고 그대로 queue에 push한다.
 - 5번 과정을 queue가 빌 때까지 반복한다. 그러면 가장 마지막에 queue에 들어온 사람이 계단을 다 내려가는 시간이 해당 계단을 이용하는 사람들이 걸리는 시간과 같다. 이는 두번째 계단도 마찬가지로 수행한다.
 
//시작 : 21:31
//끝 : 22:50
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int N;
struct pos {
	int r;
	int c;
};
vector<pos> person; //사람의 위치 저장 벡터
vector<pair<pos, int>> stair; //계단의 위치와 길이 저장 벡터
int result = 987654321; //최종 결과
void print(vector<int> v) {
	for (int i = 0; i < person.size(); i++) {
		cout << v[i] << " ";
	}
	cout << '\n';
}
//입력
void input() {
	cin >> N;
	for (int r = 0; r < N; r++) {
		for (int c = 0; c < N; c++) {
			int tmp;
			cin >> tmp;
			if (tmp == 1) {
				person.push_back({ r, c });
			}
			else if (tmp >= 2) {
				stair.push_back({ {r, c}, tmp });
			}
		}
	}
}
void init() {
	person.clear(); //다음을 위해 사람 위치 벡터 초기화
	stair.clear(); //다음을 위해 계단 위치 벡터 초기화
	result = 987654321; //다음을 위해 최종 결과 초기화
}
//현재 들어온 경우의 수의 걸리는 시간 계산 함수
void solve(vector<int> v) {
	//print(v);
	//a와 b에 각 계단에 갈 사람들과 계단의 거리 추가 
	//a는 첫번째 계단 이용자
	//b는 두번째 계단 이용자
	vector<int> a;
	vector<int> b;
	for (int i = 0; i < v.size(); i++) {
		if (v[i] == 0) {
			pos tmp = person[i];
			int distance = abs(stair[0].first.r - tmp.r) + abs(stair[0].first.c - tmp.c);
			a.push_back(distance);
		}
		else {
			pos tmp = person[i];
			int distance = abs(stair[1].first.r - tmp.r) + abs(stair[1].first.c - tmp.c);
			b.push_back(distance);
		}
	}
	
	
	queue<int> q_a;
	queue<int> q_b;
	
	int time_a; //첫번째 계단 이용자의 걸리는 시간
	int time_b; //두번째 계단 이용자의 걸리는 시간
	
	if (a.size() == 0) {//첫번째 계단을 이용하는 사람이 없는 경우
		time_a = 0; //걸리는 시간 0
	}
	else if (a.size() <= 3) { //첫번째 계단을 이용하는 사람이 3명 이하인 경우 
		sort(a.begin(), a.end()); //도착하는 시간 오름차순 정렬 
		time_a = a[a.size() - 1] + stair[0].second; //마지막 사람이 계단을 다 내려간 시간이 결과가 됨
	}
	else { //첫번째 계단을 이용하는 사람이 3명 초과인 경우
		sort(a.begin(), a.end()); //도착하는 시간 오름차순 정렬
		//queue에 3명 넣기
		q_a.push(a[0]);
		q_a.push(a[1]);
		q_a.push(a[2]);
		int idx = 3; //첫번째계단 이용자를 선택하기 위한 인덱스
		while (!q_a.empty()) { //queue가 빌 때가지 반복
			int cur_time = q_a.front() + stair[0].second; //맨 앞 사람의 나가는 시간
			q_a.pop();
			if (idx < a.size()) { //이용자가 남아 있는 경우
				if (cur_time > a[idx]) { //맨 앞 사람이 나가는 시간보다 다음 queue에 넣을 사람의 도착시간이 빠른 경우 
					a[idx] += cur_time - a[idx]; //queue에 넣을 사람의 도착 시간을 맨 앞사람이 나가는 시간과의 차이만큼 딜레이 시킨다.
					q_a.push(a[idx]); //queue에 넣는다.
				}
				else { //맨 앞 사람이 나가는 시간보다 다음 queue에 넣을 사람의 도착시간이 느린 경우 
					q_a.push(a[idx]); //도착 시간 수정없이 queeu에 넣는다.
				}
				idx++; //다음 사람을 선택하기 위해 ++
			}
			time_a = cur_time; //마지막까지 수행하면 결국 time_a에는 첫번째 계단을 이용하는 사람들이 걸리는 시간이 저장된다.
		}
	}
	
	//두번째 계단도 첫번째 계단과 동일하게 적용된다.
	if (b.size() == 0) {
		time_b = 0;
	}
	else if (b.size() <= 3) {
		sort(b.begin(), b.end());
		time_b = b[b.size() - 1] + stair[1].second;
	}
	else {
		sort(b.begin(), b.end());
		q_b.push(b[0]);
		q_b.push(b[1]);
		q_b.push(b[2]);
		int idx = 3;
		while (!q_b.empty()) {
			int cur_time = q_b.front() + stair[1].second;
			q_b.pop();
			if (idx < b.size()) {
				if (cur_time > b[idx]) {
					b[idx] += cur_time - b[idx];
					q_b.push(b[idx]);
				}
				else {
					q_b.push(b[idx]);
				}
				idx++;
			}
			time_b = cur_time;
		}
	}
	//cout << time_a << " " << time_b << '\n';
	int result_time = max(time_a, time_b); //첫번째 계단과 두번째 계단에 걸리는 시간 중 오래 걸리는 것이 최종 걸리는 시간이다.
	//문제의 해답은 모든 경우의 최종 걸리는 시간 중 최소 값이다.
	result = min(result_time, result);
	
}
//모든 경우의 수 파악을 위한 DFS
void DFS(vector<int> v, int cur, int p) {
	if (cur == p) { //모든 사람의 경우를 선택한 경우
		solve(v); //걸리는 시간 계산
		return; //종료
	}
	//0은 첫번째 계단, 1은 두번째 계단
	for (int i = 0; i <= 1; i++) {
		v.push_back(i); 
		DFS(v, cur + 1, p); //다음 사람의 경우의 수 찾기 위함
		v.pop_back(); //다른 경우의 수 찾기 위함
	}
}
int main(int argc, char** argv)
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int test_case;
	int T;
	
	cin >> T;
	
	for (test_case = 1; test_case <= T; ++test_case)
	{
		init();
		input();
		vector<int> v;
		DFS(v, 0, person.size());
		cout << "#" << test_case << " " << result + 1 << '\n';
	}
	return 0;//정상종료시 반드시 0을 리턴해야합니다.
}