#define _CRT_SECURE_NO_WARNINGS
/*
2019-00-00
장환석
*/
#include <cstdio>
#include <vector>
#include <algorithm>
#include <deque>
using namespace std;
typedef struct person{
int r;
int c;
int onstair;
int dst_a; //계단 a까지와의 거리
int dst_b; //계단 b까지와의 거리
person() {
r = -1;
c = -1;
onstair = -1;
dst_a = -1;
dst_b = -1;
}
person(int _r, int _c, int _onstair, int _dst_a, int _dst_b) {
r = _r;
c = _c;
onstair = _onstair;
dst_a = _dst_a;
dst_b = _dst_b;
}
};
typedef struct stair {
int r;
int c;
int len;
stair() {
r = -1;
c = -1;
len = -1;
}
stair(int _r, int _c, int _len) {
r = _r;
c = _c;
len = _len;
}
};
int map[10][10];
vector<person> people;
stair sa, sb;
vector<person> wait_a, wait_b; //계단 a와 b를 기다리고 있는 사람들
deque<person> on_a, on_b;//계단 a와 b에 타고 있는 사람들
bool compareA(person a, person b) {
if (a.dst_a != b.dst_a) return a.dst_a < b.dst_a;
else return a.r < b.r;
}
bool compareB(person a, person b) {
if (a.dst_b != b.dst_b) return a.dst_b < b.dst_b;
else return a.r < b.r;
}
int goDown(void) {
//여기에서 wait_a를 sort해버려서 문제가 발생했었다.
vector<person> wa, wb; //계단 a와 b를 기다리고 있는 사람들
printf("===A===\n");
for (int i = 0; i < wait_a.size(); i++) {
wa.push_back(wait_a[i]);
printf("%d, %d\n", wa[i].r, wa[i].c);
}
printf("===B===\n");
for (int i = 0; i < wait_b.size(); i++) {
wb.push_back(wait_b[i]);
printf("%d, %d\n", wb[i].r, wb[i].c);
}
//wait_a 계단 거리별로 sort
sort(wa.begin(), wa.end(), compareA);
//wait_b 계단 거리별로 sort
sort(wb.begin(), wb.end(), compareB);
//계단 내려 보내기 진행
int curr_t = 0;
vector<person>::iterator it_a, it_b;
it_a = wa.begin();
it_b = wb.begin();
//마지막 사람까지 다 탔고, 타고 있는 사람 없으면
while (true) {
curr_t += 1;
printf("============curr_t %d초 째에=========\n", curr_t);
while (!on_a.empty() && (on_a[0].onstair == sa.len )) {
printf("A 내리게 하기\n");
on_a.pop_front();
}
while (!on_b.empty() && (on_b[0].onstair == sb.len )) {
printf("B 내리게 하기\n");
on_b.pop_front();
}
//wait_a에 사람이 있고, on_a에 더 태울 수 있고, 다음에 탈 사람이 도착한 상태이면
while (it_a != wa.end() && on_a.size() < 3 && (*it_a).dst_a <= curr_t) {
printf("A에 사람 태우고\n");
on_a.push_back(*it_a);
++it_a;
}
while (it_b != wb.end() && on_b.size() < 3 && (*it_b).dst_b <= curr_t) {
printf("B에 사람 태우고\n");
on_b.push_back(*it_b);
++it_b;
}
//계단 내려가게 하고 다 내려가면 내리게 하기 //첫 째사람이 항상 가장 많이 계단을 내려갔을 것이다.
for (int i = 0; i < on_a.size(); i++) {
printf("A 계단에서 내려가게 하기\n");
on_a[i].onstair += 1;
}
for (int i = 0; i < on_b.size(); i++) {
printf("B 계단에서 내려가게 하기\n");
on_b[i].onstair += 1;
}
if (it_a == wa.end() && it_b == wb.end() && on_a.empty() && on_b.empty()) {
break;
}
}
printf("REUTNR %d\n\n", curr_t);
return curr_t;
}
void setStair(int x, int len, int &ans) {
if (x == len) {
//각 계단에 할당된 사람들을 내려보내기
int tans = goDown();
ans = ans > tans ? tans : ans;
return;
}
//x번째 사람이 계단 a를 사용하는 경우
wait_a.push_back(people[x]);
setStair(x + 1, len, ans);
wait_a.pop_back();
//x번째 사람이 계단 b를 사용하는 경우
wait_b.push_back(people[x]);
setStair(x + 1, len, ans);
wait_b.pop_back();
}
int main(void) {
int tcase = 0; scanf("%d", &tcase);
for (int tc = 1; tc <= tcase; tc++) {
people.clear();
sa = { -1,-1, -1 };
sb = { -1,-1, -1 };
wait_a.clear();
wait_b.clear();
on_a.clear();
on_b.clear();
int ans = 0xFFFFFFF, n = 0; scanf("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &map[i][j]);
if (map[i][j] == 1) {
people.push_back(person(i,j,-1,-1,-1));
//printf("%d, %d 위치에 있는 사람 push\n", i, j);
}
else if (map[i][j] >= 2) {
if (sa.r == -1) {
sa.r = i;
sa.c = j;
sa.len = map[i][j];
//printf("%d, %d, %d 위치에 있는 계단 세팅\n",sa.r, sa.c, sa.len);
}
else {
sb.r = i;
sb.c = j;
sb.len = map[i][j];
//printf("%d, %d, %d 위치에 있는 계단 세팅\n", sb.r, sb.c, sb.len);
}
}
}
}
for (int i = 0; i < people.size(); i++) {
people[i].dst_a = abs(people[i].r - sa.r) + abs(people[i].c - sa.c);
people[i].dst_b = abs(people[i].r - sb.r) + abs(people[i].c - sb.c);
}
setStair(0, people.size(), ans);
printf("#%d %d\n", tc, ans);
}
return 0;
}