#include #include // #define DEBUG typedef struct space { int sp[11]; // 0 = 上部の上面、1 〜 4 = 上部の奥面から時計回り、 // 5 = 水平面(上部の下面および下部の上面)、 // 6 〜 9 = 下部の奥面から時計回り、10 = 下部の下面 } space; static int solve(space *area[7][7], int num_remaining_spaces); static int fold_and_solve(space *area[7][7], int left_x, int left_y, int right_x, int right_y, int rotation_count, int num_remaining_spaces); static void rotate_space(space *sp, int count); static void flip_space(space *sp); static int check_space(space *sp); static void debug_print_space(space *sp); int main() { #ifdef TARGET_RT_MAC_CFM FILE *stream = fopen("input", "r"); #else FILE *stream = stdin; #endif int number_of_questions; fscanf(stream, "%d", &number_of_questions); for (; number_of_questions > 0; number_of_questions--) { int x, y, is_valid = 1; space spaces[6], *area[7][7]; memset(spaces, 0, sizeof(spaces)); memset(area, 0, sizeof(area)); for (y = 0; y < 5; y++) { for (x = 0; x < 5; x++) { int num; fscanf(stream, "%d", &num); if (num != 0) { if (num < 1 || num > 6 || spaces[num - 1].sp[5] != 0) is_valid = 0; spaces[num - 1].sp[5] = num; area[x + 1][y + 1] = &spaces[num - 1]; } } } printf("%s\n", (is_valid && solve(area, 6) ? "true" : "false")); } return 0; } static int solve(space *area[7][7], int num_remaining_spaces) { int x, y; if (num_remaining_spaces <= 1) return 1; for (y = 0; y < 7; y++) { for (x = 0; x < 7; x++) { if (!area[x][y]) continue; // 周囲に1つしかオブジェクトがないなら、折ることができる if (area[x][y - 1] && !area[x + 1][y] && !area[x][y + 1] && !area[x - 1][y]) { if (fold_and_solve(area, x, y, x, y - 1, 3, num_remaining_spaces)) return 1; } else if (!area[x][y - 1] && area[x + 1][y] && !area[x][y + 1] && !area[x - 1][y]) { if (fold_and_solve(area, x, y, x + 1, y, 0, num_remaining_spaces)) return 1; } else if (!area[x][y - 1] && !area[x + 1][y] && area[x][y + 1] && !area[x - 1][y]) { if (fold_and_solve(area, x, y, x, y + 1, 1, num_remaining_spaces)) return 1; } else if (!area[x][y - 1] && !area[x + 1][y] && !area[x][y + 1] && area[x - 1][y]) { if (fold_and_solve(area, x, y, x - 1, y, 2, num_remaining_spaces)) return 1; } } } return 0; } // 左の空間を折り曲げて右の空間へ重ね、問題が生じなければ solve() を行う。 // いずれの空間も、折る前に rotation_count だけ rotate_space() される。 static int fold_and_solve(space *area[7][7], int left_x, int left_y, int right_x, int right_y, int rotation_count, int num_remaining_spaces) { space saved_left, saved_right; space *left = area[left_x][left_y], *right = area[right_x][right_y]; int switcher; area[left_x][left_y] = NULL; memcpy(&saved_left, left, sizeof(space)); memcpy(&saved_right, right, sizeof(space)); rotate_space(left, rotation_count); rotate_space(right, rotation_count); for (switcher = 0; switcher <= 1; switcher++) { // 山折りと谷折りを両方試す #ifdef DEBUG printf("L%c (%d, %d) ", (switcher ? '-' : '+'), left_x, left_y); debug_print_space(&saved_left); printf("R%c (%d, %d) ", (switcher ? '-' : '+'), right_x, right_y); debug_print_space(&saved_right); #endif if (switcher == 1) { flip_space(left); flip_space(right); } // 折った時にすべてが右の空間内に収まらないか、あるいは面のオーバーラップが生じるならやめる if (left->sp[6] || left->sp[7] || left->sp[8] || left->sp[9] || left->sp[10] || right->sp[6] || right->sp[7] || right->sp[8] || right->sp[9] || right->sp[10] || (left->sp[0] && right->sp[2]) || (left->sp[1] && right->sp[1]) || (left->sp[2] && right->sp[5]) || (left->sp[3] && right->sp[3]) || (left->sp[4] && right->sp[0]) || (left->sp[5] && right->sp[4])) continue; // 折って、目の配置に問題がなければ solve() right->sp[2] |= left->sp[0], right->sp[1] |= left->sp[1], right->sp[5] |= left->sp[2], right->sp[3] |= left->sp[3], right->sp[0] |= left->sp[4], right->sp[4] |= left->sp[5]; if (check_space(right)) { if (switcher == 1) flip_space(right); rotate_space(right, 4 - rotation_count); #ifdef DEBUG printf("=> (%d, %d) ", right_x, right_y); debug_print_space(right); #endif if (solve(area, num_remaining_spaces - 1)) return 1; } if (switcher == 0) memcpy(area[right_x][right_y], &saved_right, sizeof(space)); } area[left_x][left_y] = left; memcpy(area[left_x][left_y], &saved_left, sizeof(space)); memcpy(area[right_x][right_y], &saved_right, sizeof(space)); return 0; } // fold_and_solve // 空間を反時計周りに count 回だけ回転させる static void rotate_space(space *sp, int count) { space old_sp; memcpy(&old_sp, sp, sizeof(space)); sp->sp[1 + 0] = old_sp.sp[1 + (0 + count) % 4]; sp->sp[1 + 1] = old_sp.sp[1 + (1 + count) % 4]; sp->sp[1 + 2] = old_sp.sp[1 + (2 + count) % 4]; sp->sp[1 + 3] = old_sp.sp[1 + (3 + count) % 4]; sp->sp[6 + 0] = old_sp.sp[6 + (0 + count) % 4]; sp->sp[6 + 1] = old_sp.sp[6 + (1 + count) % 4]; sp->sp[6 + 2] = old_sp.sp[6 + (2 + count) % 4]; sp->sp[6 + 3] = old_sp.sp[6 + (3 + count) % 4]; } // 空間の上下を反転する static void flip_space(space *sp) { space old_sp; memcpy(&old_sp, sp, sizeof(space)); sp->sp[0] = old_sp.sp[10], sp->sp[10] = old_sp.sp[0]; memcpy(sp->sp + 1, old_sp.sp + 6, sizeof(int) * 4); memcpy(sp->sp + 6, old_sp.sp + 1, sizeof(int) * 4); } // 目の配置が正しいかどうか調べる static int check_space(space *sp) { #define generate_one_check(index1, index2) \ if (sp->sp[index1] && sp->sp[index2] && sp->sp[index1] + sp->sp[index2] != 7) \ return 0; generate_one_check(0, 5); generate_one_check(1, 3); generate_one_check(2, 4); generate_one_check(5, 10); generate_one_check(6, 8); generate_one_check(7, 9); return 1; #undef generate_one_check } static void debug_print_space(space *sp) { printf("[%d] [%d %d %d %d] [%d] [%d %d %d %d] [%d]\n", sp->sp[0], sp->sp[1], sp->sp[2], sp->sp[3], sp->sp[4], sp->sp[5], sp->sp[6], sp->sp[7], sp->sp[8], sp->sp[9], sp->sp[10]); }