{"model_name":"qwen3.5-27b","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\ndouble calculate_p(int r, int s) {\n    if (s == 0) return 0.0;\n    double ratio = (double)min(r, s) / max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble calculate_total_p(const vector<Company>& companies) {\n    double total = 0;\n    for (auto& c : companies) {\n        int s = (c.c - c.a) * (c.d - c.b);\n        total += calculate_p(c.r, s);\n    }\n    return total;\n}\n\nbool can_place(const vector<tuple<int, int, int, int>>& placed, int a, int b, int c, int d) {\n    for (auto& [pa, pb, pc, pd] : placed) {\n        if (!(c <= pa || a >= pc || d <= pb || b >= pd)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid place_rectangles(vector<Company>& companies, const vector<int>& order) {\n    vector<tuple<int, int, int, int>> placed;\n    \n    for (int idx : order) {\n        int x = companies[idx].x;\n        int y = companies[idx].y;\n        int r = companies[idx].r;\n        \n        // Find all dimension pairs (w, h) such that w * h = r\n        vector<pair<int, int>> dims;\n        for (int w = 1; w * w <= r; w++) {\n            if (r % w == 0) {\n                dims.push_back({w, r / w});\n                if (w * w != r) {\n                    dims.push_back({r / w, w});\n                }\n            }\n        }\n        \n        // Prefer more square-like rectangles (better packing)\n        sort(dims.begin(), dims.end(), [](auto& p1, auto& p2) {\n            return abs(p1.first - p1.second) < abs(p2.first - p2.second);\n        });\n        \n        bool placed_rect = false;\n        for (auto [w, h] : dims) {\n            // Try all positions that contain (x, y)\n            for (int offset_x = 0; offset_x < w && !placed_rect; offset_x++) {\n                for (int offset_y = 0; offset_y < h && !placed_rect; offset_y++) {\n                    int a = x - offset_x;\n                    int b = y - offset_y;\n                    int c = a + w;\n                    int d = b + h;\n                    \n                    if (a >= 0 && c <= 10000 && b >= 0 && d <= 10000) {\n                        if (can_place(placed, a, b, c, d)) {\n                            companies[idx].a = a;\n                            companies[idx].b = b;\n                            companies[idx].c = c;\n                            companies[idx].d = d;\n                            placed.emplace_back(a, b, c, d);\n                            placed_rect = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        companies[i].a = 0;\n        companies[i].b = 0;\n        companies[i].c = 0;\n        companies[i].d = 0;\n    }\n    \n    vector<Company> best_companies = companies;\n    double best_p = -1;\n    \n    // Strategy 1: Sort by r (largest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r > current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 2: Sort by position (x then y)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].x != current[j].x) return current[i].x < current[j].x;\n            return current[i].y < current[j].y;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 3: Sort by position (y then x)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].y != current[j].y) return current[i].y < current[j].y;\n            return current[i].x < current[j].x;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 4: Random order (multiple times)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 100; trial++) {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 5: Sort by r (smallest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r < current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 6: Sort by distance from center\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 7: Sort by r * distance from center (combined heuristic)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            if (current[i].r != current[j].r) return current[i].r > current[j].r;\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Output best solution\n    for (int i = 0; i < n; i++) {\n        cout << best_companies[i].a << \" \" << best_companies[i].b << \" \" \n             << best_companies[i].c << \" \" << best_companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables for problem data\nint si, sj;\nint t[50][50];\nint p[50][50];\nint adj[50][50][4]; // Directions: 0:U, 1:D, 2:L, 3:R\nint adj_count[50][50];\nchar move_char[4] = {'U', 'D', 'L', 'R'};\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\n// Path state\nstruct State {\n    vector<pair<int, int>> path;\n    vector<char> moves;\n    long long score;\n    bool visited[2505]; // Max tiles <= 2500\n    int path_len;\n\n    State() {\n        memset(visited, 0, sizeof(visited));\n    }\n};\n\n// Check if (r, c) is valid (in bounds)\nbool is_valid(int r, int c) {\n    return r >= 0 && r < 50 && c >= 0 && c < 50;\n}\n\n// Precompute adjacencies\nvoid precompute_adj() {\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            adj_count[i][j] = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (is_valid(ni, nj)) {\n                    adj[i][j][adj_count[i][j]++] = k;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> t[i][j];\n        }\n    }\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    precompute_adj();\n\n    // RNG setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_int(0, 2); // 0: Add, 1: Remove, 2: Change\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    // Initial State\n    State current;\n    current.path.push_back({si, sj});\n    current.score = p[si][sj];\n    current.visited[t[si][sj]] = true;\n    current.path_len = 1;\n\n    State best = current;\n\n    // SA Parameters\n    double T = 1000.0;\n    double cooling = 0.9995;\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1900); // Leave some margin for output\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Decide move type\n        int move_type = dist_int(rng);\n\n        if (move_type == 0) { // Add\n            if (current.path_len == 0) continue;\n            int r = current.path.back().first;\n            int c = current.path.back().second;\n            \n            // Find valid neighbors\n            vector<int> valid_moves;\n            valid_moves.reserve(4);\n            for (int k = 0; k < adj_count[r][c]; ++k) {\n                int dir = adj[r][c][k];\n                int nr = r + di[dir];\n                int nc = c + dj[dir];\n                int tile = t[nr][nc];\n                if (!current.visited[tile]) {\n                    valid_moves.push_back(dir);\n                }\n            }\n\n            if (valid_moves.empty()) continue;\n\n            // Pick a move randomly\n            int chosen_dir = valid_moves[dist_int(rng) % valid_moves.size()];\n            \n            int nr = r + di[chosen_dir];\n            int nc = c + dj[chosen_dir];\n            int new_score = current.score + p[nr][nc];\n            int tile = t[nr][nc];\n\n            // SA Acceptance (Add always increases score since p >= 0, so prob=1)\n            // But we keep SA logic for consistency\n            double delta = (double)(new_score - current.score);\n            double prob = 1.0;\n            if (delta < 0) {\n                prob = exp(delta / T);\n            }\n\n            if (prob_dist(rng) < prob) {\n                // Accept\n                current.path.push_back({nr, nc});\n                current.moves.push_back(move_char[chosen_dir]);\n                current.score = new_score;\n                current.visited[tile] = true;\n                current.path_len++;\n                \n                if (current.score > best.score) {\n                    best = current;\n                }\n            }\n        } \n        else if (move_type == 1) { // Remove\n            if (current.path_len <= 1) continue;\n            \n            // Remove last step\n            int last_r = current.path.back().first;\n            int last_c = current.path.back().second;\n            int last_tile = t[last_r][last_c];\n            \n            current.path.pop_back();\n            current.moves.pop_back();\n            current.score -= p[last_r][last_c];\n            current.visited[last_tile] = false;\n            current.path_len--;\n\n            // Always accept removal to allow backtracking\n        } \n        else { // Change\n            if (current.path_len <= 1) continue;\n            \n            int r = current.path[current.path_len - 2].first;\n            int c = current.path[current.path_len - 2].second;\n            \n            // Find valid neighbors for the second-to-last point\n            vector<int> valid_moves;\n            valid_moves.reserve(4);\n            for (int k = 0; k < adj_count[r][c]; ++k) {\n                int dir = adj[r][c][k];\n                int nr = r + di[dir];\n                int nc = c + dj[dir];\n                int tile = t[nr][nc];\n                // Must be unvisited, and NOT the current last point\n                if (!current.visited[tile]) {\n                     // Check if it's the current last point\n                     if (nr == current.path.back().first && nc == current.path.back().second) continue;\n                     valid_moves.push_back(dir);\n                }\n            }\n\n            if (valid_moves.empty()) continue;\n\n            int chosen_dir = valid_moves[dist_int(rng) % valid_moves.size()];\n            \n            int nr = r + di[chosen_dir];\n            int nc = c + dj[chosen_dir];\n            int new_tile = t[nr][nc];\n            \n            // Remove old last\n            int old_last_r = current.path.back().first;\n            int old_last_c = current.path.back().second;\n            int old_last_tile = t[old_last_r][old_last_c];\n            \n            int delta_score = p[nr][nc] - p[old_last_r][old_last_c];\n            double prob = 1.0;\n            if (delta_score < 0) {\n                prob = exp(delta_score / T);\n            }\n            \n            if (prob_dist(rng) < prob) {\n                // Accept\n                current.path.pop_back();\n                current.moves.pop_back();\n                current.visited[old_last_tile] = false;\n                \n                current.path.push_back({nr, nc});\n                current.moves.push_back(move_char[chosen_dir]);\n                current.score += delta_score;\n                current.visited[new_tile] = true;\n                \n                if (current.score > best.score) {\n                    best = current;\n                }\n            }\n        }\n\n        // Cool down\n        T *= cooling;\n        if (T < 0.1) T = 0.1; // Floor to prevent underflow\n    }\n\n    // Output\n    cout << string(best.moves.begin(), best.moves.end()) << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <string>\n#include <tuple>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst double INIT_W = 5000.0;\nconst double K = 10.0; // Blending factor for row/col average\n\n// Edge weight estimates\n// h[i][j] stores stats for horizontal edge between (i, j) and (i, j+1)\n// v[i][j] stores stats for vertical edge between (i, j) and (i+1, j)\nstruct Stats {\n    double log_sum = 0.0;\n    int cnt = 0;\n};\n\nStats h_stats[N][N]; // 30x30, though j only goes to 28\nStats v_stats[N][N]; // 30x30, though i only goes to 28\nStats h_avg_stats[N]; // Row averages\nStats v_avg_stats[N]; // Col averages\n\n// Helper to get weight from stats\ndouble get_weight(const Stats& s) {\n    if (s.cnt == 0) return INIT_W;\n    return INIT_W * exp(s.log_sum / s.cnt);\n}\n\n// Helper to get effective weight blending edge and average\ndouble get_h_weight(int i, int j) {\n    double w_edge = get_weight(h_stats[i][j]);\n    double w_avg = get_weight(h_avg_stats[i]);\n    return (h_stats[i][j].cnt * w_edge + K * w_avg) / (h_stats[i][j].cnt + K);\n}\n\ndouble get_v_weight(int i, int j) {\n    double w_edge = get_weight(v_stats[i][j]);\n    double w_avg = get_weight(v_avg_stats[j]);\n    return (v_stats[i][j].cnt * w_edge + K * w_avg) / (v_stats[i][j].cnt + K);\n}\n\n// Update stats with ratio\nvoid update_h(int i, int j, double ratio) {\n    h_stats[i][j].log_sum += log(ratio);\n    h_stats[i][j].cnt++;\n    h_avg_stats[i].log_sum += log(ratio);\n    h_avg_stats[i].cnt++;\n}\n\nvoid update_v(int i, int j, double ratio) {\n    v_stats[i][j].log_sum += log(ratio);\n    v_stats[i][j].cnt++;\n    v_avg_stats[j].log_sum += log(ratio);\n    v_avg_stats[j].cnt++;\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int queries = 1000;\n    for (int k = 0; k < queries; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // Dijkstra\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n        vector<vector<char>> move_dir(N, vector<char>(N, 0));\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[si][sj] = 0.0;\n        pq.push({0.0, si, sj});\n\n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        char dirs[] = {'U', 'D', 'L', 'R'};\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            if (current.dist > dist[current.r][current.c]) continue;\n            if (current.r == ti && current.c == tj) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = current.r + dr[d];\n                int nc = current.c + dc[d];\n\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    double w = 0.0;\n                    if (d == 0) { // U: (nr, nc) -> (nr+1, nc) is v[nr][nc]\n                        // Move from (nr+1, nc) to (nr, nc). Edge is v[nr][nc].\n                        // Current is (nr+1, nc). Next is (nr, nc).\n                        // Wait, current is (r, c). Next is (nr, nc).\n                        // If d=0 (U), next is (r-1, c). Edge is v[r-1][c].\n                        w = get_v_weight(nr, nc);\n                    } else if (d == 1) { // D: (r, c) -> (r+1, c). Edge is v[r][c].\n                        w = get_v_weight(r, c);\n                    } else if (d == 2) { // L: (r, c) -> (r, c-1). Edge is h[r][c-1].\n                        w = get_h_weight(r, nc);\n                    } else if (d == 3) { // R: (r, c) -> (r, c+1). Edge is h[r][c].\n                        w = get_h_weight(r, c);\n                    }\n\n                    if (dist[current.r][current.c] + w < dist[nr][nc]) {\n                        dist[nr][nc] = dist[current.r][current.c] + w;\n                        parent[nr][nc] = {current.r, current.c};\n                        move_dir[nr][nc] = dirs[d];\n                        pq.push({dist[nr][nc], nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path\n        string path = \"\";\n        int curr_r = ti, curr_c = tj;\n        double path_est = 0.0;\n        vector<pair<int, int>> path_edges_h; // Store (i, j) for h edges\n        vector<pair<int, int>> path_edges_v; // Store (i, j) for v edges\n\n        while (curr_r != si || curr_c != sj) {\n            int pr = parent[curr_r][curr_c].first;\n            int pc = parent[curr_r][curr_c].second;\n            char d = move_dir[curr_r][curr_c];\n            path += d;\n\n            // Identify edge\n            if (d == 'U') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r + 1.\n                // Edge is v[curr_r][curr_c]\n                path_edges_v.push_back({curr_r, curr_c});\n                path_est += get_v_weight(curr_r, curr_c);\n            } else if (d == 'D') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r - 1.\n                // Edge is v[pr][pc] = v[curr_r-1][curr_c]\n                path_edges_v.push_back({pr, pc});\n                path_est += get_v_weight(pr, pc);\n            } else if (d == 'L') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c + 1.\n                // Edge is h[pr][curr_c]\n                path_edges_h.push_back({pr, curr_c});\n                path_est += get_h_weight(pr, curr_c);\n            } else if (d == 'R') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c - 1.\n                // Edge is h[pr][pc]\n                path_edges_h.push_back({pr, pc});\n                path_est += get_h_weight(pr, pc);\n            }\n\n            curr_r = pr;\n            curr_c = pc;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << endl;\n\n        // Read feedback\n        int result;\n        cin >> result;\n\n        // Update weights\n        if (path_est > 0) {\n            double ratio = (double)result / path_est;\n            // Avoid log(0) or negative\n            if (ratio <= 0) ratio = 1.0; \n\n            for (auto& e : path_edges_h) {\n                update_h(e.first, e.second, ratio);\n            }\n            for (auto& e : path_edges_v) {\n                update_v(e.first, e.second, ratio);\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\nconst int NUM_CHARS = 8; // A-H\n\n// State\nint matrix[N][N]; // 0-7 for A-H\nint string_counts[MAX_M]; // Number of valid placements for each string\nint total_matched = 0;\nint M;\n\n// Valid placements tracking\n// valid_placements[s] is a bitset where bit k is 1 if placement k is valid for string s\n// Placement ID encoding:\n// dir (0: horiz, 1: vert) * N * N * MAX_LEN + row * N * MAX_LEN + col * MAX_LEN + offset\n// Max ID: 2 * 20 * 20 * 12 = 9600. Let's use 10000.\nbitset<10000> valid_placements[MAX_M];\n\n// cell_active[r*N+c] stores list of placements that cover this cell and are currently valid\n// To save memory and time, we store a compact representation.\n// struct PlacementInfo { int s; int id; };\n// But we need to know dir/offset to check validity.\n// We can store {s, id}. id encodes dir, row, col, offset.\nstruct PlacementInfo {\n    int s;\n    int id;\n};\nvector<PlacementInfo> cell_active[N * N];\n\n// Potential lists for fast lookup\n// potential_lists[char][cell] stores list of {s, id} that could match at this cell with this char\n// id encodes the placement details.\nvector<PlacementInfo> potential_lists[NUM_CHARS][N * N];\n\n// Helper to encode placement ID\nint encode_id(int r, int c, int dir, int offset) {\n    return dir * N * N * MAX_LEN + r * N * MAX_LEN + c * MAX_LEN + offset;\n}\n\n// Helper to decode placement ID\nvoid decode_id(int id, int &r, int &c, int &dir, int &offset) {\n    offset = id % MAX_LEN;\n    id /= MAX_LEN;\n    c = id % N;\n    id /= N;\n    r = id % N;\n    dir = id / N;\n}\n\n// Strings data\nvector<string> strings;\nvector<int> string_lens;\n\n// Random number generator\nmt19937 rng(1337);\nuniform_int_distribution<int> dist_char(0, NUM_CHARS - 1);\nuniform_int_distribution<int> dist_cell(0, N * N - 1);\n\n// Check if a placement is valid\nbool is_placement_valid(int s, int r, int c, int dir, int offset) {\n    int len = string_lens[s];\n    const string &str = strings[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) { // Horizontal\n            cr = r;\n            cc = (c + k) % N;\n        } else { // Vertical\n            cr = (r + k) % N;\n            cc = c;\n        }\n        if (matrix[cr][cc] != (str[k] - 'A')) return false;\n    }\n    return true;\n}\n\n// Add a valid placement\nvoid add_placement(int s, int r, int c, int dir, int offset) {\n    int id = encode_id(r, c, dir, offset);\n    if (valid_placements[s].test(id)) return; // Already valid\n\n    valid_placements[s].set(id);\n    string_counts[s]++;\n    if (string_counts[s] == 1) total_matched++;\n\n    // Add to cell_active for all covered cells\n    int len = string_lens[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        cell_active[cr * N + cc].push_back({s, id});\n    }\n}\n\n// Remove a valid placement (mark as invalid)\nvoid remove_placement(int s, int r, int c, int dir, int offset) {\n    int id = encode_id(r, c, dir, offset);\n    if (!valid_placements[s].test(id)) return;\n\n    valid_placements[s].reset(id);\n    string_counts[s]--;\n    if (string_counts[s] == 0) total_matched--;\n\n    // We do NOT remove from cell_active immediately to save time.\n    // Stale entries will be ignored.\n}\n\n// Initialize potential lists\nvoid init_potential_lists() {\n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        const string &str = strings[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal placements covering (r, c)\n                // Start col j such that c is in [j, j+len-1]\n                // j = (c - k) mod N for k in [0, len-1]\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_c = (c - k);\n                    if (start_c < 0) start_c += N;\n                    int id = encode_id(r, start_c, 0, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n                // Vertical placements covering (r, c)\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_r = (r - k);\n                    if (start_r < 0) start_r += N;\n                    int id = encode_id(start_r, c, 1, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n            }\n        }\n    }\n}\n\n// Initialize matrix and state\nvoid init_state() {\n    // Fill with random chars\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            matrix[i][j] = dist_char(rng);\n        }\n    }\n\n    // Find all valid placements\n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal\n                if (is_placement_valid(s, r, c, 0, 0)) {\n                    add_placement(s, r, c, 0, 0);\n                }\n                // Vertical\n                if (is_placement_valid(s, r, c, 1, 0)) {\n                    add_placement(s, r, c, 1, 0);\n                }\n            }\n        }\n    }\n}\n\n// Update cell (r, c) from old_char to new_char\n// Returns true if accepted\nbool update_cell(int r, int c, int new_char) {\n    int old_char = matrix[r][c];\n    if (old_char == new_char) return true;\n\n    int cell_idx = r * N + c;\n\n    // 1. Invalidate existing placements covering this cell\n    // We iterate a copy of cell_active to avoid modification issues\n    // But we need to be careful.\n    // We can just iterate and check.\n    // To avoid reallocation, we can swap with back for removal.\n    // But we decided to leave stale entries.\n    // So we just iterate.\n    for (auto &p : cell_active[cell_idx]) {\n        if (valid_placements[p.s].test(p.id)) {\n            // Check if this placement matches new_char\n            // We need to know the offset relative to this cell\n            // Decode id\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            \n            // Calculate relative offset k for this cell\n            int k = -1;\n            if (tdir == 0) {\n                // Horizontal: row is tr, start col is tc. Cell is (r, c).\n                // c = (tc + k) % N => k = (c - tc) mod N\n                k = (c - tc);\n                if (k < 0) k += N;\n            } else {\n                // Vertical: col is tc, start row is tr. Cell is (r, c).\n                // r = (tr + k) % N => k = (r - tr) mod N\n                k = (r - tr);\n                if (k < 0) k += N;\n            }\n            \n            // Check if k is within string length\n            if (k >= string_lens[p.s]) {\n                // Should not happen if logic is correct\n                continue;\n            }\n\n            int required_char = strings[p.s][k] - 'A';\n            if (required_char != new_char) {\n                // Placement broken\n                remove_placement(p.s, tr, tc, tdir, 0); // offset 0 in add/remove is relative to start\n            }\n        }\n    }\n\n    // 2. Find new valid placements\n    // Iterate potential lists for new_char at this cell\n    for (auto &p : potential_lists[new_char][cell_idx]) {\n        if (!valid_placements[p.s].test(p.id)) {\n            // Check if valid\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            // Note: toffset in id is the offset of the char at (r, c) relative to start\n            // Wait, in encode_id we used offset as the offset of the char at (r, c)?\n            // Let's recheck encode_id usage.\n            // In init_potential_lists:\n            // Horizontal: start_c = (c - k). id = encode_id(r, start_c, 0, k).\n            // Here k is the offset of the char at (r, c).\n            // So decode_id gives us k.\n            // So we can check validity by checking the whole string.\n            // But we know (r, c) matches. We just need to check others.\n            // Since only (r, c) changed, we can just check the whole string.\n            // Optimization: check only if it was valid except at (r, c).\n            // But we don't track that.\n            // Just check full validity.\n            if (is_placement_valid(p.s, tr, tc, tdir, 0)) {\n                add_placement(p.s, tr, tc, tdir, 0);\n            }\n        }\n    }\n\n    matrix[r][c] = new_char;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M;\n    strings.resize(M);\n    string_lens.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        string_lens[i] = strings[i].length();\n    }\n\n    init_potential_lists();\n    init_state();\n\n    // Simulated Annealing\n    double temperature = 100.0;\n    double cooling_rate = 0.995;\n    int max_iter = 200000; // Adjust based on time\n    int iter = 0;\n\n    while (iter < max_iter && temperature > 0.01) {\n        int r = dist_cell(rng) / N;\n        int c = dist_cell(rng) % N;\n        \n        int old_char = matrix[r][c];\n        int new_char = dist_char(rng);\n        \n        // Save state for rollback\n        // We need to save total_matched and string_counts and valid_placements\n        // This is expensive.\n        // Instead, we can just revert the cell and re-run update logic in reverse?\n        // Or just accept the cost of rollback.\n        // Rollback involves:\n        // 1. Revert cell char.\n        // 2. Re-run update logic to restore counts.\n        // This is basically running update_cell again.\n        // So we can just call update_cell(r, c, old_char) if rejected.\n        \n        int old_total_matched = total_matched;\n        // We need to track changes to string_counts to revert accurately?\n        // update_cell modifies global state.\n        // If we reject, we need to revert.\n        // Since update_cell is deterministic given the matrix state,\n        // we can just call update_cell(r, c, old_char) to revert.\n        // But update_cell assumes the cell is currently new_char.\n        // So:\n        // 1. Save old_total_matched.\n        // 2. Call update_cell(r, c, new_char).\n        // 3. Check score.\n        // 4. If reject, call update_cell(r, c, old_char).\n        // 5. Update temperature.\n        \n        update_cell(r, c, new_char);\n        \n        double delta_score = total_matched - old_total_matched;\n        // Score is proportional to total_matched.\n        // If total_matched == M, we prefer fewer '.'. But we don't use '.'.\n        // So score is just total_matched.\n        \n        double prob = 1.0;\n        if (delta_score < 0) {\n            prob = exp(delta_score / temperature);\n        }\n        \n        double rand_val = (double)dist_char(rng) / (double)NUM_CHARS; // 0 to 1 approx\n        if (rand_val < prob) {\n            // Accept\n        } else {\n            // Reject, revert\n            update_cell(r, c, old_char);\n        }\n\n        temperature *= cooling_rate;\n        iter++;\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << (char)('A' + matrix[i][j]);\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> roads;\nint total_roads = 0;\n\n// Direction arrays: U, D, L, R\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\nconst char dc[] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && grid[i][j] != '#';\n}\n\nbool isVisible(int ci, int cj, int ti, int tj) {\n    if (ci == ti) {\n        for (int j = min(cj, tj); j <= max(cj, tj); j++) {\n            if (grid[ci][j] == '#') return false;\n        }\n        return true;\n    }\n    if (cj == tj) {\n        for (int i = min(ci, ti); i <= max(ci, ti); i++) {\n            if (grid[i][cj] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\nint getCost(int i, int j) {\n    return grid[i][j] - '0';\n}\n\n// Calculate total travel time of a path\nlong long calcPathCost(const vector<pair<int,int>>& path) {\n    if (path.empty()) return 0;\n    long long cost = 0;\n    for (size_t i = 1; i < path.size(); i++) {\n        cost += getCost(path[i].first, path[i].second);\n    }\n    return cost;\n}\n\n// Get all squares visible from a position\nvector<pair<int,int>> getVisibleSquares(int ci, int cj) {\n    vector<pair<int,int>> visible;\n    for (const auto& [ri, rj] : roads) {\n        if (isVisible(ci, cj, ri, rj)) {\n            visible.push_back({ri, rj});\n        }\n    }\n    return visible;\n}\n\n// BFS to find shortest path between two points\nvector<pair<int,int>> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {{si, sj}};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    queue<pair<int,int>> q;\n    \n    dist[si][sj] = 0;\n    q.push({si, sj});\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) {\n            vector<pair<int,int>> path;\n            int i = ti, j = tj;\n            while (!(i == si && j == sj)) {\n                path.push_back({i, j});\n                auto [pi, pj] = parent[i][j];\n                i = pi; j = pj;\n            }\n            path.push_back({si, sj});\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (isValid(ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                parent[ni][nj] = {ci, cj};\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    return {{si, sj}};\n}\n\nint main() {\n    srand(42);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n    }\n    \n    // Collect all road squares\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                roads.push_back({i, j});\n            }\n        }\n    }\n    total_roads = roads.size();\n    \n    // Phase 1: Greedy coverage\n    vector<pair<int,int>> path = {{si, sj}};\n    set<pair<int,int>> covered;\n    \n    // Mark initially visible squares\n    for (const auto& [ri, rj] : roads) {\n        if (isVisible(si, sj, ri, rj)) {\n            covered.insert({ri, rj});\n        }\n    }\n    \n    int ci = si, cj = sj;\n    int max_iter = 200000;\n    int iter = 0;\n    \n    while ((int)covered.size() < total_roads && iter < max_iter) {\n        iter++;\n        \n        int best_d = -1;\n        int max_new = -1;\n        int min_cost = 1000000;\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (!isValid(ni, nj)) continue;\n            \n            int new_covered = 0;\n            for (const auto& [ri, rj] : roads) {\n                if (covered.find({ri, rj}) == covered.end()) {\n                    if (isVisible(ni, nj, ri, rj)) {\n                        new_covered++;\n                    }\n                }\n            }\n            \n            if (new_covered > max_new || (new_covered == max_new && new_covered > 0)) {\n                max_new = new_covered;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1) {\n            // No new coverage, move randomly\n            best_d = rand() % 4;\n        }\n        \n        ci += di[best_d];\n        cj += dj[best_d];\n        path.push_back({ci, cj});\n        \n        for (const auto& [ri, rj] : roads) {\n            if (isVisible(ci, cj, ri, rj)) {\n                covered.insert({ri, rj});\n            }\n        }\n    }\n    \n    // Phase 2: Return to start using BFS\n    vector<pair<int,int>> returnPath = bfsPath(path.back().first, path.back().second, si, sj);\n    for (size_t i = 1; i < returnPath.size(); i++) {\n        path.push_back(returnPath[i]);\n    }\n    \n    // Phase 3: Simulated Annealing optimization\n    long long currentCost = calcPathCost(path);\n    long long bestCost = currentCost;\n    double temperature = 10000.0;\n    double coolingRate = 0.995;\n    \n    auto evaluate = [&]() {\n        set<pair<int,int>> tempCovered;\n        for (const auto& [ri, rj] : roads) {\n            if (isVisible(si, sj, ri, rj)) {\n                tempCovered.insert({ri, rj});\n            }\n        }\n        for (const auto& [ci, cj] : path) {\n            for (const auto& [ri, rj] : roads) {\n                if (isVisible(ci, cj, ri, rj)) {\n                    tempCovered.insert({ri, rj});\n                }\n            }\n        }\n        return (int)tempCovered.size() == total_roads;\n    };\n    \n    while (temperature > 1.0) {\n        // Try 2-opt swap\n        int n = path.size();\n        int i1 = rand() % (n - 2);\n        int i2 = rand() % (n - i1 - 2) + i1 + 1;\n        \n        vector<pair<int,int>> newPath = path;\n        reverse(newPath.begin() + i1 + 1, newPath.begin() + i2 + 1);\n        \n        if (evaluate()) {\n            long long newCost = calcPathCost(newPath);\n            long long delta = newCost - currentCost;\n            \n            if (delta < 0 || rand() % 1000 < (int)(1000.0 * exp(-delta / temperature))) {\n                path = newPath;\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    // Phase 4: Convert path to movement string\n    string result;\n    for (size_t i = 1; i < path.size(); i++) {\n        int di_val = path[i].first - path[i-1].first;\n        int dj_val = path[i].second - path[i-1].second;\n        \n        if (di_val == -1) result += 'U';\n        else if (di_val == 1) result += 'D';\n        else if (dj_val == -1) result += 'L';\n        else if (dj_val == 1) result += 'R';\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    vector<int> dependents;\n    int indegree;\n    int status; // 0: available, 1: assigned, 2: done\n    int start_day;\n};\n\nstruct Member {\n    int id;\n    vector<double> estimate;\n    vector<int> lower_bound;\n    int current_task; // -1 if free\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<vector<int>> adj;\nint day = 0;\n\ndouble calculate_cost(int task_idx, int member_idx) {\n    double cost = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            cost += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n        }\n    }\n    return max(1.0, cost);\n}\n\nvoid update_costs_for_member(int member_idx) {\n    // Re-calculate costs for all tasks for this member\n    // This is O(N * K)\n    // We don't store costs explicitly to save memory and update time, \n    // we calculate on demand or update a cache if needed.\n    // Given N=1000, M=20, calculating on demand is O(N*K) = 20000 ops.\n    // Doing this for all members is 400000 ops.\n    // Doing this every day is 2000 * 400000 = 8e8 ops. Too slow.\n    // We need to cache costs.\n    // But costs only change when skills change.\n    // Skills change when a task completes.\n    // So we update costs only when skills update.\n    // This is O(N*K) per completion. Total N completions.\n    // Total O(N^2 * K) = 1000^2 * 20 = 2e7 ops. Acceptable.\n    // So we maintain a cost matrix.\n}\n\nvector<vector<double>> cost_matrix;\n\nvoid update_cost_matrix(int member_idx) {\n    for (int i = 0; i < N; ++i) {\n        cost_matrix[i][member_idx] = calculate_cost(i, member_idx);\n    }\n}\n\nvoid update_skills(int member_idx, int task_idx, int t) {\n    // Update lower bounds and estimates\n    // t is the actual time taken\n    \n    // If t=1, we know w=0, so s >= d for all k\n    if (t == 1) {\n        for (int k = 0; k < K; ++k) {\n            if (tasks[task_idx].d[k] > members[member_idx].lower_bound[k]) {\n                members[member_idx].lower_bound[k] = tasks[task_idx].d[k];\n                // Update estimate to be at least lower bound\n                if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                    members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n                }\n            }\n        }\n    }\n    \n    // Update estimate based on observed time\n    // w_obs approx t (if t > 1)\n    // w_pred = sum(max(0, d - estimate))\n    \n    double w_pred = 0;\n    int count_non_zero = 0;\n    vector<int> contributing_skills;\n    \n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            w_pred += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n            count_non_zero++;\n            contributing_skills.push_back(k);\n        }\n    }\n    \n    double w_obs = 0;\n    if (t > 1) {\n        // w = t - r, r in [-3, 3]. So w in [t-3, t+3].\n        // Expectation is t.\n        // But if t=1, w=0.\n        w_obs = t; \n        // Conservative: if t is small, w might be 0.\n        // But if t=1, handled above.\n        // If t=2, w could be 0 (if r=2) or 5 (if r=-3).\n        // But if w=0, t=1 always. So if t>1, w>0.\n        // So w_obs = t is reasonable.\n    } else {\n        w_obs = 0;\n    }\n    \n    if (count_non_zero > 0) {\n        double diff = w_pred - w_obs;\n        // If diff > 0, we overestimated skills (predicted less work than observed). Decrease estimate.\n        // If diff < 0, we underestimated skills. Increase estimate.\n        // Adjustment per skill\n        double adjust = diff / count_non_zero;\n        \n        for (int k : contributing_skills) {\n            members[member_idx].estimate[k] -= adjust;\n            // Clamp to lower bound\n            if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n            }\n            // Also ensure non-negative\n            if (members[member_idx].estimate[k] < 0) {\n                members[member_idx].estimate[k] = 0;\n            }\n        }\n    }\n    \n    // Update cost matrix for this member\n    update_cost_matrix(member_idx);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n        }\n        tasks[i].indegree = 0;\n        tasks[i].status = 0;\n        tasks[i].start_day = 0;\n    }\n\n    adj.resize(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        tasks[v].indegree++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].estimate.assign(K, 0.0);\n        members[i].lower_bound.assign(K, 0);\n        members[i].current_task = -1;\n    }\n\n    cost_matrix.assign(N, vector<double>(M, 0.0));\n    // Initialize cost matrix\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cost_matrix[i][j] = calculate_cost(i, j);\n        }\n    }\n\n    // Count dependents for priority\n    vector<int> outdegree(N, 0);\n    for (int i = 0; i < N; ++i) {\n        outdegree[i] = adj[i].size();\n    }\n\n    while (true) {\n        day++;\n        if (day > 2000) break;\n\n        // Identify free members\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (members[j].current_task == -1) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Identify available tasks\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (tasks[i].status == 0 && tasks[i].indegree == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Assign tasks\n        // We want to match free_members to available_tasks to minimize cost\n        // Priority: cost first, then outdegree (tasks that unlock more)\n        \n        struct Assignment {\n            double cost;\n            int task_idx;\n            int member_idx;\n            int priority; // outdegree\n            bool operator<(const Assignment& other) const {\n                if (abs(cost - other.cost) > 1e-9) return cost < other.cost;\n                return priority > other.priority; // Higher outdegree first\n            }\n        };\n\n        vector<Assignment> candidates;\n        candidates.reserve(free_members.size() * available_tasks.size());\n\n        for (int j : free_members) {\n            for (int i : available_tasks) {\n                candidates.push_back({cost_matrix[i][j], i, j, outdegree[i]});\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n\n        vector<int> assigned_tasks(N, -1); // -1 if not assigned in this round\n        vector<int> assigned_members(M, -1); // -1 if not assigned in this round\n        vector<pair<int, int>> output_assignments;\n\n        for (const auto& cand : candidates) {\n            if (assigned_tasks[cand.task_idx] == -1 && assigned_members[cand.member_idx] == -1) {\n                assigned_tasks[cand.task_idx] = cand.task_idx;\n                assigned_members[cand.member_idx] = cand.member_idx;\n                output_assignments.push_back({cand.member_idx, cand.task_idx});\n                \n                // Update status\n                tasks[cand.task_idx].status = 1;\n                tasks[cand.task_idx].start_day = day;\n                members[cand.member_idx].current_task = cand.task_idx;\n            }\n        }\n\n        // Output\n        cout << output_assignments.size();\n        for (const auto& p : output_assignments) {\n            cout << \" \" << (p.first + 1) << \" \" << (p.second + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completions\n        int n_completions;\n        cin >> n_completions;\n        if (n_completions == -1) break;\n\n        vector<int> completed_members(n_completions);\n        for (int i = 0; i < n_completions; ++i) {\n            cin >> completed_members[i];\n            --completed_members[i]; // 0-indexed\n        }\n\n        for (int j : completed_members) {\n            int task_idx = members[j].current_task;\n            if (task_idx != -1) {\n                int t = day - tasks[task_idx].start_day + 1;\n                \n                // Update skills\n                update_skills(j, task_idx, t);\n                \n                // Update task status\n                tasks[task_idx].status = 2;\n                members[j].current_task = -1;\n                \n                // Update dependencies\n                for (int v : adj[task_idx]) {\n                    tasks[v].indegree--;\n                    if (tasks[v].indegree == 0) {\n                        // Task v becomes available\n                        // No need to do anything, it will be picked up next day\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n    int orderId; // -1 for office\n    int type; // 0 for pickup, 1 for dropoff, 2 for office\n};\n\nint dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    vector<Order> orders(1000);\n    for (int i = 0; i < 1000; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n    \n    int ox = 400, oy = 400;\n    \n    // Selected orders\n    vector<int> selected;\n    \n    // Initial selection: pick orders with short pickup-dropoff distance\n    vector<pair<int, int>> orderDist;\n    for (int i = 0; i < 1000; i++) {\n        int d = dist(orders[i].a, orders[i].b, orders[i].c, orders[i].d);\n        orderDist.push_back({d, i});\n    }\n    sort(orderDist.begin(), orderDist.end());\n    for (int i = 0; i < 50; i++) {\n        selected.push_back(orderDist[i].second);\n    }\n    \n    // Build initial route: office -> all pickups -> all dropoffs -> office\n    auto buildRoute = [&](const vector<int>& sel) {\n        vector<Point> route;\n        route.reserve(2 * sel.size() + 2);\n        route.push_back({ox, oy, -1, 2});\n        for (int idx : sel) {\n            route.push_back({orders[idx].a, orders[idx].b, idx, 0});\n        }\n        for (int idx : sel) {\n            route.push_back({orders[idx].c, orders[idx].d, idx, 1});\n        }\n        route.push_back({ox, oy, -1, 2});\n        return route;\n    };\n    \n    vector<Point> route = buildRoute(selected);\n    \n    // Calculate route cost\n    auto calcCost = [&]() {\n        int cost = 0;\n        for (size_t i = 0; i + 1 < route.size(); i++) {\n            cost += dist(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n        }\n        return cost;\n    };\n    \n    int currentCost = calcCost();\n    int bestCost = currentCost;\n    vector<Point> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // Simulated annealing parameters\n    random_device rd;\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> randDist(0.0, 1.0);\n    \n    double temperature = 5000.0;\n    double coolingRate = 0.99995;\n    \n    auto startTime = chrono::high_resolution_clock::now();\n    double timeLimit = 1.9;\n    \n    // Check if route is valid (pickup before dropoff for each order)\n    auto isValidRoute = [&](const vector<Point>& r, const vector<int>& sel) {\n        vector<int> pickupPos(1000, -1), dropoffPos(1000, -1);\n        for (size_t k = 0; k < r.size(); k++) {\n            if (r[k].orderId >= 0) {\n                if (r[k].type == 0) pickupPos[r[k].orderId] = k;\n                else dropoffPos[r[k].orderId] = k;\n            }\n        }\n        for (int idx : sel) {\n            if (pickupPos[idx] >= dropoffPos[idx]) return false;\n        }\n        return true;\n    };\n    \n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed >= timeLimit) break;\n        \n        // Try different moves\n        int moveType = randDist(gen) < 0.35 ? 0 : (randDist(gen) < 0.7 ? 1 : 2);\n        \n        if (moveType == 0) {\n            // Swap: exchange an order in/out of selected set\n            int inIdx = (int)(randDist(gen) * selected.size());\n            \n            // Find an order not in selected\n            int outOrder = -1;\n            {\n                int cnt = 0;\n                for (int i = 0; i < 1000; i++) {\n                    bool inSelected = false;\n                    for (int s : selected) {\n                        if (s == i) {\n                            inSelected = true;\n                            break;\n                        }\n                    }\n                    if (!inSelected) {\n                        if (cnt == (int)(randDist(gen) * (1000 - selected.size()))) {\n                            outOrder = i;\n                            break;\n                        }\n                        cnt++;\n                    }\n                }\n            }\n            \n            if (outOrder < 0) continue;\n            \n            int inOrder = selected[inIdx];\n            \n            // Try swap\n            auto oldSelected = selected;\n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            selected[inIdx] = outOrder;\n            route = buildRoute(selected);\n            \n            if (!isValidRoute(route, selected)) {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        } else if (moveType == 1) {\n            // 2-opt: reverse a segment of the route\n            int i = (int)(randDist(gen) * (route.size() - 3));\n            int j = i + 1 + (int)(randDist(gen) * (route.size() - i - 2));\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            reverse(route.begin() + i, route.begin() + j + 1);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        } else {\n            // Insert: move a point to different position\n            int pos1 = (int)(randDist(gen) * (route.size() - 2));\n            int pos2 = (int)(randDist(gen) * (route.size() - 2));\n            \n            if (pos1 == pos2) continue;\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            Point p = route[pos1];\n            route.erase(route.begin() + pos1);\n            route.insert(route.begin() + pos2, p);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        }\n        \n        temperature *= coolingRate;\n        \n        // Periodically output for visualization (optional)\n        if (elapsed > 0.5 && elapsed < 0.6) {\n            cout << bestSelected.size();\n            for (int idx : bestSelected) {\n                cout << \" \" << orders[idx].id;\n            }\n            cout << \"\\n\";\n            cout << bestRoute.size();\n            for (auto& p : bestRoute) {\n                cout << \" \" << p.x << \" \" << p.y;\n            }\n            cout << \"\\n\";\n        }\n    }\n    \n    // Output final best solution\n    cout << bestSelected.size();\n    for (int idx : bestSelected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (auto& p : bestRoute) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    // Optimization for faster I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<pair<int, int>> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        // Calculate rounded Euclidean distance\n        long long dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        long long dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = (int)round(sqrt(dx * dx + dy * dy));\n    }\n\n    dsu d(N);\n    vector<int> degree(N);\n    vector<long long> min_d_vec(N); // Not strictly needed as we scan, but for clarity\n\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int root_u = d.find(u);\n        int root_v = d.find(v);\n\n        if (root_u == root_v) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Scan future edges to analyze connectivity and potential costs\n        fill(degree.begin(), degree.end(), 0);\n        long long min_d = 1e18;\n        long long min_d_all = 1e18;\n        bool has_direct = false;\n\n        for (int j = i + 1; j < M; ++j) {\n            int u_j = edges[j].u;\n            int v_j = edges[j].v;\n            int ru = d.find(u_j);\n            int rv = d.find(v_j);\n\n            if (ru != rv) {\n                degree[ru]++;\n                degree[rv]++;\n                min_d_all = min(min_d_all, (long long)edges[j].d);\n                \n                if ((ru == root_u && rv == root_v) || (ru == root_v && rv == root_u)) {\n                    min_d = min(min_d, (long long)edges[j].d);\n                    has_direct = true;\n                }\n            }\n        }\n\n        bool accept = false;\n\n        // Safety Check: If a component is a leaf or isolated in the remaining graph, we must accept.\n        if (degree[root_u] <= 1 || degree[root_v] <= 1) {\n            accept = true;\n        }\n        // Cost Check 1: Direct connection available\n        else if (has_direct) {\n            if (l_i <= 2.0 * min_d) {\n                accept = true;\n            }\n        }\n        // Cost Check 2: No direct connection, rely on indirect (fallback)\n        else {\n            if (min_d_all != 1e18) {\n                if (l_i <= 3.0 * min_d_all) {\n                    accept = true;\n                }\n            } else {\n                // No edges remaining, must accept to connect\n                accept = true;\n            }\n        }\n\n        cout << (accept ? \"1\" : \"0\") << \"\\n\";\n        cout.flush();\n\n        if (accept) {\n            d.unite(u, v);\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Pet {\n    int x, y, type;\n    bool operator<(const Pet& other) const {\n        return type < other.type;\n    }\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct State {\n    int turn;\n    vector<Pet> pets;\n    vector<Human> humans;\n    vector<vector<bool>> wall;\n    vector<vector<bool>> passable;\n};\n\nState state;\nmt19937 rng;\n\n// Directions: up, down, left, right\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char moveChars[] = {'U', 'D', 'L', 'R'};\nconst char wallChars[] = {'u', 'd', 'l', 'r'};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;\n}\n\nbool isPassable(int x, int y) {\n    if (!isValid(x, y)) return false;\n    return !state.wall[x][y];\n}\n\nbool hasPetAt(int x, int y) {\n    for (const auto& pet : state.pets) {\n        if (pet.x == x && pet.y == y) return true;\n    }\n    return false;\n}\n\nbool hasHumanAt(int x, int y) {\n    for (const auto& human : state.humans) {\n        if (human.x == x && human.y == y) return true;\n    }\n    return false;\n}\n\nbool hasPetAdjacent(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (hasPetAt(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canPlaceWall(int x, int y) {\n    if (!isValid(x, y)) return false;\n    if (state.wall[x][y]) return false;\n    if (hasPetAt(x, y)) return false;\n    if (hasHumanAt(x, y)) return false;\n    if (hasPetAdjacent(x, y)) return false;\n    return true;\n}\n\nint bfsReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint countPetsInReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (hasPetAt(x, y)) count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint getDistance(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint bfsDistance(int x1, int y1, int x2, int y2) {\n    if (!isValid(x1, y1) || !isValid(x2, y2)) return 1e9;\n    if (x1 == x2 && y1 == y2) return 0;\n    \n    vector<vector<int>> dist(GRID_SIZE, vector<int>(GRID_SIZE, 1e9));\n    queue<pair<int, int>> q;\n    \n    dist[x1][y1] = 0;\n    q.push({x1, y1});\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == x2 && y == y2) return dist[x][y];\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny] && dist[nx][ny] == 1e9) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return 1e9;\n}\n\ndouble evaluateAction(int humanIdx, char action) {\n    // Simulate the action and evaluate the result\n    State simState = state;\n    \n    // Apply human action\n    if (action == '.') {\n        // Stay\n    } else if (action >= 'A' && action <= 'Z') {\n        // Move\n        int d = 0;\n        if (action == 'U') d = 0;\n        else if (action == 'D') d = 1;\n        else if (action == 'L') d = 2;\n        else if (action == 'R') d = 3;\n        \n        int nx = simState.humans[humanIdx].x + dx[d];\n        int ny = simState.humans[humanIdx].y + dy[d];\n        \n        if (isValid(nx, ny) && !simState.wall[nx][ny]) {\n            simState.humans[humanIdx].x = nx;\n            simState.humans[humanIdx].y = ny;\n        }\n    } else if (action >= 'a' && action <= 'z') {\n        // Place wall\n        int d = 0;\n        if (action == 'u') d = 0;\n        else if (action == 'd') d = 1;\n        else if (action == 'l') d = 2;\n        else if (action == 'r') d = 3;\n        \n        int wx = simState.humans[humanIdx].x + dx[d];\n        int wy = simState.humans[humanIdx].y + dy[d];\n        \n        if (canPlaceWall(wx, wy)) {\n            simState.wall[wx][wy] = true;\n        }\n    }\n    \n    // Calculate score\n    int reachable = bfsReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    int petsInArea = countPetsInReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    \n    double score = (double)reachable / 900.0 * pow(0.5, petsInArea);\n    \n    // Penalty for being close to dogs\n    for (const auto& pet : simState.pets) {\n        if (pet.type == 4) { // Dog\n            int dist = bfsDistance(simState.humans[humanIdx].x, simState.humans[humanIdx].y, pet.x, pet.y);\n            if (dist < 10) {\n                score -= 0.1 * (10 - dist);\n            }\n        }\n    }\n    \n    return score;\n}\n\nchar decideAction(int humanIdx) {\n    vector<char> possibleActions = {'.', 'U', 'D', 'L', 'R', 'u', 'd', 'l', 'r'};\n    char bestAction = '.';\n    double bestScore = -1e9;\n    \n    for (char action : possibleActions) {\n        // Check if action is valid\n        if (action >= 'A' && action <= 'Z') {\n            int d = 0;\n            if (action == 'U') d = 0;\n            else if (action == 'D') d = 1;\n            else if (action == 'L') d = 2;\n            else if (action == 'R') d = 3;\n            \n            int nx = state.humans[humanIdx].x + dx[d];\n            int ny = state.humans[humanIdx].y + dy[d];\n            \n            if (!isValid(nx, ny) || state.wall[nx][ny]) continue;\n        } else if (action >= 'a' && action <= 'z') {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n        }\n        \n        double score = evaluateAction(humanIdx, action);\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestAction = action;\n        }\n    }\n    \n    return bestAction;\n}\n\nchar decideActionStrategic(int humanIdx) {\n    // Strategic decision based on turn phase\n    int turn = state.turn;\n    \n    // Early phase: Build walls around humans\n    if (turn < 50) {\n        // Prioritize wall placement\n        vector<char> wallActions = {'u', 'd', 'l', 'r'};\n        char bestWall = '.';\n        double bestScore = -1e9;\n        \n        for (char action : wallActions) {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateAction(humanIdx, action);\n            \n            // Bonus for blocking dogs\n            for (const auto& pet : state.pets) {\n                if (pet.type == 4) { // Dog\n                    int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                    if (dist < 15) {\n                        score += 0.5;\n                    }\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestWall = action;\n            }\n        }\n        \n        if (bestWall != '.') return bestWall;\n        \n        // If no good wall placement, stay\n        return '.';\n    }\n    \n    // Middle phase: Expand and defend\n    if (turn < 200) {\n        // Mix of wall placement and movement\n        char action = decideAction(humanIdx);\n        \n        // Bias towards walls if close to pets\n        for (const auto& pet : state.pets) {\n            if (pet.type == 4) { // Dog\n                int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                if (dist < 10) {\n                    // Prefer wall placement\n                    vector<char> wallActions = {'u', 'd', 'l', 'r'};\n                    for (char wall : wallActions) {\n                        int d = 0;\n                        if (wall == 'u') d = 0;\n                        else if (wall == 'd') d = 1;\n                        else if (wall == 'l') d = 2;\n                        else if (wall == 'r') d = 3;\n                        \n                        int wx = state.humans[humanIdx].x + dx[d];\n                        int wy = state.humans[humanIdx].y + dy[d];\n                        \n                        if (canPlaceWall(wx, wy)) {\n                            return wall;\n                        }\n                    }\n                }\n            }\n        }\n        \n        return action;\n    }\n    \n    // Late phase: Fine-tune\n    return decideAction(humanIdx);\n}\n\nvoid updateState(const vector<string>& petMoves) {\n    // Update pet positions based on their moves\n    for (int i = 0; i < state.pets.size(); i++) {\n        const string& move = petMoves[i];\n        int x = state.pets[i].x;\n        int y = state.pets[i].y;\n        \n        for (char c : move) {\n            int d = 0;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            \n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                x = nx;\n                y = ny;\n            }\n        }\n        \n        state.pets[i].x = x;\n        state.pets[i].y = y;\n    }\n    \n    state.turn++;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    // Read input\n    int N;\n    cin >> N;\n    \n    state.pets.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> state.pets[i].x >> state.pets[i].y >> state.pets[i].type;\n        state.pets[i].x--; // Convert to 0-indexed\n        state.pets[i].y--;\n    }\n    \n    int M;\n    cin >> M;\n    \n    state.humans.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> state.humans[i].x >> state.humans[i].y;\n        state.humans[i].x--; // Convert to 0-indexed\n        state.humans[i].y--;\n    }\n    \n    // Initialize state\n    state.turn = 0;\n    state.wall.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    state.passable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Main game loop\n    for (int turn = 0; turn < MAX_TURNS; turn++) {\n        // Check time limit\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2800) {\n            // Output stay for all humans to avoid TLE\n            for (int i = 0; i < M; i++) {\n                cout << '.';\n            }\n            cout << endl;\n            flush(cout);\n            \n            // Read pet moves\n            vector<string> petMoves(M);\n            for (int i = 0; i < N; i++) {\n                cin >> petMoves[i];\n            }\n            continue;\n        }\n        \n        // Decide actions for each human\n        string actions = \"\";\n        for (int i = 0; i < M; i++) {\n            char action = decideActionStrategic(i);\n            actions += action;\n        }\n        \n        cout << actions << endl;\n        flush(cout);\n        \n        // Read pet moves\n        vector<string> petMoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petMoves[i];\n        }\n        \n        // Update state\n        updateState(petMoves);\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int INF = 1e9;\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    if (!(cin >> si >> sj >> ti >> tj >> p)) return 0;\n\n    // Read horizontal walls\n    // h[i][j] is 1 if there is a wall between (i, j) and (i, j+1)\n    vector<string> h(MAX_N);\n    for (int i = 0; i < MAX_N; ++i) {\n        cin >> h[i];\n    }\n\n    // Read vertical walls\n    // v[i][j] is 1 if there is a wall between (i, j) and (i+1, j)\n    vector<string> v(MAX_N - 1);\n    for (int i = 0; i < MAX_N - 1; ++i) {\n        cin >> v[i];\n    }\n\n    // BFS to compute shortest path distances from all cells to the target (ti, tj)\n    // This is used as a heuristic to guide the agent towards the target.\n    vector<vector<int>> dist(MAX_N, vector<int>(MAX_N, INF));\n    queue<pair<int, int>> q;\n\n    dist[ti][tj] = 0;\n    q.push({ti, tj});\n\n    // Directions: R, L, D, U\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    char moves[] = {'R', 'L', 'D', 'U'};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k];\n            int nj = j + dj[k];\n\n            if (ni >= 0 && ni < MAX_N && nj >= 0 && nj < MAX_N) {\n                bool wall = false;\n                if (k == 0) { // R: check wall between (i,j) and (i,j+1)\n                    if (h[i][j] == '1') wall = true;\n                } else if (k == 1) { // L: check wall between (i,j-1) and (i,j)\n                    if (h[i][j-1] == '1') wall = true;\n                } else if (k == 2) { // D: check wall between (i,j) and (i+1,j)\n                    if (v[i][j] == '1') wall = true;\n                } else if (k == 3) { // U: check wall between (i-1,j) and (i,j)\n                    if (v[i-1][j] == '1') wall = true;\n                }\n\n                if (!wall && dist[ni][nj] == INF) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n\n    // Probability distribution of the agent's position\n    // prob[i][j] is the probability that the agent is at (i, j)\n    vector<vector<double>> prob(MAX_N, vector<double>(MAX_N, 0.0));\n    prob[si][sj] = 1.0;\n\n    string result = \"\";\n    double move_prob = 1.0 - p;\n\n    // Buffer for next probability distribution\n    vector<vector<double>> next_prob(MAX_N, vector<double>(MAX_N));\n\n    // Greedily choose the move for each of the 200 steps\n    for (int step = 0; step < 200; ++step) {\n        int best_move = 0;\n        double min_expected_dist = 1e18;\n        double max_reach_prob = -1.0;\n        vector<vector<double>> best_next_prob;\n\n        // Evaluate all 4 possible moves\n        for (int k = 0; k < 4; ++k) {\n            // Reset next_prob buffer\n            for(int i = 0; i < MAX_N; ++i) \n                for(int j = 0; j < MAX_N; ++j) \n                    next_prob[i][j] = 0.0;\n\n            // Simulate the move\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (prob[i][j] == 0.0) continue;\n                    // If already at target, stay there (absorbing state)\n                    if (i == ti && j == tj) {\n                        next_prob[i][j] += prob[i][j];\n                        continue;\n                    }\n\n                    int ni = i + di[k];\n                    int nj = j + dj[k];\n                    bool blocked = false;\n                    \n                    // Check boundaries\n                    if (ni < 0 || ni >= MAX_N || nj < 0 || nj >= MAX_N) blocked = true;\n                    else {\n                        // Check walls\n                        if (k == 0) { if (h[i][j] == '1') blocked = true; }\n                        else if (k == 1) { if (h[i][j-1] == '1') blocked = true; }\n                        else if (k == 2) { if (v[i][j] == '1') blocked = true; }\n                        else if (k == 3) { if (v[i-1][j] == '1') blocked = true; }\n                    }\n\n                    if (blocked) {\n                        // If blocked, agent stays in current square with probability 1\n                        // (p from forgetting + (1-p) from blocked move)\n                        next_prob[i][j] += prob[i][j];\n                    } else {\n                        // Move with probability (1-p)\n                        next_prob[ni][nj] += prob[i][j] * move_prob;\n                        // Stay with probability p (forgetting)\n                        next_prob[i][j] += prob[i][j] * p;\n                    }\n                }\n            }\n\n            // Calculate evaluation metrics\n            double ed = 0.0; // Expected distance to target\n            double rp = 0.0; // Probability of being at target\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (i == ti && j == tj) {\n                        rp = next_prob[i][j];\n                    } else {\n                        if (dist[i][j] != INF) {\n                            ed += next_prob[i][j] * dist[i][j];\n                        }\n                    }\n                }\n            }\n\n            // Select the best move based on metrics\n            // Primary: Minimize expected distance\n            // Secondary: Maximize probability of reaching target (tie-breaker)\n            if (ed < min_expected_dist - 1e-9) {\n                min_expected_dist = ed;\n                max_reach_prob = rp;\n                best_move = k;\n                best_next_prob = next_prob;\n            } else if (abs(ed - min_expected_dist) < 1e-9) {\n                if (rp > max_reach_prob) {\n                    max_reach_prob = rp;\n                    best_move = k;\n                    best_next_prob = next_prob;\n                }\n            }\n        }\n\n        // Append the best move to the result string\n        result += moves[best_move];\n        // Update the probability distribution\n        prob = best_next_prob;\n    }\n\n    cout << result << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to table from problem statement\nconst int to[8][4] = {\n    {1, 0, -1, -1}, // 0\n    {3, -1, -1, 0}, // 1\n    {-1, -1, 3, 2}, // 2\n    {-1, 2, 1, -1}, // 3\n    {1, 0, 3, 2},   // 4\n    {3, 2, 1, 0},   // 5\n    {2, -1, 0, -1}, // 6\n    {-1, 3, -1, 1}  // 7\n};\n\nint grid_type[30][30];\nint rot[30][30];\nint best_rot[30][30];\n\n// Visited generation array to avoid memset every time\nint vis_gen[30][30][4];\nint dist[30][30][4];\nint trace_id = 0;\n\nint get_effective_type(int base, int r) {\n    if (base < 4) return (base + r) % 4;\n    if (base == 4) return 4 + (r % 2);\n    if (base == 5) return 5 - (r % 2);\n    if (base == 6) return 6 + (r % 2);\n    if (base == 7) return 7 - (r % 2);\n    return 0;\n}\n\nlong long calc_score() {\n    static vector<int> lengths;\n    lengths.clear();\n    lengths.reserve(900);\n\n    trace_id++;\n    if (trace_id == 0) { // Overflow protection\n        memset(vis_gen, 0, sizeof(vis_gen));\n        trace_id = 1;\n    }\n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (vis_gen[i][j][d] == trace_id) continue;\n\n                int cur_i = i, cur_j = j, cur_d = d;\n                int steps = 0;\n                bool cycle_found = false;\n                int cycle_len = 0;\n\n                // Trace\n                while (true) {\n                    if (vis_gen[cur_i][cur_j][cur_d] == trace_id) {\n                        // Found a node visited in this trace\n                        cycle_len = steps - dist[cur_i][cur_j][cur_d];\n                        cycle_found = true;\n                        break;\n                    }\n                    if (vis_gen[cur_i][cur_j][cur_d] != 0) {\n                        // Visited in previous trace, no new cycle\n                        break;\n                    }\n\n                    vis_gen[cur_i][cur_j][cur_d] = trace_id;\n                    dist[cur_i][cur_j][cur_d] = steps;\n\n                    int t = get_effective_type(grid_type[cur_i][cur_j], rot[cur_i][cur_j]);\n                    int next_d = to[t][cur_d];\n                    if (next_d == -1) break;\n\n                    int next_i = cur_i + di[next_d];\n                    int next_j = cur_j + dj[next_d];\n\n                    if (next_i < 0 || next_i >= 30 || next_j < 0 || next_j >= 30) break;\n\n                    cur_i = next_i;\n                    cur_j = next_j;\n                    cur_d = (next_d + 2) % 4;\n                    steps++;\n                }\n\n                if (cycle_found) {\n                    lengths.push_back(cycle_len);\n                }\n            }\n        }\n    }\n\n    if (lengths.size() < 2) return 0;\n    sort(lengths.rbegin(), lengths.rend());\n    return (long long)lengths[0] * lengths[1];\n}\n\nvoid solve() {\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            grid_type[i][j] = s[j] - '0';\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_rot(0, 3);\n    uniform_int_distribution<int> dist_idx(0, 29);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Initialize random rotations\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            rot[i][j] = dist_rot(rng);\n        }\n    }\n\n    // Copy to best\n    for (int i = 0; i < 30; ++i)\n        for (int j = 0; j < 30; ++j)\n            best_rot[i][j] = rot[i][j];\n\n    long long best_score = calc_score();\n    long long current_score = best_score;\n\n    auto start_time = chrono::steady_clock::now();\n    auto limit_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    double T = 10000.0;\n    int restart_count = 0;\n    int no_improve_count = 0;\n\n    while (chrono::steady_clock::now() < limit_time) {\n        int r = dist_idx(rng);\n        int c = dist_idx(rng);\n\n        int old_rot = rot[r][c];\n        rot[r][c] = (rot[r][c] + 1) % 4;\n\n        long long new_score = calc_score();\n\n        // Acceptance criteria\n        bool accept = false;\n        if (new_score > current_score) {\n            accept = true;\n        } else if (new_score == current_score) {\n            // Accept equal score to allow movement\n            accept = true;\n        } else {\n            // Metropolis criterion\n            double prob = exp((new_score - current_score) / T);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n\n        if (accept) {\n            current_score = new_score;\n            no_improve_count = 0;\n            if (new_score > best_score) {\n                best_score = new_score;\n                for (int i = 0; i < 30; ++i)\n                    for (int j = 0; j < 30; ++j)\n                        best_rot[i][j] = rot[i][j];\n            }\n        } else {\n            rot[r][c] = old_rot;\n            no_improve_count++;\n        }\n\n        // Restart if stuck at 0 score\n        if (best_score == 0 && no_improve_count > 50000) {\n            restart_count++;\n            no_improve_count = 0;\n            // Randomize again\n            for (int i = 0; i < 30; ++i) {\n                for (int j = 0; j < 30; ++j) {\n                    rot[i][j] = dist_rot(rng);\n                }\n            }\n            current_score = calc_score();\n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int i = 0; i < 30; ++i)\n                    for (int j = 0; j < 30; ++j)\n                        best_rot[i][j] = rot[i][j];\n            }\n            T = 10000.0;\n        }\n\n        T *= 0.999;\n        if (T < 1.0) T = 1.0;\n    }\n\n    // Output best_rot\n    string out = \"\";\n    out.reserve(900);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            out += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << out << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <map>\n\nusing namespace std;\n\n// Global variables\nint N, T;\nvector<string> input_board;\nint board[12][12];\nint target[12][12];\nint counts[16];\nstring moves;\nint empty_r, empty_c;\n\n// Directions: U, D, L, R\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dchar[] = {'U', 'D', 'L', 'R'};\n\n// Helper to get tile value from hex char\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return 0;\n}\n\n// Check if a move is valid\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Apply a move\nvoid apply_move(char move) {\n    int dir = -1;\n    if (move == 'U') dir = 0;\n    else if (move == 'D') dir = 1;\n    else if (move == 'L') dir = 2;\n    else if (move == 'R') dir = 3;\n    \n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    \n    if (!is_valid(nr, nc)) return;\n    \n    int tile = board[nr][nc];\n    board[empty_r][empty_c] = tile;\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    moves += move;\n}\n\n// Undo a move (for backtracking in solver if needed, but we don't use it)\n// We will simulate moves directly.\n\n// BFS to find shortest path for empty square\n// Returns sequence of moves to reach (tr, tc)\n// Obstacles are tiles that are already placed correctly (solved)\n// We pass a mask or list of solved cells?\n// Actually, we can just check against the target configuration.\n// But during solving, the board is changing.\n// We need to know which cells are \"locked\" (solved).\n// We can maintain a `solved[N][N]` boolean array.\nbool solved[12][12];\n\nstring bfs_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return \"\";\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\n    \n    // Parent pointers to reconstruct path\n    // Use a map or 2D array\n    // Since N is small, 2D array is fine.\n    // Store move char to reach this cell\n    char parent_move[12][12];\n    bool visited[12][12];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        visited[i][j] = false;\n        parent_move[i][j] = 0;\n    }\n    \n    visited[empty_r][empty_c] = true;\n    \n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            // Reconstruct path\n            string path = \"\";\n            int cr = tr, cc = tc;\n            while(cr != empty_r || cc != empty_c) {\n                char m = parent_move[cr][cc];\n                path += m;\n                // Move back\n                int dir = -1;\n                if (m == 'U') dir = 0;\n                else if (m == 'D') dir = 1;\n                else if (m == 'L') dir = 2;\n                else if (m == 'R') dir = 3;\n                // Reverse direction\n                int rev_dr = -dr[dir];\n                int rev_dc = -dc[dir];\n                cr += rev_dr;\n                cc += rev_dc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (is_valid(nr, nc) && !visited[nr][nc]) {\n                // Check if this cell is solved (locked)\n                // We can only move the empty square into unsolved cells.\n                // Wait, the empty square moves into the cell where a tile is.\n                // So we are swapping empty with a tile.\n                // The tile moves to (r, c).\n                // If (r, c) is solved, we shouldn't move the tile out of it.\n                // So we cannot move empty square FROM a solved cell?\n                // No, the empty square is at (r, c). We move it to (nr, nc).\n                // This means the tile at (nr, nc) moves to (r, c).\n                // If (nr, nc) is a solved tile, we shouldn't move it.\n                // So we cannot move empty square into a solved cell.\n                if (solved[nr][nc]) continue;\n                \n                visited[nr][nc] = true;\n                parent_move[nr][nc] = dchar[i];\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\"; // Should not happen\n}\n\n// Find position of a tile\npair<int, int> find_tile(int val) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == val) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Place a tile at target position\n// This function assumes we can move the empty square freely in unsolved region\n// It brings the tile to (tr, tc)\nvoid place_tile_at(int tr, int tc) {\n    int target_val = target[tr][tc];\n    if (board[tr][tc] == target_val) return;\n    \n    // Find where the target tile is\n    auto pos = find_tile(target_val);\n    int fr = pos.first, fc = pos.second;\n    \n    // We need to move the tile from (fr, fc) to (tr, tc).\n    // This is done by moving the empty square to a position adjacent to (fr, fc),\n    // then moving the tile towards (tr, tc).\n    // However, a simpler strategy is:\n    // 1. Move empty square to (fr, fc) is not possible directly if we want to move tile.\n    //    We need to move empty square to a neighbor of (fr, fc), say (nr, nc).\n    //    Then move tile from (fr, fc) to (nr, nc).\n    //    Then repeat until tile is at (tr, tc).\n    // But this is complex to implement generally.\n    // Instead, we can use the standard approach:\n    // Move empty square to a position such that we can slide the tile into (tr, tc).\n    // Specifically, move empty square to (tr, tc) first? No, (tr, tc) is the target.\n    // We want to bring the tile to (tr, tc).\n    // So we want the empty square to be at a neighbor of (tr, tc), and the tile at the other side.\n    // Or we can move the empty square to (fr, fc) (which is currently occupied by the tile) -> Impossible.\n    // We need to move the empty square to a neighbor of (fr, fc), then swap.\n    // Let's use BFS to find a path for the empty square to reach a neighbor of (fr, fc).\n    // Then move the tile one step.\n    // Repeat until tile is at (tr, tc).\n    // But we must not disturb solved tiles.\n    // The solved tiles are locked.\n    // So we treat solved tiles as obstacles for the empty square.\n    // Also, we must not move the target tile out of the way if it's already placed?\n    // No, we are placing it.\n    \n    // Strategy:\n    // While tile is not at (tr, tc):\n    //   Find a path for empty square to a neighbor of the tile (fr, fc).\n    //   The neighbor must be in the unsolved region (or the target position).\n    //   Move empty square there.\n    //   Move tile into the empty square's position.\n    //   Update (fr, fc).\n    \n    // This is basically moving the tile towards (tr, tc) using the empty square.\n    // We need to ensure we don't block the path.\n    // Since the unsolved region is connected, this should work.\n    \n    // Optimization: Calculate a path for the tile to (tr, tc) avoiding solved tiles.\n    // Then move empty square to facilitate each step.\n    // But BFS for empty square is safer.\n    \n    while (fr != tr || fc != tc) {\n        // We want to move tile from (fr, fc) to a neighbor closer to (tr, tc).\n        // Let's find a neighbor (nr, nc) of (fr, fc) such that:\n        // 1. (nr, nc) is not solved.\n        // 2. (nr, nc) is closer to (tr, tc) or is (tr, tc).\n        // Actually, any unsolved neighbor is fine, but we want to progress.\n        // Let's try to move towards (tr, tc).\n        \n        int best_nr = -1, best_nc = -1;\n        int min_dist = 1e9;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = fr + dr[i];\n            int nc = fc + dc[i];\n            if (is_valid(nr, nc) && !solved[nr][nc]) {\n                int dist = abs(nr - tr) + abs(nc - tc);\n                if (dist < min_dist) {\n                    min_dist = dist;\n                    best_nr = nr;\n                    best_nc = nc;\n                }\n            }\n        }\n        \n        // If no neighbor is unsolved, we are stuck. But this shouldn't happen.\n        if (best_nr == -1) {\n            // Fallback: any unsolved neighbor\n            for (int i = 0; i < 4; ++i) {\n                int nr = fr + dr[i];\n                int nc = fc + dc[i];\n                if (is_valid(nr, nc) && !solved[nr][nc]) {\n                    best_nr = nr;\n                    best_nc = nc;\n                    break;\n                }\n            }\n        }\n        \n        if (best_nr == -1) break; // Should not happen\n        \n        // Move empty square to (best_nr, best_nc)\n        // But wait, (best_nr, best_nc) is currently occupied by some tile.\n        // We want to move the empty square to (best_nr, best_nc).\n        // Then swap with (fr, fc).\n        // So we need path from empty_r, empty_c to best_nr, best_nc.\n        // But we must not pass through (fr, fc) because it's occupied by the tile we want to move.\n        // Actually, BFS handles obstacles. We should mark (fr, fc) as obstacle for empty square path?\n        // No, (fr, fc) is occupied by the tile. Empty square cannot go there.\n        // So (fr, fc) is naturally an obstacle for empty square.\n        // But we need to make sure BFS doesn't consider it as a valid cell for empty square.\n        // Our BFS checks `!visited`. `board[fr][fc]` is not 0, so empty square is not there.\n        // So BFS will not go to (fr, fc).\n        // However, we need to ensure we don't move other tiles that are solved.\n        // `solved` array handles that.\n        \n        string path = bfs_to(best_nr, best_nc);\n        for (char m : path) apply_move(m);\n        \n        // Now empty square is at (best_nr, best_nc).\n        // Tile is at (fr, fc).\n        // We need to move tile to (best_nr, best_nc).\n        // This means moving empty square to (fr, fc).\n        // But (fr, fc) is adjacent to (best_nr, best_nc).\n        // So we just need to apply the reverse move of the last step?\n        // No, we need to move the tile.\n        // The move is: slide tile from (fr, fc) to (best_nr, best_nc).\n        // This corresponds to moving empty square from (best_nr, best_nc) to (fr, fc).\n        // So we find the direction from (best_nr, best_nc) to (fr, fc).\n        \n        int dir = -1;\n        if (fr == best_nr - 1) dir = 0; // Empty moves Up to (fr, fc) -> Tile moves Down\n        else if (fr == best_nr + 1) dir = 1;\n        else if (fc == best_nc - 1) dir = 2;\n        else if (fc == best_nc + 1) dir = 3;\n        \n        apply_move(dchar[dir]);\n        \n        // Update tile position\n        fr = best_nr;\n        fc = best_nc;\n        \n        if (moves.size() > T) {\n            cout << moves << endl;\n            exit(0);\n        }\n    }\n    solved[tr][tc] = true;\n}\n\n// Backtracking to find target configuration\nbool solve_target(int idx) {\n    if (idx == N * N) return true;\n    \n    int r = idx / N;\n    int c = idx % N;\n    \n    // If this is the empty square position\n    if (r == N - 1 && c == N - 1) {\n        if (counts[0] > 0) {\n            target[r][c] = 0;\n            counts[0]--;\n            if (solve_target(idx + 1)) return true;\n            counts[0]++;\n            target[r][c] = -1;\n        }\n        return false;\n    }\n    \n    // Try all tile types\n    for (int t = 1; t <= 15; ++t) {\n        if (counts[t] > 0) {\n            // Check compatibility with left neighbor\n            if (c > 0) {\n                int left = target[r][c - 1];\n                if (left != 0) {\n                    // left must have Right (4) iff t has Left (1)\n                    bool left_has_right = (left & 4) != 0;\n                    bool t_has_left = (t & 1) != 0;\n                    if (left_has_right != t_has_left) continue;\n                }\n            }\n            // Check compatibility with top neighbor\n            if (r > 0) {\n                int top = target[r - 1][c];\n                if (top != 0) {\n                    // top must have Down (8) iff t has Up (2)\n                    bool top_has_down = (top & 8) != 0;\n                    bool t_has_up = (t & 2) != 0;\n                    if (top_has_down != t_has_up) continue;\n                }\n            }\n            \n            target[r][c] = t;\n            counts[t]--;\n            if (solve_target(idx + 1)) return true;\n            counts[t]++;\n            target[r][c] = -1;\n        }\n    }\n    \n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T)) return 0;\n    \n    input_board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> input_board[i];\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(input_board[i][j]);\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n            counts[board[i][j]]++;\n        }\n    }\n    \n    // Initialize target with -1\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            target[i][j] = -1;\n            \n    // Solve target configuration\n    // We assume empty square is at (N-1, N-1) for target\n    // But we must ensure counts[0] is 1.\n    // The input has exactly one 0.\n    \n    if (!solve_target(0)) {\n        // Should not happen based on problem statement\n        return 0;\n    }\n    \n    // Initialize solved array\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            solved[i][j] = false;\n            \n    // Solve puzzle\n    // Phase 1: First N-1 rows, first N-1 cols\n    for (int r = 0; r < N - 1; ++r) {\n        for (int c = 0; c < N - 1; ++c) {\n            place_tile_at(r, c);\n            if (moves.size() > T) {\n                cout << moves << endl;\n                return 0;\n            }\n        }\n    }\n    \n    // Phase 2: Last column, first N-1 rows\n    for (int r = 0; r < N - 1; ++r) {\n        place_tile_at(r, N - 1);\n        if (moves.size() > T) {\n            cout << moves << endl;\n            return 0;\n        }\n    }\n    \n    // Phase 3: Last row, first N-1 cols\n    for (int c = 0; c < N - 1; ++c) {\n        place_tile_at(N - 1, c);\n        if (moves.size() > T) {\n            cout << moves << endl;\n            return 0;\n        }\n    }\n    \n    // The empty square should be at (N-1, N-1) now.\n    // If not, it's fine as long as tiles are correct.\n    // But our target has 0 at (N-1, N-1).\n    // So the last cell is automatically correct.\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\n// Cross product to determine which side of line a point is on\nint point_side(const Line& line, const Point& p) {\n    long long dx = line.qx - line.px;\n    long long dy = line.qy - line.py;\n    long long px = p.x - line.px;\n    long long py = p.y - line.py;\n    long long cp = dx * py - dy * px;\n    if (cp > 0) return 1;\n    if (cp < 0) return -1;\n    return 0;\n}\n\n// Calculate score for current cut configuration\nint calculate_score(const vector<Point>& strawberries, \n                    const vector<Line>& cuts, \n                    const vector<int>& a) {\n    int n = strawberries.size();\n    int k = cuts.size();\n    \n    // For each strawberry, determine its region (bitmask of which side of each cut)\n    vector<int> region(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < k; j++) {\n            int side = point_side(cuts[j], strawberries[i]);\n            if (side == 1) {\n                region[i] |= (1 << j);\n            }\n            // If side == 0, strawberry is on the line (doesn't count)\n        }\n    }\n    \n    // Count strawberries in each region\n    map<int, int> region_count;\n    for (int i = 0; i < n; i++) {\n        if (region[i] != -1) { // Not on any line\n            region_count[region[i]]++;\n        }\n    }\n    \n    // Calculate score\n    int total_score = 0;\n    int total_attendees = 0;\n    for (int d = 1; d <= 10; d++) {\n        total_attendees += a[d];\n    }\n    \n    if (total_attendees == 0) return 0;\n    \n    // Count pieces with each number of strawberries\n    vector<int> b(11, 0);\n    for (const auto& [region_id, count] : region_count) {\n        if (count >= 1 && count <= 10) {\n            b[count]++;\n        }\n    }\n    \n    int distributed = 0;\n    for (int d = 1; d <= 10; d++) {\n        distributed += min(a[d], b[d]);\n    }\n    \n    return round(1e6 * distributed / total_attendees);\n}\n\n// Generate a random line\nLine generate_random_line(mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    line.px = dist(gen);\n    line.py = dist(gen);\n    line.qx = dist(gen);\n    line.qy = dist(gen);\n    \n    // Ensure points are different\n    while (line.px == line.qx && line.py == line.qy) {\n        line.qx = dist(gen);\n        line.qy = dist(gen);\n    }\n    \n    return line;\n}\n\n// Generate a line that passes between two strawberries\nLine generate_separating_line(const Point& p1, const Point& p2, \n                              mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    \n    // Create a line perpendicular to the segment p1-p2\n    long long dx = p2.x - p1.x;\n    long long dy = p2.y - p1.y;\n    \n    // Midpoint\n    long long mx = (p1.x + p2.x) / 2;\n    long long my = (p1.y + p2.y) / 2;\n    \n    // Perpendicular direction\n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    // Add some randomness\n    long long offset_x = dist(gen) % 100000 - 50000;\n    long long offset_y = dist(gen) % 100000 - 50000;\n    \n    line.px = mx + pdx + offset_x;\n    line.py = my + pdy + offset_y;\n    line.qx = mx - pdx + offset_x;\n    line.qy = my - pdy + offset_y;\n    \n    return line;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(11);\n    for (int i = 1; i <= 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<long long> dist(-1000000000, 1000000000);\n    \n    vector<Line> cuts;\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::steady_clock::now() + chrono::seconds(2.8);\n    \n    // Phase 1: Generate initial random cuts\n    for (int i = 0; i < min(K, 30); i++) {\n        if (chrono::steady_clock::now() > time_limit) break;\n        cuts.push_back(generate_random_line(gen, dist));\n    }\n    \n    // Phase 2: Try to improve with strategic cuts\n    int attempts = 0;\n    int max_attempts = 50000;\n    \n    while (chrono::steady_clock::now() < time_limit && attempts < max_attempts) {\n        attempts++;\n        \n        if (cuts.size() >= K) {\n            // Try to replace a cut\n            int idx = gen() % cuts.size();\n            Line new_cut = generate_random_line(gen, dist);\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts[idx] = new_cut;\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        } else {\n            // Try to add a cut\n            Line new_cut = generate_random_line(gen, dist);\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.push_back(new_cut);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n        \n        // Occasionally try strategic cuts between strawberries\n        if (attempts % 100 == 0 && cuts.size() < K) {\n            int i1 = gen() % N;\n            int i2 = gen() % N;\n            while (i2 == i1) i2 = gen() % N;\n            \n            Line strategic_cut = generate_separating_line(strawberries[i1], strawberries[i2], gen, dist);\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.push_back(strategic_cut);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n    }\n    \n    // Final optimization: try to remove unnecessary cuts\n    for (int i = cuts.size() - 1; i >= 0; i--) {\n        if (chrono::steady_clock::now() > time_limit) break;\n        \n        vector<Line> test_cuts = cuts;\n        test_cuts.erase(test_cuts.begin() + i);\n        \n        int old_score = calculate_score(strawberries, cuts, a);\n        int new_score = calculate_score(strawberries, test_cuts, a);\n        \n        if (new_score >= old_score) {\n            cuts = test_cuts;\n        }\n    }\n    \n    // Output\n    cout << cuts.size() << endl;\n    for (const auto& cut : cuts) {\n        cout << cut.px << \" \" << cut.py << \" \" << cut.qx << \" \" << cut.qy << endl;\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Point structure\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\n// Rectangle edge representation\nstruct Edge {\n    int x1, y1, x2, y2;\n    bool operator<(const Edge& other) const {\n        if (x1 != other.x1) return x1 < other.x1;\n        if (y1 != other.y1) return y1 < other.y1;\n        if (x2 != other.x2) return x2 < other.x2;\n        return y2 < other.y2;\n    }\n};\n\n// Operation record\nstruct Operation {\n    Point p1, p2, p3, p4;\n    double score;\n};\n\nclass RectJoinSolver {\nprivate:\n    int N, M;\n    set<Point> dots;\n    set<Edge> drawnEdges;\n    vector<Operation> operations;\n    int cx, cy;\n    \n    // Calculate weight of a point\n    double weight(int x, int y) const {\n        return (double)(x - cx) * (x - cx) + (double)(y - cy) * (y - cy) + 1.0;\n    }\n    \n    // Check if point is within grid\n    bool inGrid(int x, int y) const {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    }\n    \n    // Check if point has a dot\n    bool hasDot(int x, int y) const {\n        return dots.count({x, y}) > 0;\n    }\n    \n    // Normalize edge for consistent representation\n    Edge normalizeEdge(int x1, int y1, int x2, int y2) const {\n        if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n            return {x2, y2, x1, y1};\n        }\n        return {x1, y1, x2, y2};\n    }\n    \n    // Check if edge already exists\n    bool edgeExists(int x1, int y1, int x2, int y2) const {\n        return drawnEdges.count(normalizeEdge(x1, y1, x2, y2)) > 0;\n    }\n    \n    // Add edge to drawn edges\n    void addEdge(int x1, int y1, int x2, int y2) {\n        drawnEdges.insert(normalizeEdge(x1, y1, x2, y2));\n    }\n    \n    // Check if two edges share a segment of positive length\n    bool edgesOverlap(const Edge& e1, const Edge& e2) const {\n        // Check if edges are on the same line\n        if (e1.x1 == e1.x2 && e2.x1 == e2.x2) {\n            // Both vertical\n            if (e1.x1 != e2.x1) return false;\n            int yMin1 = min(e1.y1, e1.y2), yMax1 = max(e1.y1, e1.y2);\n            int yMin2 = min(e2.y1, e2.y2), yMax2 = max(e2.y1, e2.y2);\n            int overlapMin = max(yMin1, yMin2), overlapMax = min(yMax1, yMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        if (e1.y1 == e1.y2 && e2.y1 == e2.y2) {\n            // Both horizontal\n            if (e1.y1 != e2.y1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            int overlapMin = max(xMin1, xMin2), overlapMax = min(xMax1, xMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        return false;\n    }\n    \n    // Check if any edge of rectangle overlaps with existing edges\n    bool rectangleOverlaps(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const {\n        Edge edges[4] = {\n            normalizeEdge(x1, y1, x2, y2),\n            normalizeEdge(x2, y2, x3, y3),\n            normalizeEdge(x3, y3, x4, y4),\n            normalizeEdge(x4, y4, x1, y1)\n        };\n        \n        for (const auto& e : edges) {\n            for (const auto& existing : drawnEdges) {\n                if (edgesOverlap(e, existing)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n    \n    // Check if there are dots on rectangle perimeter (excluding the 3 existing dots)\n    bool hasDotsOnPerimeter(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,\n                           const Point& p2, const Point& p3, const Point& p4) const {\n        auto checkEdge = [&](int x1, int y1, int x2, int y2) {\n            int dx = x2 - x1, dy = y2 - y1;\n            int steps = max(abs(dx), abs(dy));\n            for (int i = 1; i < steps; i++) {\n                int x = x1 + dx * i / steps;\n                int y = y1 + dy * i / steps;\n                // Skip the three existing dots\n                if ((x == p2.x && y == p2.y) || (x == p3.x && y == p3.y) || \n                    (x == p4.x && y == p4.y)) continue;\n                if (hasDot(x, y)) return true;\n            }\n            return false;\n        };\n        \n        return checkEdge(x1, y1, x2, y2) ||\n               checkEdge(x2, y2, x3, y3) ||\n               checkEdge(x3, y3, x4, y4) ||\n               checkEdge(x4, y4, x1, y1);\n    }\n    \n    // Find 4th point for rectangle given 3 points\n    // Returns true if valid rectangle can be formed\n    bool findRectanglePoint(const Point& p2, const Point& p3, const Point& p4, Point& p1) const {\n        // Try all 6 permutations to find which 3 points form 3 corners of rectangle\n        // and calculate the 4th point\n        \n        // For axis-aligned rectangle: opposite corners have same x or same y\n        // For 45-degree rectangle: diagonal properties differ\n        \n        // Case 1: p2, p3, p4 are consecutive corners\n        // p1 should complete the rectangle\n        \n        // Check if p2-p3 and p3-p4 are perpendicular\n        int dx1 = p3.x - p2.x, dy1 = p3.y - p2.y;\n        int dx2 = p4.x - p3.x, dy2 = p4.y - p3.y;\n        \n        // For axis-aligned: one of dx1,dy1 is 0, one of dx2,dy2 is 0\n        // For 45-degree: |dx1| == |dy1| and |dx2| == |dy2|\n        \n        // Calculate potential p1 for different configurations\n        // Rectangle: p1, p2, p3, p4 in order\n        \n        // Configuration 1: p2, p3, p4 are corners, find p1\n        // p1 = p2 + p4 - p3 (vector addition)\n        p1.x = p2.x + p4.x - p3.x;\n        p1.y = p2.y + p4.y - p3.y;\n        \n        if (!inGrid(p1.x, p1.y)) return false;\n        \n        // Verify rectangle properties\n        int dx21 = p1.x - p2.x, dy21 = p1.y - p2.y;\n        int dx34 = p4.x - p3.x, dy34 = p4.y - p3.y;\n        int dx14 = p4.x - p1.x, dy14 = p4.y - p1.y;\n        int dx23 = p3.x - p2.x, dy23 = p3.y - p2.y;\n        \n        // Check if opposite sides are equal and parallel\n        bool axisAligned = (dx21 == dx34 && dy21 == dy34) && \n                          (dx14 == dx23 && dy14 == dy23);\n        \n        bool diagonal45 = (abs(dx21) == abs(dy21) && abs(dx14) == abs(dy14)) &&\n                         (abs(dx34) == abs(dy34) && abs(dx23) == abs(dy23));\n        \n        if (!axisAligned && !diagonal45) return false;\n        \n        return true;\n    }\n    \n    // Find all valid moves\n    vector<Operation> findValidMoves() {\n        vector<Operation> validMoves;\n        vector<Point> dotList(dots.begin(), dots.end());\n        int nDots = dotList.size();\n        \n        // Try all combinations of 3 dots\n        for (int i = 0; i < nDots; i++) {\n            for (int j = i + 1; j < nDots; j++) {\n                for (int k = j + 1; k < nDots; k++) {\n                    Point p2 = dotList[i];\n                    Point p3 = dotList[j];\n                    Point p4 = dotList[k];\n                    \n                    // Try to find p1 that completes rectangle\n                    Point p1;\n                    if (!findRectanglePoint(p2, p3, p4, p1)) continue;\n                    \n                    // p1 must not have a dot yet\n                    if (hasDot(p1.x, p1.y)) continue;\n                    \n                    // Check rectangle overlaps\n                    if (rectangleOverlaps(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y)) continue;\n                    \n                    // Check dots on perimeter\n                    if (hasDotsOnPerimeter(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y,\n                                          p2, p3, p4)) continue;\n                    \n                    Operation op;\n                    op.p1 = p1;\n                    op.p2 = p2;\n                    op.p3 = p3;\n                    op.p4 = p4;\n                    op.score = weight(p1.x, p1.y);\n                    \n                    validMoves.push_back(op);\n                }\n            }\n        }\n        \n        return validMoves;\n    }\n    \n    // Execute a move\n    void executeMove(const Operation& op) {\n        dots.insert(op.p1);\n        addEdge(op.p1.x, op.p1.y, op.p2.x, op.p2.y);\n        addEdge(op.p2.x, op.p2.y, op.p3.x, op.p3.y);\n        addEdge(op.p3.x, op.p3.y, op.p4.x, op.p4.y);\n        addEdge(op.p4.x, op.p4.y, op.p1.x, op.p1.y);\n        operations.push_back(op);\n    }\n    \npublic:\n    RectJoinSolver(int n, int m, const vector<pair<int,int>>& initial) {\n        N = n; M = m;\n        cx = (N - 1) / 2;\n        cy = (N - 1) / 2;\n        \n        for (const auto& p : initial) {\n            dots.insert({p.first, p.second});\n        }\n    }\n    \n    void solve() {\n        auto startTime = chrono::steady_clock::now();\n        auto timeLimit = chrono::seconds(4); // Leave margin for 5 sec limit\n        \n        int maxIterations = 10000;\n        int iteration = 0;\n        \n        while (iteration < maxIterations) {\n            auto currentTime = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::seconds>(currentTime - startTime).count() >= 4) {\n                break;\n            }\n            \n            vector<Operation> moves = findValidMoves();\n            \n            if (moves.empty()) break;\n            \n            // Sort by weight (higher weight first)\n            sort(moves.begin(), moves.end(), [](const Operation& a, const Operation& b) {\n                return a.score > b.score;\n            });\n            \n            // Execute best move\n            executeMove(moves[0]);\n            iteration++;\n        }\n    }\n    \n    void output() const {\n        cout << operations.size() << endl;\n        for (const auto& op : operations) {\n            cout << op.p1.x << \" \" << op.p1.y << \" \"\n                 << op.p2.x << \" \" << op.p2.y << \" \"\n                 << op.p3.x << \" \" << op.p3.y << \" \"\n                 << op.p4.x << \" \" << op.p4.y << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    \n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initial[i].first >> initial[i].second;\n    }\n    \n    RectJoinSolver solver(N, M, initial);\n    solver.solve();\n    solver.output();\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Board representation: 10x10 grid, 0=empty, 1-3=flavors\nstruct Board {\n    int grid[10][10];\n    \n    Board() {\n        for(int i = 0; i < 10; i++)\n            for(int j = 0; j < 10; j++)\n                grid[i][j] = 0;\n    }\n};\n\n// Count connected components and calculate score\nlong long calculateScore(const Board& b) {\n    int visited[10][10];\n    for(int i = 0; i < 10; i++)\n        for(int j = 0; j < 10; j++)\n            visited[i][j] = 0;\n    \n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n    \n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] != 0 && !visited[i][j]) {\n                // BFS for connected component\n                int flavor = b.grid[i][j];\n                int size = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = 1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    size++;\n                    \n                    for(int d = 0; d < 4; d++) {\n                        int nr = r + dr[d];\n                        int nc = c + dc[d];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10) {\n                            if(!visited[nr][nc] && b.grid[nr][nc] == flavor) {\n                                visited[nr][nc] = 1;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Tilt board in given direction\nvoid tilt(Board& b, char dir) {\n    Board newb = b;\n    \n    if(dir == 'F') { // Forward (up)\n        for(int j = 0; j < 10; j++) {\n            int write = 0;\n            for(int i = 0; i < 10; i++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int i = write; i < 10; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'B') { // Backward (down)\n        for(int j = 0; j < 10; j++) {\n            int write = 9;\n            for(int i = 9; i >= 0; i--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int i = 0; i < write; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'L') { // Left\n        for(int i = 0; i < 10; i++) {\n            int write = 0;\n            for(int j = 0; j < 10; j++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int j = write; j < 10; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'R') { // Right\n        for(int i = 0; i < 10; i++) {\n            int write = 9;\n            for(int j = 9; j >= 0; j--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int j = 0; j < write; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    }\n    \n    b = newb;\n}\n\n// Count candies of each flavor\nvoid countFlavors(const Board& b, int& f1, int& f2, int& f3) {\n    f1 = f2 = f3 = 0;\n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] == 1) f1++;\n            else if(b.grid[i][j] == 2) f2++;\n            else if(b.grid[i][j] == 3) f3++;\n        }\n    }\n}\n\n// Calculate normalized score\ndouble getNormalizedScore(const Board& b) {\n    int f1, f2, f3;\n    countFlavors(b, f1, f2, f3);\n    long long numerator = calculateScore(b);\n    long long denominator = (long long)f1*f1 + (long long)f2*f2 + (long long)f3*f3;\n    if(denominator == 0) return 0;\n    return (double)numerator / denominator;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read all flavors in advance\n    vector<int> flavors(100);\n    for(int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    Board board;\n    char directions[] = {'F', 'B', 'L', 'R'};\n    \n    // Process each candy placement\n    for(int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Place candy in p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int count = 0;\n        for(int i = 0; i < 10; i++) {\n            for(int j = 0; j < 10; j++) {\n                if(board.grid[i][j] == 0) {\n                    count++;\n                    if(count == p) {\n                        board.grid[i][j] = flavors[t];\n                        break;\n                    }\n                }\n                if(count == p) break;\n            }\n            if(count == p) break;\n        }\n        \n        // Skip output for last step (nothing happens)\n        if(t == 99) {\n            cout << \"F\" << endl;\n            continue;\n        }\n        \n        // Try all 4 directions and pick the best\n        double bestScore = -1;\n        char bestDir = 'F';\n        \n        for(char dir : directions) {\n            Board temp = board;\n            tilt(temp, dir);\n            double score = getNormalizedScore(temp);\n            \n            if(score > bestScore) {\n                bestScore = score;\n                bestDir = dir;\n            }\n        }\n        \n        // Apply the best direction\n        tilt(board, bestDir);\n        cout << bestDir << endl;\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <bitset>\n\nusing namespace std;\n\n// Maximum N is 100\nconst int MAX_N = 100;\n\nstruct Graph {\n    int n;\n    vector<bitset<MAX_N>> adj;\n\n    Graph(int n) : n(n), adj(n) {}\n\n    // Parse from string\n    static Graph from_string(int n, const string& s) {\n        Graph g(n);\n        int idx = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (idx < s.size()) {\n                    if (s[idx] == '1') {\n                        g.adj[i][j] = 1;\n                        g.adj[j][i] = 1;\n                    }\n                }\n                idx++;\n            }\n        }\n        return g;\n    }\n\n    // To string\n    string to_string() const {\n        string s;\n        s.reserve(n * (n - 1) / 2);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                s += (adj[i][j] ? '1' : '0');\n            }\n        }\n        return s;\n    }\n\n    // Generate random graph with probability p\n    static Graph random(int n, double p, mt19937& gen) {\n        Graph g(n);\n        uniform_real_distribution<double> dist(0.0, 1.0);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (dist(gen) < p) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                }\n            }\n        }\n        return g;\n    }\n};\n\nstruct Features {\n    double edge_count;\n    double triangle_count;\n    double sum_sq_deg;\n    double sum_cube_deg;\n    vector<double> sorted_degrees;\n\n    Features() : edge_count(0), triangle_count(0), sum_sq_deg(0), sum_cube_deg(0) {}\n};\n\nFeatures compute_features(const Graph& g) {\n    Features f;\n    f.edge_count = 0;\n    f.sum_sq_deg = 0;\n    f.sum_cube_deg = 0;\n    f.sorted_degrees.resize(g.n);\n\n    vector<int> deg(g.n, 0);\n    for (int i = 0; i < g.n; ++i) {\n        deg[i] = g.adj[i].count();\n        f.edge_count += deg[i];\n        f.sum_sq_deg += (double)deg[i] * deg[i];\n        f.sum_cube_deg += (double)deg[i] * deg[i] * deg[i];\n    }\n    f.edge_count /= 2.0;\n    f.sorted_degrees = deg;\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Count triangles\n    // O(N^3 / 64) using bitsets\n    f.triangle_count = 0;\n    for (int i = 0; i < g.n; ++i) {\n        for (int j = i + 1; j < g.n; ++j) {\n            if (g.adj[i][j]) {\n                // Count common neighbors of i and j\n                // Only count neighbors k > j to avoid overcounting\n                // Actually, standard way: sum over i<j<k.\n                // Here we iterate i, j. We need k > j.\n                // bitset::count counts all set bits. We need to mask k > j.\n                // Since we only care about existence, we can just iterate k.\n                // Optimization: bitset AND.\n                // But bitset doesn't support range count efficiently.\n                // For N=100, simple loop is fast enough.\n                for (int k = j + 1; k < g.n; ++k) {\n                    if (g.adj[i][k] && g.adj[j][k]) {\n                        f.triangle_count++;\n                    }\n                }\n            }\n        }\n    }\n    return f;\n}\n\n// Expected features under noise epsilon\nFeatures compute_expected_features(const Graph& g, double eps) {\n    Features f;\n    int n = g.n;\n    int total_edges = n * (n - 1) / 2;\n\n    // Expected Edge Count\n    // E = E_g * (1 - eps) + (Total - E_g) * eps\n    //   = E_g * (1 - 2*eps) + Total * eps\n    double E_g = g.adj[0].count() / 2.0; // Not accurate, need to sum properly\n    // Recompute E_g accurately\n    long long e_g = 0;\n    for(int i=0; i<n; ++i) e_g += g.adj[i].count();\n    e_g /= 2;\n    f.edge_count = e_g * (1.0 - 2.0 * eps) + total_edges * eps;\n\n    // Expected Degree Sequence\n    // E[d_i] = d_i * (1 - 2*eps) + (n - 1) * eps\n    vector<double> exp_deg(n);\n    for (int i = 0; i < n; ++i) {\n        double d_i = (double)g.adj[i].count();\n        exp_deg[i] = d_i * (1.0 - 2.0 * eps) + (n - 1) * eps;\n    }\n    f.sorted_degrees = exp_deg;\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Expected Sum Sq Deg\n    // E[d_i^2] = d_i^2 (1-eps)^2 + (n-1-d_i)^2 eps^2 + 2 d_i (n-1-d_i) eps (1-eps)\n    // Actually, d_i is sum of Bernoulli trials.\n    // Var(d_i) = (n-1) eps (1-eps).\n    // E[d_i^2] = Var(d_i) + E[d_i]^2.\n    f.sum_sq_deg = 0;\n    f.sum_cube_deg = 0; // Harder to compute exact expectation for cube.\n    // Let's use E[d_i]^2 approximation for sum_sq_deg? No, use Var + Mean^2.\n    double var_deg = (n - 1) * eps * (1.0 - eps);\n    for (int i = 0; i < n; ++i) {\n        double mean_d = exp_deg[i];\n        f.sum_sq_deg += var_deg + mean_d * mean_d;\n        // For cube, approximation: E[X^3] approx E[X]^3 + 3 E[X] Var[X]\n        // This is for Gaussian. Bernoulli sum is close to Gaussian for large n.\n        f.sum_cube_deg += mean_d * mean_d * mean_d + 3.0 * mean_d * var_deg;\n    }\n\n    // Expected Triangle Count\n    // For each triplet, calculate prob of forming triangle.\n    // Let k be edges in G among triplet.\n    // Prob = (1-eps)^3 if k=3\n    //       eps*(1-eps)^2 if k=2\n    //       eps^2*(1-eps) if k=1\n    //       eps^3 if k=0\n    // We can iterate all triplets.\n    f.triangle_count = 0;\n    double p0 = pow(eps, 3);\n    double p1 = pow(eps, 2) * (1.0 - eps);\n    double p2 = eps * pow(1.0 - eps, 2);\n    double p3 = pow(1.0 - eps, 3);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            for (int k = j + 1; k < n; ++k) {\n                int edges = 0;\n                if (g.adj[i][j]) edges++;\n                if (g.adj[i][k]) edges++;\n                if (g.adj[j][k]) edges++;\n                if (edges == 0) f.triangle_count += p0;\n                else if (edges == 1) f.triangle_count += p1;\n                else if (edges == 2) f.triangle_count += p2;\n                else f.triangle_count += p3;\n            }\n        }\n    }\n\n    return f;\n}\n\ndouble feature_distance(const Features& f1, const Features& f2) {\n    double dist = 0.0;\n    // Weighted distance\n    // Normalize by expected variance?\n    // For simplicity, use Euclidean on normalized features.\n    // We assume features have different scales.\n    // Edge count ~ N^2/2. Triangles ~ N^3/6.\n    // Let's normalize by N^2 and N^3.\n    \n    // Actually, just raw distance might be dominated by high magnitude features.\n    // Let's use relative differences or standard normalization.\n    // For this heuristic, let's use simple Euclidean on scaled features.\n    \n    // Scale factors\n    double s_ec = 1.0; // Edge count\n    double s_tc = 1.0 / 100.0; // Triangle count usually larger\n    double s_sq = 1.0 / 1000.0; // Sum sq deg\n    double s_cb = 1.0 / 10000.0; // Sum cube deg\n    double s_deg = 1.0 / 10.0; // Degree (0 to N)\n\n    dist += s_ec * (f1.edge_count - f2.edge_count) * (f1.edge_count - f2.edge_count);\n    dist += s_tc * (f1.triangle_count - f2.triangle_count) * (f1.triangle_count - f2.triangle_count);\n    dist += s_sq * (f1.sum_sq_deg - f2.sum_sq_deg) * (f1.sum_sq_deg - f2.sum_sq_deg);\n    dist += s_cb * (f1.sum_cube_deg - f2.sum_cube_deg) * (f1.sum_cube_deg - f2.sum_cube_deg);\n    \n    for (size_t i = 0; i < f1.sorted_degrees.size(); ++i) {\n        dist += s_deg * (f1.sorted_degrees[i] - f2.sorted_degrees[i]) * (f1.sorted_degrees[i] - f2.sorted_degrees[i]);\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Optimization Phase\n    // We want to find N and M graphs that maximize score.\n    // Score = 0.9^E / N.\n    // We estimate E based on margin.\n    \n    int best_N = 40;\n    vector<Graph> best_Gs;\n    vector<Features> best_ExpectedFeatures;\n    double best_score = -1.0;\n\n    // Try different N\n    // Time limit 5s. Let's spend ~3s optimizing.\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 3.0; // seconds\n\n    // Search space for N\n    vector<int> N_candidates = {20, 30, 40, 50, 60, 70, 80, 90};\n    // If M is large, we might need larger N.\n    if (M > 50) N_candidates = {40, 50, 60, 70, 80, 90};\n    if (M > 80) N_candidates = {50, 60, 70, 80, 90};\n\n    for (int N : N_candidates) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        // Generate candidate graphs\n        // We need M graphs. Generate pool of size 5*M.\n        int pool_size = min(500, M * 5);\n        vector<Graph> candidates;\n        candidates.reserve(pool_size);\n        \n        // Density distribution\n        // Random graphs with varying densities are good.\n        for (int i = 0; i < pool_size; ++i) {\n            double p = (double)rand() / RAND_MAX; // Simple random density\n            // Better: uniform random edges\n            // Let's just use random edges with p=0.5 for variety\n            // Or p from 0.1 to 0.9\n            p = 0.1 + 0.8 * ((double)rand() / RAND_MAX);\n            candidates.push_back(Graph::random(N, p, gen));\n        }\n\n        // Compute expected features for candidates\n        vector<Features> cand_expected(pool_size);\n        for (int i = 0; i < pool_size; ++i) {\n            cand_expected[i] = compute_expected_features(candidates[i], eps);\n        }\n\n        // Greedy selection of M graphs to maximize min distance\n        vector<int> selected_indices;\n        selected_indices.reserve(M);\n        \n        // Pick first one arbitrarily\n        selected_indices.push_back(0);\n        \n        for (int i = 1; i < M; ++i) {\n            int best_idx = -1;\n            double max_min_dist = -1.0;\n            \n            for (int j = 0; j < pool_size; ++j) {\n                if (find(selected_indices.begin(), selected_indices.end(), j) != selected_indices.end()) continue;\n                \n                double min_d = 1e18;\n                for (int k : selected_indices) {\n                    double d = feature_distance(cand_expected[j], cand_expected[k]);\n                    if (d < min_d) min_d = d;\n                }\n                \n                if (min_d > max_min_dist) {\n                    max_min_dist = min_d;\n                    best_idx = j;\n                }\n            }\n            \n            if (best_idx != -1) {\n                selected_indices.push_back(best_idx);\n            } else {\n                // Fallback: pick random\n                int r = rand() % pool_size;\n                while (find(selected_indices.begin(), selected_indices.end(), r) != selected_indices.end()) r = rand() % pool_size;\n                selected_indices.push_back(r);\n            }\n        }\n\n        // Estimate Margin\n        double min_pair_dist = 1e18;\n        for (size_t i = 0; i < selected_indices.size(); ++i) {\n            for (size_t j = i + 1; j < selected_indices.size(); ++j) {\n                double d = feature_distance(cand_expected[selected_indices[i]], cand_expected[selected_indices[j]]);\n                if (d < min_pair_dist) min_pair_dist = d;\n            }\n        }\n\n        // Estimate Error E\n        // If min_pair_dist is large, E is small.\n        // Heuristic: E = max(0, 100 * exp(-min_pair_dist / 10.0))\n        // This is very rough.\n        // Let's assume if min_pair_dist > 5000, E=0.\n        // The scale of distance depends on N.\n        // Let's just use min_pair_dist as a proxy for quality.\n        // We want to maximize Quality / N.\n        // Quality = min_pair_dist.\n        // Score = 0.9^E / N.\n        // Let's assume E = 100 * exp(-min_pair_dist / 5000.0).\n        // If min_pair_dist is very small, E=100.\n        \n        double E_est = 0.0;\n        if (min_pair_dist < 1000.0) {\n             E_est = 100.0 * exp(-min_pair_dist / 500.0);\n        } else {\n             E_est = 100.0 * exp(-min_pair_dist / 5000.0);\n        }\n        if (E_est < 0.0) E_est = 0.0;\n        if (E_est > 100.0) E_est = 100.0;\n\n        double score = pow(0.9, E_est) / N;\n        \n        // We prefer smaller N if score is similar\n        if (score > best_score || (abs(score - best_score) < 1e-9 && N < best_N)) {\n            best_score = score;\n            best_N = N;\n            best_Gs.clear();\n            best_ExpectedFeatures.clear();\n            for (int idx : selected_indices) {\n                best_Gs.push_back(candidates[idx]);\n                best_ExpectedFeatures.push_back(cand_expected[idx]);\n            }\n        }\n    }\n\n    // Output N and Graphs\n    cout << best_N << endl;\n    for (const auto& g : best_Gs) {\n        cout << g.to_string() << endl;\n    }\n    cout.flush();\n\n    // Query Processing\n    // We have best_Gs and best_ExpectedFeatures.\n    // For each query, compute features of H, find closest.\n    \n    // Precompute expected features for best_Gs (already done in best_ExpectedFeatures)\n    \n    string H_str;\n    for (int q = 0; q < 100; ++q) {\n        cin >> H_str;\n        Graph H = Graph::from_string(best_N, H_str);\n        Features h_feat = compute_features(H);\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double d = feature_distance(h_feat, best_ExpectedFeatures[k]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint N, M, D, K;\nstruct Edge {\n    int u, v, w, id;\n};\nvector<Edge> edges;\nvector<int> edge_day;\nvector<vector<long long>> dist_original;\nmt19937 rng;\n\nvoid init_rng() {\n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n}\n\nvoid calc_original_distances() {\n    dist_original.assign(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int i = 1; i <= N; i++) {\n        dist_original[i][i] = 0;\n    }\n    \n    for (auto& e : edges) {\n        dist_original[e.u][e.v] = min(dist_original[e.u][e.v], (long long)e.w);\n        dist_original[e.v][e.u] = min(dist_original[e.v][e.u], (long long)e.w);\n    }\n    \n    for (int k = 1; k <= N; k++) {\n        for (int i = 1; i <= N; i++) {\n            if (dist_original[i][k] == 1e18) continue;\n            for (int j = 1; j <= N; j++) {\n                if (dist_original[k][j] == 1e18) continue;\n                dist_original[i][j] = min(dist_original[i][j], dist_original[i][k] + dist_original[k][j]);\n            }\n        }\n    }\n}\n\nlong long calc_frustration_day(int k) {\n    vector<vector<long long>> dist(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int i = 1; i <= N; i++) {\n        dist[i][i] = 0;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        if (edge_day[i] != k) {\n            dist[edges[i].u][edges[i].v] = min(dist[edges[i].u][edges[i].v], (long long)edges[i].w);\n            dist[edges[i].v][edges[i].u] = min(dist[edges[i].v][edges[i].u], (long long)edges[i].w);\n        }\n    }\n    \n    for (int k_iter = 1; k_iter <= N; k_iter++) {\n        for (int i = 1; i <= N; i++) {\n            if (dist[i][k_iter] == 1e18) continue;\n            for (int j = 1; j <= N; j++) {\n                if (dist[k_iter][j] == 1e18) continue;\n                dist[i][j] = min(dist[i][j], dist[i][k_iter] + dist[k_iter][j]);\n            }\n        }\n    }\n    \n    long long total_increase = 0;\n    for (int i = 1; i <= N; i++) {\n        for (int j = 1; j <= N; j++) {\n            if (i != j) {\n                if (dist[i][j] >= 1e9) {\n                    total_increase += 1e9;\n                } else {\n                    total_increase += max(0LL, dist[i][j] - dist_original[i][j]);\n                }\n            }\n        }\n    }\n    \n    return total_increase;\n}\n\nlong long calc_total_frustration() {\n    long long total = 0;\n    for (int k = 1; k <= D; k++) {\n        total += calc_frustration_day(k);\n    }\n    return total;\n}\n\nvoid init_solution() {\n    edge_day.assign(M, 0);\n    vector<int> day_count(D + 1, 0);\n    \n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    shuffle(edge_order.begin(), edge_order.end(), rng);\n    \n    for (int i : edge_order) {\n        int best_day = 1;\n        for (int d = 2; d <= D; d++) {\n            if (day_count[d] < day_count[best_day]) {\n                best_day = d;\n            }\n        }\n        edge_day[i] = best_day;\n        day_count[best_day]++;\n    }\n}\n\nvoid local_search() {\n    long long best_frustration = calc_total_frustration();\n    vector<int> best_day = edge_day;\n    \n    int no_improve = 0;\n    int max_no_improve = 300;\n    \n    while (no_improve < max_no_improve) {\n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) continue;\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        long long new_frustration = calc_total_frustration();\n        \n        if (new_frustration < best_frustration) {\n            best_frustration = new_frustration;\n            best_day = edge_day;\n            no_improve = 0;\n        } else {\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            no_improve++;\n        }\n    }\n    \n    edge_day = best_day;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> D >> K;\n    \n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i;\n    }\n    \n    vector<int> x(N + 1), y(N + 1);\n    for (int i = 1; i <= N; i++) {\n        cin >> x[i] >> y[i];\n    }\n    \n    init_rng();\n    calc_original_distances();\n    init_solution();\n    local_search();\n    \n    for (int i = 0; i < M; i++) {\n        cout << edge_day[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int MAXD = 15;\n\nint D;\nvector<string> f[2], r[2];\nint b[2][MAXD][MAXD][MAXD];\n\n// Block structure\nstruct Block {\n    int id;\n    vector<tuple<int,int,int>> cells;\n    int volume;\n    \n    Block() : id(0), volume(0) {}\n    Block(int i, const vector<tuple<int,int,int>>& c) : id(i), cells(c), volume(c.size()) {}\n};\n\n// Get all 24 rotations of a shape\nvector<vector<tuple<int,int,int>>> get_rotations(const vector<tuple<int,int,int>>& shape) {\n    vector<vector<tuple<int,int,int>>> rotations;\n    \n    auto normalize = [](vector<tuple<int,int,int>> s) {\n        int min_x = 0, min_y = 0, min_z = 0;\n        for (auto& [x, y, z] : s) {\n            min_x = min(min_x, x);\n            min_y = min(min_y, y);\n            min_z = min(min_z, z);\n        }\n        for (auto& [x, y, z] : s) {\n            x -= min_x;\n            y -= min_y;\n            z -= min_z;\n        }\n        sort(s.begin(), s.end());\n        return s;\n    };\n    \n    auto rotate_x = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(x, z, -y);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_y = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-z, y, x);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_z = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-y, x, z);\n        }\n        return normalize(s);\n    };\n    \n    vector<tuple<int,int,int>> current = shape;\n    set<vector<tuple<int,int,int>>> seen;\n    queue<vector<tuple<int,int,int>>> q;\n    \n    current = normalize(current);\n    seen.insert(current);\n    q.push(current);\n    rotations.push_back(current);\n    \n    while (!q.empty()) {\n        auto cur = q.front();\n        q.pop();\n        \n        for (auto& rot : {rotate_x, rotate_y, rotate_z}) {\n            auto next = rot(cur);\n            if (seen.find(next) == seen.end()) {\n                seen.insert(next);\n                q.push(next);\n                rotations.push_back(next);\n            }\n        }\n    }\n    \n    return rotations;\n}\n\n// Check if two shapes can match through rotation/translation\nbool can_match_shapes(const vector<tuple<int,int,int>>& shape1, const vector<tuple<int,int,int>>& shape2) {\n    if (shape1.size() != shape2.size()) return false;\n    \n    auto norm2 = normalize(shape2);\n    auto rotations = get_rotations(shape1);\n    \n    for (const auto& rot : rotations) {\n        if (rot == norm2) return true;\n    }\n    \n    return false;\n}\n\n// Normalize a shape for comparison\nvector<tuple<int,int,int>> normalize(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> s = shape;\n    if (s.empty()) return s;\n    \n    int min_x = 0, min_y = 0, min_z = 0;\n    for (auto& [x, y, z] : s) {\n        min_x = min(min_x, x);\n        min_y = min(min_y, y);\n        min_z = min(min_z, z);\n    }\n    for (auto& [x, y, z] : s) {\n        x -= min_x;\n        y -= min_y;\n        z -= min_z;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\n// Find connected components in a 3D grid\nvector<vector<tuple<int,int,int>>> find_connected_components(int id, const int (*grid)[MAXD][MAXD][MAXD]) {\n    vector<vector<tuple<int,int,int>>> components;\n    bool visited[MAXD][MAXD][MAXD] = {0};\n    \n    auto bfs = [&](int sx, int sy, int sz, int target_id) {\n        vector<tuple<int,int,int>> component;\n        queue<tuple<int,int,int>> q;\n        \n        visited[sx][sy][sz] = true;\n        q.push({sx, sy, sz});\n        component.push_back({sx, sy, sz});\n        \n        int dx[] = {1, -1, 0, 0, 0, 0};\n        int dy[] = {0, 0, 1, -1, 0, 0};\n        int dz[] = {0, 0, 0, 0, 1, -1};\n        \n        while (!q.empty()) {\n            auto [x, y, z] = q.front();\n            q.pop();\n            \n            for (int i = 0; i < 6; i++) {\n                int nx = x + dx[i];\n                int ny = y + dy[i];\n                int nz = z + dz[i];\n                \n                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                    !visited[nx][ny][nz] && (*grid)[nx][ny][nz] == target_id) {\n                    visited[nx][ny][nz] = true;\n                    q.push({nx, ny, nz});\n                    component.push_back({nx, ny, nz});\n                }\n            }\n        }\n        \n        return component;\n    };\n    \n    // Find all blocks with their IDs\n    map<int, vector<tuple<int,int,int>>> blocks;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if ((*grid)[x][y][z] > 0) {\n                    blocks[(*grid)[x][y][z]].push_back({x, y, z});\n                }\n            }\n        }\n    }\n    \n    for (auto& [id, cells] : blocks) {\n        components.push_back(cells);\n    }\n    \n    return components;\n}\n\n// Main optimization function\nvoid optimize() {\n    // Phase 1: Initial placement - place unit blocks at all valid positions\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent blocks with same ID to form larger blocks\n    // This is already done by the initial placement\n    \n    // Phase 3: Try to find common blocks between the two constructions\n    // Group blocks by their normalized shapes\n    map<vector<tuple<int,int,int>>, vector<pair<int,int>>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back({id, i});\n        }\n    }\n    \n    // Phase 4: Try to merge blocks that have matching shapes\n    // This is a heuristic - we prioritize larger blocks and shared blocks\n    \n    // For now, output the initial solution\n    // A more sophisticated solution would use simulated annealing or genetic algorithms\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        r[i].resize(D);\n        for (int z = 0; z < D; z++) {\n            cin >> f[i][z];\n        }\n        for (int z = 0; z < D; z++) {\n            cin >> r[i][z];\n        }\n    }\n    \n    // Initialize block arrays\n    memset(b, 0, sizeof(b));\n    \n    // Phase 1: Initial placement\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent cells into connected components\n    // This creates larger blocks from adjacent unit blocks\n    int new_block_counter = 0;\n    int temp_b[2][MAXD][MAXD][MAXD];\n    memset(temp_b, 0, sizeof(temp_b));\n    \n    for (int i = 0; i < 2; i++) {\n        // Find connected components\n        bool visited[MAXD][MAXD][MAXD] = {0};\n        \n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0 && !visited[x][y][z]) {\n                        // BFS to find connected component\n                        vector<tuple<int,int,int>> component;\n                        queue<tuple<int,int,int>> q;\n                        \n                        visited[x][y][z] = true;\n                        q.push({x, y, z});\n                        component.push_back({x, y, z});\n                        \n                        int dx[] = {1, -1, 0, 0, 0, 0};\n                        int dy[] = {0, 0, 1, -1, 0, 0};\n                        int dz[] = {0, 0, 0, 0, 1, -1};\n                        \n                        while (!q.empty()) {\n                            auto [cx, cy, cz] = q.front();\n                            q.pop();\n                            \n                            for (int d = 0; d < 6; d++) {\n                                int nx = cx + dx[d];\n                                int ny = cy + dy[d];\n                                int nz = cz + dz[d];\n                                \n                                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                    !visited[nx][ny][nz] && b[i][nx][ny][nz] > 0) {\n                                    visited[nx][ny][nz] = true;\n                                    q.push({nx, ny, nz});\n                                    component.push_back({nx, ny, nz});\n                                }\n                            }\n                        }\n                        \n                        // Assign new block ID to all cells in component\n                        new_block_counter++;\n                        for (auto& [cx, cy, cz] : component) {\n                            temp_b[i][cx][cy][cz] = new_block_counter;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Copy back\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    b[i][x][y][z] = temp_b[i][x][y][z];\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Try to match blocks between the two constructions\n    // Group blocks by normalized shape\n    map<vector<tuple<int,int,int>>, vector<int>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back(id);\n        }\n    }\n    \n    // Try to reuse blocks with matching shapes\n    int reused_blocks = 0;\n    for (auto& [norm, ids1] : shape_to_blocks[0]) {\n        if (shape_to_blocks[1].find(norm) != shape_to_blocks[1].end()) {\n            auto& ids2 = shape_to_blocks[1][norm];\n            // Reuse the first matching block\n            if (!ids1.empty() && !ids2.empty()) {\n                int reuse_id = ids1[0];\n                for (int x = 0; x < D; x++) {\n                    for (int y = 0; y < D; y++) {\n                        for (int z = 0; z < D; z++) {\n                            if (b[1][x][y][z] == ids2[0]) {\n                                b[1][x][y][z] = reuse_id;\n                            }\n                        }\n                    }\n                }\n                reused_blocks++;\n            }\n        }\n    }\n    \n    // Output\n    cout << new_block_counter << \"\\n\";\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    cout << b[i][x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \");\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst long long INF_COST = 1e18;\nconst int MAX_P = 5000;\n\n// Data structures\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int _x, int _y) : x(_x), y(_y) {}\n    \n    long long distSq(const Point& other) const {\n        return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y);\n    }\n    \n    double dist(const Point& other) const {\n        return sqrt(distSq(other));\n    }\n};\n\nstruct Edge {\n    int u, v, w;\n    int id;\n};\n\nstruct Resident {\n    int x, y, id;\n};\n\n// Global data\nint N, M, K;\nvector<Point> stations;\nvector<Edge> edges;\nvector<Resident> residents;\nvector<int> P;\nvector<int> B;\nvector<int> activeStations;\nvector<vector<int>> stationResidents;\nvector<vector<int>> adj;\nvector<long long> edgeCost;\n\n// Calculate total cost\nlong long calculateCost() {\n    long long cost = 0;\n    \n    // Edge costs\n    for (int j = 0; j < M; j++) {\n        if (B[j]) cost += edges[j].w;\n    }\n    \n    // Coverage costs\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    \n    return cost;\n}\n\n// Check if all residents are covered\nbool allCovered() {\n    for (int k = 0; k < K; k++) {\n        bool covered = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && stations[i].distSq(residents[k]) <= 1LL * P[i] * P[i]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\n// Check connectivity from vertex 1\nbool isConnected() {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    \n    q.push(0);\n    visited[0] = true;\n    \n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        \n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int edgeIdx = edge.second;\n            \n            if (B[edgeIdx] && !visited[v]) {\n                visited[v] = true;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Check if all stations with P > 0 are reachable\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && !visited[i]) {\n            return false;\n        }\n    }\n    \n    return true;\n}\n\n// Get minimum P needed to cover a resident\nint getPForResident(int stationIdx, int residentIdx) {\n    long long d2 = stations[stationIdx].distSq(residents[residentIdx]);\n    if (d2 > 1LL * MAX_P * MAX_P) return -1;\n    return (int)ceil(sqrt(d2));\n}\n\n// Assign residents to nearest active station\nvoid assignResidentsToStations() {\n    stationResidents.assign(N, vector<int>());\n    \n    for (int k = 0; k < K; k++) {\n        int bestStation = -1;\n        long long minDist = INF_COST;\n        \n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0) {\n                long long d = stations[i].distSq(residents[k]);\n                if (d < minDist) {\n                    minDist = d;\n                    bestStation = i;\n                }\n            }\n        }\n        \n        if (bestStation >= 0) {\n            stationResidents[bestStation].push_back(k);\n        }\n    }\n}\n\n// Calculate optimal P for each station based on assigned residents\nvoid optimizeP() {\n    for (int i = 0; i < N; i++) {\n        if (stationResidents[i].empty()) {\n            P[i] = 0;\n            continue;\n        }\n        \n        // Find maximum distance to any assigned resident\n        long long maxDist = 0;\n        for (int k : stationResidents[i]) {\n            maxDist = max(maxDist, stations[i].distSq(residents[k]));\n        }\n        \n        if (maxDist > 1LL * MAX_P * MAX_P) {\n            P[i] = MAX_P;\n        } else {\n            P[i] = (int)ceil(sqrt(maxDist));\n        }\n    }\n}\n\n// Build MST to connect active stations to vertex 1\nvoid buildNetwork() {\n    // Reset all edges\n    fill(B.begin(), B.end(), 0);\n    \n    // Collect active stations\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0) active.push_back(i);\n    }\n    \n    // If vertex 1 is not active, make it active\n    if (P[0] == 0 && !active.empty()) {\n        P[0] = 1;\n        active.push_back(0);\n    }\n    \n    // Use Kruskal's algorithm to connect all active stations\n    struct EdgeWithCost {\n        int u, v, w, id;\n    };\n    \n    vector<EdgeWithCost> edgeList;\n    for (int j = 0; j < M; j++) {\n        edgeList.push_back({edges[j].u - 1, edges[j].v - 1, edges[j].w, j});\n    }\n    \n    sort(edgeList.begin(), edgeList.end(), [](const EdgeWithCost& a, const EdgeWithCost& b) {\n        return a.w < b.w;\n    });\n    \n    // Union-Find\n    vector<int> parent(N);\n    iota(parent.begin(), parent.end(), 0);\n    \n    function<int(int)> find = [&](int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    };\n    \n    auto unite = [&](int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x != y) {\n            parent[x] = y;\n            return true;\n        }\n        return false;\n    };\n    \n    // Connect all active stations to vertex 1\n    for (auto& e : edgeList) {\n        if (find(e.u) != find(e.v)) {\n            unite(e.u, e.v);\n            B[e.id] = 1;\n        }\n    }\n}\n\n// Local search: try adding/removing stations\nvoid localSearch() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int iterations = 10000;\n    double temperature = 1000000.0;\n    double coolingRate = 0.9995;\n    \n    long long bestCost = calculateCost();\n    vector<int> bestP = P;\n    vector<int> bestB = B;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        // Try random modification\n        int action = rng() % 5;\n        \n        if (action == 0) {\n            // Try activating a new station\n            int station = rng() % N;\n            if (P[station] == 0) {\n                int oldP = P[station];\n                P[station] = 1;\n                \n                // Assign nearby residents\n                for (int k = 0; k < K; k++) {\n                    long long d = stations[station].distSq(residents[k]);\n                    if (d <= 1LL * MAX_P * MAX_P) {\n                        // Check if this is better than current assignment\n                        int currentBest = -1;\n                        long long currentDist = INF_COST;\n                        for (int i = 0; i < N; i++) {\n                            if (P[i] > 0) {\n                                long long d2 = stations[i].distSq(residents[k]);\n                                if (d2 < currentDist) {\n                                    currentDist = d2;\n                                    currentBest = i;\n                                }\n                            }\n                        }\n                        \n                        if (currentBest < 0 || d < currentDist) {\n                            // Reassign to this station\n                            optimizeP();\n                        }\n                    }\n                }\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 1) {\n            // Try deactivating a station\n            vector<int> activeStations;\n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) activeStations.push_back(i);\n            }\n            \n            if (activeStations.size() > 1) {\n                int idx = rng() % activeStations.size();\n                int station = activeStations[idx];\n                \n                // Skip vertex 1\n                if (station == 0) continue;\n                \n                int oldP = P[station];\n                P[station] = 0;\n                \n                // Reassign residents\n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 2) {\n            // Try increasing P\n            int station = rng() % N;\n            if (P[station] < MAX_P) {\n                int oldP = P[station];\n                P[station] = min(MAX_P, P[station] + rng() % 500 + 1);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 3) {\n            // Try decreasing P\n            int station = rng() % N;\n            if (P[station] > 0) {\n                int oldP = P[station];\n                P[station] = max(0, P[station] - rng() % 500);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else {\n            // Try reassigning a random resident\n            int resident = rng() % K;\n            int bestStation = -1;\n            long long minDist = INF_COST;\n            \n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) {\n                    long long d = stations[i].distSq(residents[resident]);\n                    if (d < minDist) {\n                        minDist = d;\n                        bestStation = i;\n                    }\n                }\n            }\n            \n            if (bestStation >= 0) {\n                int oldP = P[bestStation];\n                int newP = (int)ceil(sqrt(minDist));\n                P[bestStation] = newP;\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[bestStation] = oldP;\n                    buildNetwork();\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    P = bestP;\n    B = bestB;\n}\n\n// Initial solution\nvoid initSolution() {\n    P.assign(N, 0);\n    B.assign(M, 0);\n    \n    // Find nearest station for each resident\n    vector<int> residentStation(K, -1);\n    vector<long long> residentDist(K, INF_COST);\n    \n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d = stations[i].distSq(residents[k]);\n            if (d < residentDist[k]) {\n                residentDist[k] = d;\n                residentStation[k] = i;\n            }\n        }\n    }\n    \n    // Set P for each station based on assigned residents\n    for (int i = 0; i < N; i++) {\n        long long maxDist = 0;\n        for (int k = 0; k < K; k++) {\n            if (residentStation[k] == i) {\n                maxDist = max(maxDist, residentDist[k]);\n            }\n        }\n        \n        if (maxDist > 0) {\n            P[i] = (int)ceil(sqrt(maxDist));\n            if (P[i] > MAX_P) P[i] = MAX_P;\n        }\n    }\n    \n    // Ensure vertex 1 is active if needed\n    if (P[0] == 0) {\n        P[0] = 1;\n    }\n    \n    // Build network\n    buildNetwork();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N >> M >> K;\n    \n    stations.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    edgeCost.resize(M);\n    \n    for (int j = 0; j < M; j++) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n        edges[j].u--;\n        edges[j].v--;\n        edges[j].id = j;\n        adj[edges[j].u].push_back({edges[j].v, j});\n        adj[edges[j].v].push_back({edges[j].u, j});\n        edgeCost[j] = edges[j].w;\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n    \n    // Initial solution\n    initSolution();\n    \n    // Local search with simulated annealing\n    localSearch();\n    \n    // Final optimization\n    optimizeP();\n    buildNetwork();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\n\nint N = 30;\nvector<vector<int>> grid;\nvector<tuple<int, int, int, int>> operations;\n\n// Get all 6 adjacent positions\nvector<pair<int, int>> get_adj(int x, int y) {\n    vector<pair<int, int>> adj;\n    int dx[] = {-1, -1, 0, 0, 1, 1};\n    int dy[] = {-1, 0, -1, 1, 0, 1};\n    \n    for (int i = 0; i < 6; i++) {\n        int nx = x + dx[i];\n        int ny = y + dy[i];\n        if (nx >= 0 && nx < N && ny >= 0 && ny <= nx) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\n// BFS to find shortest path from (sx, sy) to (tx, ty)\nvector<pair<int, int>> bfs_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {};\n    \n    queue<pair<int, int>> q;\n    map<pair<int, int>, pair<int, int>> parent;\n    \n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == tx && y == ty) {\n            vector<pair<int, int>> path;\n            auto curr = make_pair(tx, ty);\n            while (curr.first != -1 && curr.second != -1) {\n                path.push_back(curr);\n                curr = parent[curr];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto [nx, ny] : get_adj(x, y)) {\n            if (parent.find({nx, ny}) == parent.end()) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    return {};\n}\n\n// Swap balls at two positions and record operation\nvoid swap_positions(int x1, int y1, int x2, int y2) {\n    int temp = grid[x1][y1];\n    grid[x1][y1] = grid[x2][y2];\n    grid[x2][y2] = temp;\n    operations.emplace_back(x1, y1, x2, y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    grid.resize(N);\n    for (int x = 0; x < N; x++) {\n        grid[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n        }\n    }\n    \n    // Track which positions are already filled\n    vector<vector<bool>> filled(N);\n    for (int x = 0; x < N; x++) {\n        filled[x].assign(x + 1, false);\n    }\n    \n    // Process positions from top to bottom\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (filled[x][y]) continue;\n            \n            // Find smallest ball among all unfilled positions\n            int best_val = 1e9;\n            int best_x = -1, best_y = -1;\n            \n            for (int px = x; px < N; px++) {\n                for (int py = 0; py <= px; py++) {\n                    if (!filled[px][py] && grid[px][py] < best_val) {\n                        best_val = grid[px][py];\n                        best_x = px;\n                        best_y = py;\n                    }\n                }\n            }\n            \n            // Move the best ball to current position\n            if (best_x != -1 && (best_x != x || best_y != y)) {\n                vector<pair<int, int>> path = bfs_path(best_x, best_y, x, y);\n                \n                // Perform swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); i++) {\n                    auto [x1, y1] = path[i];\n                    auto [x2, y2] = path[i + 1];\n                    swap_positions(x1, y1, x2, y2);\n                }\n            }\n            \n            filled[x][y] = true;\n        }\n    }\n    \n    // Output results\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <tuple>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\n// Grid dimensions\nconst int D = 9;\nint N;\nvector<pair<int, int>> obstacles;\nvector<vector<int>> grid; // 0: empty, 1: obstacle, 2: container\nvector<vector<int>> container_id; // ID of container at (i, j), -1 if empty\nvector<pair<int, int>> used_coords; // To track placed containers\n\n// Directions\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\n// BFS to find reachable empty squares and distances\n// Returns a map of (i, j) -> distance\nmap<pair<int, int>, int> get_distances(int start_i, int start_j) {\n    map<pair<int, int>, int> dist;\n    queue<pair<int, int>> q;\n    q.push({start_i, start_j});\n    dist[{start_i, start_j}] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n            if (nr >= 0 && nr < D && nc >= 0 && nc < D) {\n                if (grid[nr][nc] == 0 && dist.find({nr, nc}) == dist.end()) {\n                    dist[{nr, nc}] = dist[{r, c}] + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return dist;\n}\n\n// Check if a square is \"Safe\" to place a container\n// Safe means removing it (making it occupied) does not disconnect any other empty squares from entrance\nbool is_safe(int r, int c, int entrance_r, int entrance_c) {\n    // Temporarily mark as occupied\n    int original = grid[r][c];\n    grid[r][c] = 2; // Mark as occupied\n    \n    // Count reachable empty squares\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    int reachable_count = 0;\n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            reachable_count++;\n        }\n    }\n    \n    // Restore\n    grid[r][c] = original;\n    \n    // Calculate total empty squares\n    int total_empty = 0;\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (grid[i][j] == 0) total_empty++;\n        }\n    }\n    \n    // If we placed at (r, c), one less empty square.\n    // So we expect reachable_count == total_empty - 1\n    // Note: (r, c) is now occupied, so it's not counted in total_empty in the check above?\n    // Wait, total_empty is calculated with (r, c) as empty (restored).\n    // So if (r, c) is occupied, total empty is total_empty - 1.\n    // We need all other empty squares to be reachable.\n    // So reachable_count should be total_empty - 1.\n    \n    return reachable_count == total_empty - 1;\n}\n\n// Sort empty squares by accessibility for placement\n// We want to fill Leaves (Far) first, then Closer.\n// So sort by Distance Descending.\n// Safe squares are prioritized.\nvector<pair<int, int>> get_sorted_candidates(int entrance_r, int entrance_c) {\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    vector<pair<int, int>> candidates;\n    \n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            candidates.push_back(pos);\n        }\n    }\n    \n    // Sort by Distance Descending (Far first)\n    // Tie-breaker: Coordinate order for stability\n    sort(candidates.begin(), candidates.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {\n        if (dist[a] != dist[b]) return dist[a] > dist[b];\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    \n    // Filter Safe squares\n    vector<pair<int, int>> safe_candidates;\n    for (auto p : candidates) {\n        if (is_safe(p.first, p.second, entrance_r, entrance_c)) {\n            safe_candidates.push_back(p);\n        }\n    }\n    \n    // If no safe candidates (should not happen unless 1 square left), return all reachable\n    if (safe_candidates.empty() && !candidates.empty()) {\n        return candidates;\n    }\n    \n    return safe_candidates;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int entrance_r = 0;\n    int entrance_c = (D - 1) / 2;\n    \n    if (!(cin >> D >> N)) return 0;\n    \n    obstacles.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    // Initialize grid\n    grid.assign(D, vector<int>(D, 0));\n    container_id.assign(D, vector<int>(D, -1));\n    \n    for (auto obs : obstacles) {\n        grid[obs.first][obs.second] = 1;\n    }\n    // Entrance is (0, (D-1)/2)\n    // It is not an obstacle.\n    // We treat entrance as empty for placement logic, but we cannot place container there.\n    // Actually problem says \"It is neither the entrance nor an obstacle square\".\n    // So entrance is effectively blocked for placement.\n    grid[entrance_r][entrance_c] = 1; // Mark as obstacle for placement logic\n    \n    set<int> used_ids;\n    int total_containers = D * D - 1 - N;\n    \n    // Placement Phase\n    for (int d = 0; d < total_containers; ++d) {\n        int t;\n        cin >> t;\n        used_ids.insert(t);\n        \n        // Calculate rank r among remaining IDs\n        // r = number of unused IDs smaller than t\n        // Since used_ids contains all IDs placed so far,\n        // unused IDs are those not in used_ids.\n        // But we know t is the current ID.\n        // We can count how many IDs < t are already used.\n        int smaller_used = 0;\n        for (int u : used_ids) {\n            if (u < t) smaller_used++;\n        }\n        // Total IDs < t is t.\n        // So unused IDs < t is t - smaller_used.\n        int r = t - smaller_used;\n        \n        // Get sorted candidates\n        vector<pair<int, int>> candidates = get_sorted_candidates(entrance_r, entrance_c);\n        \n        int U = candidates.size();\n        // We want to place Large IDs at Far (Index 0), Small IDs at Close (Index U-1).\n        // Index k = U - 1 - r.\n        // Clamp k to [0, U-1]\n        int k = U - 1 - r;\n        if (k < 0) k = 0;\n        if (k >= U) k = U - 1;\n        \n        pair<int, int> chosen = candidates[k];\n        grid[chosen.first][chosen.second] = 2;\n        container_id[chosen.first][chosen.second] = t;\n        used_coords.push_back(chosen);\n        \n        cout << chosen.first << \" \" << chosen.second << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval Phase\n    // Greedy: Pick reachable container with min ID\n    vector<pair<int, int>> retrieval_order;\n    // Reset entrance to empty for retrieval logic?\n    // Entrance is (0, 4). It is marked as obstacle (1).\n    // For retrieval, we need to find reachable containers.\n    // Path must be through empty squares.\n    // Entrance is empty (conceptually).\n    // Let's mark entrance as 0 for BFS.\n    grid[entrance_r][entrance_c] = 0;\n    \n    int remaining = total_containers;\n    while (remaining > 0) {\n        // Find all reachable containers\n        // BFS from entrance\n        map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n        \n        int min_id = 1e9;\n        pair<int, int> best_pos = {-1, -1};\n        \n        for (auto const& [pos, d] : dist) {\n            if (grid[pos.first][pos.second] == 2) {\n                int id = container_id[pos.first][pos.second];\n                if (id < min_id) {\n                    min_id = id;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if (best_pos.first != -1) {\n            retrieval_order.push_back(best_pos);\n            grid[best_pos.first][best_pos.second] = 0; // Becomes empty\n            container_id[best_pos.first][best_pos.second] = -1;\n            remaining--;\n        } else {\n            // Should not happen\n            break;\n        }\n    }\n    \n    for (auto p : retrieval_order) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 101;\n\nint n, m;\nint grid[MAXN][MAXN];\nint adj_count[MAXM][MAXM];\nbool required_adj[MAXM][MAXM];\nint num_tiles[MAXM];\nvector<pair<int, int>> tiles[MAXM];\nint pos[MAXN][MAXN];\nvector<pair<int, int>> all_nonzero;\n\nint visited[MAXN][MAXN];\nint visited_cookie = 0;\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < n && c >= 0 && c < n;\n}\n\n// Check connectivity of a specific color\nbool check_connectivity(int color) {\n    if (num_tiles[color] <= 1) return true;\n    \n    visited_cookie++;\n    int start_r = tiles[color][0].first;\n    int start_c = tiles[color][0].second;\n    \n    int count = 0;\n    vector<pair<int, int>> q;\n    q.reserve(num_tiles[color]);\n    q.push_back({start_r, start_c});\n    visited[start_r][start_c] = visited_cookie;\n    count++;\n    \n    int head = 0;\n    while(head < q.size()){\n        auto [r, c] = q[head++];\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_cookie){\n                visited[nr][nc] = visited_cookie;\n                q.push_back({nr, nc});\n                count++;\n            }\n        }\n    }\n    return count == num_tiles[color];\n}\n\n// Try to remove tile at (r, c)\nbool try_remove(int r, int c) {\n    int color = grid[r][c];\n    if(color == 0) return false;\n    \n    // Check adjacency impact\n    bool adj_ok = true;\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != color){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                // If this is the last edge between c1 and c2, and they are required to be adjacent\n                if(adj_count[c1][c2] == 1 && required_adj[c1][c2]){\n                    adj_ok = false;\n                    break;\n                }\n            }\n        }\n    }\n    if(!adj_ok) return false;\n    \n    // Temporarily remove\n    int idx = pos[r][c];\n    tiles[color].erase(tiles[color].begin() + idx);\n    num_tiles[color]--;\n    grid[r][c] = 0;\n    \n    // Update adj_count\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != 0){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                adj_count[c1][c2]--;\n            }\n        }\n    }\n    \n    bool conn_ok = check_connectivity(color);\n    \n    if(!conn_ok){\n        // Revert\n        grid[r][c] = color;\n        num_tiles[color]++;\n        tiles[color].push_back({r, c});\n        pos[r][c] = tiles[color].size() - 1;\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc)){\n                int ncolor = grid[nr][nc];\n                if(ncolor != 0){\n                    int c1 = min(color, ncolor);\n                    int c2 = max(color, ncolor);\n                    adj_count[c1][c2]++;\n                }\n            }\n        }\n        return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> n >> m)) return 0;\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cin >> grid[i][j];\n            if(grid[i][j] != 0){\n                tiles[grid[i][j]].push_back({i, j});\n                pos[i][j] = tiles[grid[i][j]].size() - 1;\n                num_tiles[grid[i][j]]++;\n                all_nonzero.push_back({i, j});\n            }\n        }\n    }\n    \n    memset(required_adj, 0, sizeof(required_adj));\n    memset(adj_count, 0, sizeof(adj_count));\n    \n    // Compute required adjacencies and counts\n    // Count each edge once\n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            int c = grid[i][j];\n            for(int k=0; k<4; k++){\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if(is_valid(ni, nj)){\n                    int nc = grid[ni][nj];\n                    if(c != nc){\n                        int c1 = min(c, nc);\n                        int c2 = max(c, nc);\n                        // Count only once by checking coordinate order\n                        if((i < ni) || (i == ni && j < nj)){\n                             required_adj[c1][c2] = true;\n                             adj_count[c1][c2]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    mt19937 rng(1337);\n    uniform_int_distribution<int> dist_idx(0, (int)all_nonzero.size() - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int no_change = 0;\n    // Run greedy removal\n    while(true){\n        auto now = chrono::steady_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.9) break;\n        \n        if(all_nonzero.empty()) break;\n        \n        int idx = dist_idx((int)all_nonzero.size());\n        auto [r, c] = all_nonzero[idx];\n        \n        if(try_remove(r, c)){\n            // Remove from all_nonzero\n            int last_idx = all_nonzero.size() - 1;\n            all_nonzero[idx] = all_nonzero[last_idx];\n            all_nonzero.pop_back();\n            no_change = 0;\n        } else {\n            no_change++;\n            if(no_change > 5000) break;\n        }\n    }\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cout << grid[i][j] << (j == n-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for problem constraints\nint N, D, Q;\nvector<double> estimated_weights;\nvector<int> assignment;\nvector<vector<int>> sets;\nvector<double> set_sums;\n\n// Random number generator\nmt19937 rng(123456);\n\n// Function to output a query\nvoid output_query(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n}\n\n// Function to read query response\nstring read_response() {\n    string res;\n    cin >> res;\n    return res;\n}\n\n// Simulated Annealing for partitioning\nvoid simulate_annealing() {\n    // Initialize assignment using LPT (Largest Processing Time) heuristic\n    // Sort items by estimated weight descending\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({estimated_weights[i], i});\n    }\n    sort(items.begin(), items.end(), [](const pair<double, int>& a, const pair<double, int>& b) {\n        return a.first > b.first;\n    });\n\n    // Initialize sets and sums\n    sets.assign(D, vector<int>());\n    set_sums.assign(D, 0.0);\n    assignment.assign(N, 0);\n\n    for (int i = 0; i < N; ++i) {\n        int item_idx = items[i].second;\n        double weight = items[i].first;\n        \n        // Find set with minimum current sum\n        int min_set = 0;\n        for (int j = 1; j < D; ++j) {\n            if (set_sums[j] < set_sums[min_set]) {\n                min_set = j;\n            }\n        }\n        \n        sets[min_set].push_back(item_idx);\n        set_sums[min_set] += weight;\n        assignment[item_idx] = min_set;\n    }\n\n    // Calculate initial variance\n    double total_sum = 0.0;\n    for (double s : set_sums) total_sum += s;\n    double mean = total_sum / D;\n    double current_variance = 0.0;\n    for (double s : set_sums) {\n        current_variance += (s - mean) * (s - mean);\n    }\n    current_variance /= D;\n\n    double best_variance = current_variance;\n    vector<int> best_assignment = assignment;\n\n    // SA parameters\n    double temperature = 1.0;\n    double cooling_rate = 0.995;\n    int max_iterations = 20000;\n    int iterations = 0;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    auto end_time = chrono::high_resolution_clock::now() + chrono::seconds(1.5); // Leave margin for output\n\n    while (iterations < max_iterations && chrono::high_resolution_clock::now() < end_time) {\n        iterations++;\n        \n        // Select random move: swap or move\n        int move_type = uniform_int_distribution<int>(0, 1)(rng);\n        \n        if (move_type == 0) {\n            // Swap items between two different sets\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2 || sets[s1].empty() || sets[s2].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, sets[s1].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, sets[s2].size() - 1)(rng);\n            \n            int u = sets[s1][idx1];\n            int v = sets[s2][idx2];\n            \n            double w_u = estimated_weights[u];\n            double w_v = estimated_weights[v];\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u + w_v;\n            double new_sum_s2 = set_sums[s2] - w_v + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                assignment[v] = s1;\n                current_variance = new_variance;\n                \n                if (current_variance < best_variance) {\n                    best_variance = current_variance;\n                    best_assignment = assignment;\n                }\n            }\n        } else {\n            // Move item from one set to another\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (sets[s1].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, sets[s1].size() - 1)(rng);\n            int u = sets[s1][idx1];\n            double w_u = estimated_weights[u];\n            \n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u;\n            double new_sum_s2 = set_sums[s2] + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                current_variance = new_variance;\n                \n                if (current_variance < best_variance) {\n                    best_variance = current_variance;\n                    best_assignment = assignment;\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < 1e-9) break;\n    }\n\n    assignment = best_assignment;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    estimated_weights.assign(N, 1.0);\n\n    // Weight Estimation Phase\n    // We use Q queries to estimate weights\n    // We construct L and R such that sum(L) approx sum(R)\n    // This maximizes information gain\n    \n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    for (int q = 0; q < Q; ++q) {\n        // Shuffle items to ensure randomness in selection\n        shuffle(p.begin(), p.end(), rng);\n        \n        vector<int> L, R;\n        double sum_L = 0.0;\n        double sum_R = 0.0;\n        \n        // Greedy assignment to balance sums\n        // Ensure L and R are not empty\n        if (N >= 2) {\n            L.push_back(p[0]);\n            sum_L += estimated_weights[p[0]];\n            R.push_back(p[1]);\n            sum_R += estimated_weights[p[1]];\n        }\n        \n        for (int i = (N >= 2 ? 2 : 0); i < N; ++i) {\n            int item = p[i];\n            if (sum_L <= sum_R) {\n                L.push_back(item);\n                sum_L += estimated_weights[item];\n            } else {\n                R.push_back(item);\n                sum_R += estimated_weights[item];\n            }\n        }\n        \n        // Output query\n        output_query(L, R);\n        \n        // Read response\n        string res = read_response();\n        \n        // Update weights\n        double diff = sum_L - sum_R;\n        double eta = 0.5 * (1.0 - (double)q / Q); // Decaying learning rate\n        \n        if (res == \"<\") {\n            // L < R, but we estimated sum_L vs sum_R\n            // If sum_L >= sum_R, we are wrong\n            if (diff >= -1e-9) { // Allow small tolerance\n                // Decrease L weights, increase R weights\n                double adjustment = eta * max(0.0, diff + 1e-9);\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        } else if (res == \">\") {\n            // L > R\n            if (diff <= 1e-9) {\n                // Increase L weights, decrease R weights\n                double adjustment = eta * max(0.0, -diff + 1e-9);\n                for (int item : L) estimated_weights[item] += adjustment / L.size();\n                for (int item : R) estimated_weights[item] -= adjustment / R.size();\n            }\n        } else if (res == \"=\") {\n            // L = R\n            if (abs(diff) > 1e-9) {\n                // Adjust to reduce difference\n                double adjustment = eta * diff;\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        }\n        \n        // Ensure weights stay positive\n        for (double &w : estimated_weights) {\n            if (w < 0.1) w = 0.1;\n        }\n    }\n\n    // Partitioning Phase\n    simulate_annealing();\n\n    // Output final assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n\nusing namespace std;\n\n// Global variables to store state\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // pos[v] = {stack_idx, height} (0-indexed stack, 0-indexed height)\nvector<pair<int, int>> operations;\n\n// Function to calculate inversions between a block S and a stack Dest\n// S is a vector of box values in the block (from bottom to top)\n// Dest is the index of the destination stack\n// Returns the number of pairs (u, d) such that u in S, d in stacks[Dest], u > d\nint count_inversions(const vector<int>& S, int dest_idx) {\n    int count = 0;\n    const auto& dest_stack = stacks[dest_idx];\n    for (int u : S) {\n        for (int d : dest_stack) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to calculate inversions between a block S and boxes below v in Source stack\n// v is the box we want to expose (it is below S in the source stack)\n// S is the block above v\nint count_inversions_below(const vector<int>& S, int source_idx, int v) {\n    int count = 0;\n    const auto& source_stack = stacks[source_idx];\n    // Find position of v\n    int v_pos = -1;\n    for (int i = 0; i < source_stack.size(); ++i) {\n        if (source_stack[i] == v) {\n            v_pos = i;\n            break;\n        }\n    }\n    // Iterate boxes below v\n    for (int i = 0; i < v_pos; ++i) {\n        int d = source_stack[i];\n        for (int u : S) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to execute a move\n// Move block starting at box v (and all above it) to dest_stack_idx\n// Returns the number of boxes moved\nint move_block(int v, int dest_stack_idx) {\n    auto [src_idx, h] = pos[v];\n    if (src_idx == dest_stack_idx) return 0;\n    \n    const auto& src_stack = stacks[src_idx];\n    // Identify the block\n    // The block starts at h and goes to top\n    vector<int> block;\n    for (int i = h; i < src_stack.size(); ++i) {\n        block.push_back(src_stack[i]);\n    }\n    \n    // Move to dest\n    for (int u : block) {\n        stacks[dest_stack_idx].push_back(u);\n        pos[u] = {dest_stack_idx, (int)stacks[dest_stack_idx].size() - 1};\n    }\n    \n    // Remove from src\n    for (int i = 0; i < block.size(); ++i) {\n        stacks[src_idx].pop_back();\n    }\n    \n    operations.push_back({v, dest_stack_idx + 1}); // 1-indexed output\n    return block.size();\n}\n\n// Function to remove box v (Op 2)\nvoid remove_box(int v) {\n    auto [src_idx, h] = pos[v];\n    // It must be at the top\n    if (h != (int)stacks[src_idx].size() - 1) {\n        // Should not happen if logic is correct\n        return;\n    }\n    stacks[src_idx].pop_back();\n    operations.push_back({v, 0});\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    pos.resize(N + 1);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Main loop\n    for (int v = 1; v <= N; ++v) {\n        // Check if v is at the top\n        auto [src_idx, h] = pos[v];\n        while (h != (int)stacks[src_idx].size() - 1) {\n            // v is covered. Identify boxes above v.\n            const auto& src_stack = stacks[src_idx];\n            vector<int> boxes_above;\n            for (int i = h + 1; i < src_stack.size(); ++i) {\n                boxes_above.push_back(src_stack[i]);\n            }\n            \n            int k = boxes_above.size();\n            if (k == 0) break; // Should not happen\n\n            // Generate candidates\n            // We try moving suffixes of boxes_above\n            // Suffixes: top 1, top 2, ..., top k (whole block)\n            // To save time, if k is large, we limit suffixes.\n            \n            vector<int> suffix_lengths;\n            if (k <= 5) {\n                for (int len = 1; len <= k; ++len) suffix_lengths.push_back(len);\n            } else {\n                suffix_lengths.push_back(1);\n                suffix_lengths.push_back(2);\n                suffix_lengths.push_back(k);\n            }\n\n            int best_score = 1e9;\n            int best_move_v = -1;\n            int best_dest = -1;\n\n            // Random seed for tie-breaking\n            static mt19937 rng(1337);\n            vector<pair<int, int>> candidates;\n\n            for (int len : suffix_lengths) {\n                // The block to move is the top 'len' boxes of boxes_above\n                // boxes_above is from bottom to top.\n                // So top 'len' boxes are boxes_above[k-len ... k-1]\n                vector<int> S;\n                for (int i = k - len; i < k; ++i) {\n                    S.push_back(boxes_above[i]);\n                }\n                int v_to_move = S.back(); // The bottom-most box of the block being moved\n\n                for (int dest = 0; dest < M; ++dest) {\n                    if (dest == src_idx) continue;\n\n                    // Cost = len + 1\n                    int cost = len + 1;\n\n                    // Delta Potential = New Inversions - Removed Inversions\n                    // New Inversions: pairs (u, d) with u in S, d in stacks[dest], u > d\n                    int new_inv = count_inversions(S, dest);\n                    \n                    // Removed Inversions: pairs (u, d) with u in S, d in stacks[src_idx] below v, u > d\n                    int removed_inv = count_inversions_below(S, src_idx, v);\n\n                    int score = cost + (new_inv - removed_inv);\n\n                    if (score < best_score) {\n                        best_score = score;\n                        candidates.clear();\n                        candidates.push_back({v_to_move, dest});\n                    } else if (score == best_score) {\n                        candidates.push_back({v_to_move, dest});\n                    }\n                }\n            }\n\n            if (candidates.empty()) {\n                // Fallback: move top 1 box to random stack\n                int top_box = boxes_above.back();\n                int dest = src_idx;\n                while (dest == src_idx) dest = rng() % M;\n                move_block(top_box, dest);\n            } else {\n                int idx = rng() % candidates.size();\n                move_block(candidates[idx].first, candidates[idx].second);\n            }\n            \n            // Update pos[v] and h after move\n            // pos[v] is updated inside move_block\n            // But we need to re-check if v is at top\n            auto [new_src, new_h] = pos[v];\n            src_idx = new_src;\n            h = new_h;\n        }\n\n        // Now v should be at top\n        remove_box(v);\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring route;\nvector<pair<int, int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\nstring dir_chars = \"RDLU\";\n\nbool can_move(int i, int j, int di, int dj) {\n    int ni = i + di, nj = j + dj;\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    if (di == 1) return h[i][j] == '0';\n    if (di == -1) return h[ni][j] == '0';\n    if (dj == 1) return v[i][j] == '0';\n    if (dj == -1) return v[i][nj] == '0';\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N);\n    for (int i = 0; i < N; i++) cin >> h[i];\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    d.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    visited.assign(N, vector<bool>(N, false));\n    \n    // Sort neighbors by dirtiness (descending) for prioritization\n    auto get_neighbors = [&](int i, int j) {\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !visited[ni][nj]) {\n                if (can_move(i, j, di, dj)) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        return neighbors;\n    };\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        auto neighbors = get_neighbors(i, j);\n        for (auto& [dirt, dir] : neighbors) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (!visited[ni][nj] && can_move(i, j, di, dj)) {\n                route += dir_chars[dir];\n                dfs(ni, nj);\n                route += dir_chars[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Optimize: Add loops to high-dirtiness squares\n    // Find squares with high dirtiness and add revisit loops\n    vector<tuple<int, int, int>> high_dirtiness;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            high_dirtiness.push_back({d[i][j], i, j});\n        }\n    }\n    sort(high_dirtiness.rbegin(), high_dirtiness.end());\n    \n    // Try to add revisit loops to top high-dirtiness squares\n    int route_len = route.size();\n    int max_len = 100000;\n    \n    for (auto& [dirt, i, j] : high_dirtiness) {\n        if (route_len >= max_len - 20) break;\n        \n        // Try to add a small loop through this square\n        // Check if we can add a revisit from nearby visited squares\n        int best_dir = -1;\n        int best_score = 0;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                if (can_move(i, j, di, dj) && can_move(ni, nj, -di, -dj)) {\n                    best_dir = dir;\n                    best_score = dirt;\n                    break;\n                }\n            }\n        }\n        \n        if (best_dir >= 0 && route_len + 2 <= max_len) {\n            // Insert a revisit loop at a reasonable position\n            // For simplicity, we'll add it at the end before returning to (0,0)\n            route += dir_chars[best_dir];\n            route += dir_chars[(best_dir + 2) % 4];\n            route_len += 2;\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, M;\nint start_i, start_j;\nvector<string> grid(15);\nvector<string> targets;\nvector<pair<int, int>> char_pos[26];\nvector<pair<int, int>> path;\nint total_cost;\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nint move_cost(int i1, int j1, int i2, int j2) {\n    return manhattan(i1, j1, i2, j2) + 1;\n}\n\n// Find nearest position for character c from current position\npair<int, int> find_nearest(char c, int curr_i, int curr_j) {\n    int best_dist = 1e9;\n    pair<int, int> best_pos = {-1, -1};\n    for (auto& p : char_pos[c - 'A']) {\n        int d = manhattan(curr_i, curr_j, p.first, p.second);\n        if (d < best_dist) {\n            best_dist = d;\n            best_pos = p;\n        }\n    }\n    return best_pos;\n}\n\n// Calculate cost for a given order of targets\nint calculate_cost(const vector<int>& order, int& cost) {\n    int ci = start_i, cj = start_j;\n    cost = 0;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            cost += move_cost(ci, cj, pos.first, pos.second);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return cost;\n}\n\n// Generate path for given order\nvector<pair<int, int>> generate_path(const vector<int>& order) {\n    vector<pair<int, int>> result;\n    int ci = start_i, cj = start_j;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            result.push_back(pos);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return result;\n}\n\n// Check overlap between two strings (suffix of s1 with prefix of s2)\nint check_overlap(const string& s1, const string& s2) {\n    int max_ov = min((int)s1.size(), (int)s2.size());\n    for (int ov = max_ov; ov >= 1; ov--) {\n        if (s1.substr(s1.size() - ov) == s2.substr(0, ov)) {\n            return ov;\n        }\n    }\n    return 0;\n}\n\n// Simulated annealing optimization\nvoid optimize() {\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    \n    // Initial greedy improvement\n    for (int i = 0; i < 500; i++) {\n        int best_i = -1, best_j = -1;\n        int best_cost = 1e9;\n        int current_cost;\n        calculate_cost(order, current_cost);\n        \n        for (int j = 0; j < M; j++) {\n            for (int k = j + 1; k < M; k++) {\n                swap(order[j], order[k]);\n                int new_cost;\n                calculate_cost(order, new_cost);\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_i = j;\n                    best_j = k;\n                }\n                swap(order[j], order[k]);\n            }\n        }\n        \n        if (best_i != -1) {\n            swap(order[best_i], order[best_j]);\n        } else {\n            break;\n        }\n    }\n    \n    // Simulated annealing\n    double temp = 500.0;\n    double decay = 0.9998;\n    int iterations = 80000;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int current_cost;\n        calculate_cost(order, current_cost);\n        \n        // Random swap\n        int i = rand() % M;\n        int j = rand() % M;\n        swap(order[i], order[j]);\n        \n        int new_cost;\n        calculate_cost(order, new_cost);\n        \n        int delta = new_cost - current_cost;\n        \n        // Accept if better, or with probability if worse\n        if (delta <= 0 || (double)rand() / RAND_MAX < exp(-delta / temp)) {\n            // Keep swap\n        } else {\n            swap(order[i], order[j]); // Revert\n        }\n        \n        temp *= decay;\n    }\n    \n    // Final local search\n    for (int iter = 0; iter < 2000; iter++) {\n        int best_i = -1, best_j = -1;\n        int best_cost = 1e9;\n        int current_cost;\n        calculate_cost(order, current_cost);\n        \n        for (int j = 0; j < M; j++) {\n            for (int k = j + 1; k < M; k++) {\n                swap(order[j], order[k]);\n                int new_cost;\n                calculate_cost(order, new_cost);\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_i = j;\n                    best_j = k;\n                }\n                swap(order[j], order[k]);\n            }\n        }\n        \n        if (best_i != -1) {\n            swap(order[best_i], order[best_j]);\n        } else {\n            break;\n        }\n    }\n    \n    // Generate final path\n    path = generate_path(order);\n    calculate_cost(order, total_cost);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> M >> start_i >> start_j;\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_pos[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    optimize();\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables\nint N, M;\ndouble epsilon;\nstruct Shape {\n    int id;\n    int area;\n    vector<pair<int, int>> cells;\n};\nvector<Shape> shapes;\nmap<pair<int, int>, int> drilled_values;\nbool solved = false;\n\n// Random number generator\nmt19937 rng(1337);\n\n// Function to query a single cell\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    int v;\n    cin >> v;\n    drilled_values[{r, c}] = v;\n    return v;\n}\n\n// Function to query a set of cells\nint divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Submit answer\nvoid submit(const vector<pair<int, int>>& cells) {\n    cout << \"a \" << cells.size();\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) {\n        solved = true;\n        exit(0);\n    }\n}\n\n// Check if a shape at position (r, c) covers (i, j)\nbool covers(const Shape& s, int r, int c, int i, int j) {\n    for (auto p : s.cells) {\n        if (r + p.first == i && c + p.second == j) return true;\n    }\n    return false;\n}\n\n// Calculate predicted v(i, j) for a configuration\nint predict_v(const vector<pair<int, int>>& config, int i, int j) {\n    int count = 0;\n    for (int k = 0; k < M; ++k) {\n        int r = config[k].first;\n        int c = config[k].second;\n        if (covers(shapes[k], r, c, i, j)) count++;\n    }\n    return count;\n}\n\n// Check if a configuration is consistent with drilled values\nbool is_consistent(const vector<pair<int, int>>& config) {\n    for (auto const& [pos, val] : drilled_values) {\n        int i = pos.first;\n        int j = pos.second;\n        int pred = predict_v(config, i, j);\n        if (pred != val) return false;\n    }\n    return true;\n}\n\n// Backtracking solver\n// candidates[k] is a list of possible positions for shape k\n// config[k] stores the chosen position for shape k\nbool solve(int k, vector<pair<int, int>>& config, vector<vector<pair<int, int>>>& candidates) {\n    if (k == M) {\n        return is_consistent(config);\n    }\n    \n    // Try all candidates for shape k\n    for (auto pos : candidates[k]) {\n        config[k] = pos;\n        // Pruning: Check consistency with drilled cells so far\n        bool possible = true;\n        for (auto const& [p, val] : drilled_values) {\n            int i = p.first;\n            int j = p.second;\n            // Calculate partial sum for this shape\n            int current_contribution = covers(shapes[k], pos.first, pos.second, i, j) ? 1 : 0;\n            // We need to check if it's possible to reach 'val' with remaining shapes\n            // This is a bit expensive to check fully, so let's just check exact match for drilled cells\n            // Actually, we can check if current config so far is consistent with drilled cells\n            // But we don't know other shapes yet.\n            // So we just check if the current shape doesn't violate any 0 constraints\n            if (val == 0 && current_contribution == 1) {\n                possible = false;\n                break;\n            }\n        }\n        if (!possible) continue;\n\n        if (solve(k + 1, config, candidates)) return true;\n    }\n    return false;\n}\n\n// Collect all possible positions for each shape\nvoid generate_candidates(vector<vector<pair<int, int>>>& candidates) {\n    candidates.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& s = shapes[k];\n        int max_r = N - 1;\n        int max_c = N - 1;\n        // Find bounding box of shape to determine max valid top-left\n        int s_max_r = 0, s_max_c = 0;\n        for (auto p : s.cells) {\n            s_max_r = max(s_max_r, p.first);\n            s_max_c = max(s_max_c, p.second);\n        }\n        for (int r = 0; r <= N - 1 - s_max_r; ++r) {\n            for (int c = 0; c <= N - 1 - s_max_c; ++c) {\n                // Check consistency with drilled cells\n                bool ok = true;\n                for (auto const& [pos, val] : drilled_values) {\n                    if (val == 0 && covers(s, r, c, pos.first, pos.second)) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) {\n                    candidates[k].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\n// Recursive region processing\nvoid process_region(int r1, int c1, int r2, int c2) {\n    int h = r2 - r1 + 1;\n    int w = c2 - c1 + 1;\n    int area = h * w;\n    \n    if (area <= 16) {\n        for (int r = r1; r <= r2; ++r) {\n            for (int c = c1; c <= c2; ++c) {\n                if (drilled_values.find({r, c}) == drilled_values.end()) {\n                    drill(r, c);\n                }\n            }\n        }\n        return;\n    }\n\n    // Query region\n    vector<pair<int, int>> cells;\n    for (int r = r1; r <= r2; ++r) {\n        for (int c = c1; c <= c2; ++c) {\n            cells.push_back({r, c});\n        }\n    }\n    \n    int k = cells.size();\n    int total_obs = 0;\n    int Q = 10; // Number of queries\n    for (int q = 0; q < Q; ++q) {\n        total_obs += divine(cells);\n    }\n    double avg_obs = (double)total_obs / Q;\n    \n    // Estimate true sum\n    // mu = k*eps + v*(1-2*eps)\n    // v_est = (avg_obs - k*eps) / (1-2*eps)\n    double v_est = (avg_obs - k * epsilon) / (1.0 - 2.0 * epsilon);\n    \n    // Threshold for \"empty\"\n    // If v_est is very small, assume empty.\n    // To be safe, we require v_est < 0.2 (since min non-zero is 1)\n    // But noise can make it negative.\n    // Let's say if v_est < 0.5, suspect empty.\n    if (v_est < 0.5) {\n        // Suspected empty. Verify with 1 drill.\n        int vr = r1 + (rng() % h);\n        int vc = c1 + (rng() % w);\n        int val = drill(vr, vc);\n        if (val > 0) {\n            // Not empty, recurse\n            int mr = (r1 + r2) / 2;\n            int mc = (c1 + c2) / 2;\n            process_region(r1, c1, mr, mc);\n            process_region(r1, c1, mr, c2); // Overlap? No, split properly\n            process_region(r1, c1, mr, mc); // Wait, standard quad split\n            // Correct split:\n            // Top-Left, Top-Right, Bottom-Left, Bottom-Right\n            // To avoid overlap, split at mid\n            int mid_r = (r1 + r2) / 2;\n            int mid_c = (c1 + c2) / 2;\n            process_region(r1, c1, mid_r, mid_c);\n            process_region(r1, mid_c + 1, mid_r, c2);\n            process_region(mid_r + 1, c1, r2, mid_c);\n            process_region(mid_r + 1, mid_c + 1, r2, c2);\n        } else {\n            // Assume empty, do nothing\n        }\n    } else {\n        // Definitely has oil, recurse\n        int mid_r = (r1 + r2) / 2;\n        int mid_c = (c1 + c2) / 2;\n        process_region(r1, c1, mid_r, mid_c);\n        process_region(r1, mid_c + 1, mid_r, c2);\n        process_region(mid_r + 1, c1, r2, mid_c);\n        process_region(mid_r + 1, mid_c + 1, r2, c2);\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> epsilon;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        shapes[k].id = k;\n        int d;\n        cin >> d;\n        shapes[k].area = d;\n        shapes[k].cells.resize(d);\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n        }\n    }\n\n    // Heuristic search for regions with oil\n    process_region(0, 0, N - 1, N - 1);\n\n    // Solve for configuration\n    vector<vector<pair<int, int>>> candidates;\n    generate_candidates(candidates);\n    \n    // Sort shapes by number of candidates (MRV)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return candidates[a].size() < candidates[b].size();\n    });\n\n    // We need to map back to original indices\n    // Let's just use the sorted order in recursion\n    // But the config vector needs to be indexed by original shape index\n    // Let's modify solve to take shape index from order\n    \n    vector<pair<int, int>> config(M);\n    // We need to re-implement solve to use the order\n    // Or just permute candidates\n    \n    // Let's create a permuted candidates list\n    vector<vector<pair<int, int>>> perm_candidates(M);\n    for(int i=0; i<M; ++i) perm_candidates[i] = candidates[order[i]];\n    \n    // We need a helper solve that takes the permuted candidates\n    // But predict_v uses original shape indices.\n    // So we need to keep track of which original shape we are placing.\n    \n    // Let's rewrite solve to accept a mapping\n    // Actually, simpler: just use the original candidates but pick the shape with fewest candidates first.\n    // We can do this by reordering the recursion.\n    \n    // Let's implement a custom solver\n    vector<int> shape_order = order;\n    vector<pair<int, int>> final_config(M);\n    \n    // We need to pass the current depth and the shape index we are deciding\n    // But since we reordered, we need to map back.\n    // Let's just use a lambda or a separate function with state\n    \n    // To keep it simple, let's just use the original candidates but sort them by size\n    // and pass the permutation to the solver.\n    \n    // Re-implementing solve with permutation\n    // We will fill final_config based on shape_order[k]\n    \n    auto solve_perm = [&](auto&& self, int k) -> bool {\n        if (k == M) {\n            return is_consistent(final_config);\n        }\n        int shape_idx = shape_order[k];\n        for (auto pos : candidates[shape_idx]) {\n            final_config[shape_idx] = pos;\n            // Pruning\n            bool possible = true;\n            for (auto const& [p, val] : drilled_values) {\n                if (val == 0 && covers(shapes[shape_idx], pos.first, pos.second, p.first, p.second)) {\n                    possible = false;\n                    break;\n                }\n            }\n            if (!possible) continue;\n            \n            if (self(self, k + 1)) return true;\n        }\n        return false;\n    };\n\n    if (solve_perm(solve_perm, 0)) {\n        // Found a configuration\n        // Collect all cells with v > 0\n        vector<pair<int, int>> result;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (predict_v(final_config, i, j) > 0) {\n                    result.push_back({i, j});\n                }\n            }\n        }\n        submit(result);\n    } else {\n        // Failed to find configuration.\n        // This might mean we missed some oil (false empty).\n        // We can try to drill more cells.\n        // But to keep it simple for the contest, we can just drill all remaining cells.\n        // Or submit an empty set? No, that's wrong.\n        // Let's drill all cells that are not drilled yet.\n        // This ensures we find the answer, but costs more.\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drilled_values.find({i, j}) == drilled_values.end()) {\n                    drill(i, j);\n                }\n            }\n        }\n        // Retry solving\n        generate_candidates(candidates);\n        if (solve_perm(solve_perm, 0)) {\n            vector<pair<int, int>> result;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (predict_v(final_config, i, j) > 0) {\n                        result.push_back({i, j});\n                    }\n                }\n            }\n            submit(result);\n        } else {\n            // Still failed? Fallback to all drilled cells with v>0\n            vector<pair<int, int>> result;\n            for (auto const& [pos, val] : drilled_values) {\n                if (val > 0) result.push_back(pos);\n            }\n            submit(result);\n        }\n    }\n\n    return 0;\n}","ahc031":"```cpp\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n#include <queue>\n\nusing namespace std;\n\n// Rectangle structure\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\n// Problem parameters\nint W, D, N;\nvector<vector<int>> a;  // desired areas\nvector<vector<Rect>> rects;  // assigned rectangles\n\n// Check if rectangles overlap\nbool checkOverlap(const vector<Rect>& day_rects) {\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!(day_rects[i].i1 <= day_rects[j].i0 ||\n                  day_rects[i].i0 >= day_rects[j].i1 ||\n                  day_rects[i].j1 <= day_rects[j].j0 ||\n                  day_rects[i].j0 >= day_rects[j].j1)) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\n// Calculate area cost for a day\nlong long calculateAreaCost(int d) {\n    long long cost = 0;\n    for (int k = 0; k < N; k++) {\n        int actual = rects[d][k].area();\n        if (actual < a[d][k]) {\n            cost += 100LL * (a[d][k] - actual);\n        }\n    }\n    return cost;\n}\n\n// Calculate partition segments for a day\nvector<vector<int>> getHorizontalSegments(int d) {\n    vector<vector<int>> H(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) H[i0][j] = 1;\n            if (i1 > 0 && i1 < W) H[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) H[i][j0] = 1;\n            if (j1 > 0 && j1 < W) H[i][j1] = 1;\n        }\n    }\n    return H;\n}\n\nvector<vector<int>> getVerticalSegments(int d) {\n    vector<vector<int>> V(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) V[i0][j] = 1;\n            if (i1 > 0 && i1 < W) V[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) V[i][j0] = 1;\n            if (j1 > 0 && j1 < W) V[i][j1] = 1;\n        }\n    }\n    return V;\n}\n\nlong long calculatePartitionCost(int d) {\n    if (d == 0) return 0;\n    long long cost = 0;\n    auto H_prev = getHorizontalSegments(d - 1);\n    auto H_curr = getHorizontalSegments(d);\n    auto V_prev = getVerticalSegments(d - 1);\n    auto V_curr = getVerticalSegments(d);\n    \n    for (int i = 1; i < W; i++) {\n        for (int j = 0; j < W; j++) {\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; i++) {\n        for (int j = 1; j < W; j++) {\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n        }\n    }\n    return cost;\n}\n\nlong long calculateTotalCost() {\n    long long total = 0;\n    for (int d = 0; d < D; d++) {\n        total += calculateAreaCost(d);\n        total += calculatePartitionCost(d);\n    }\n    return total;\n}\n\n// Initialize with better packing strategy\nvoid initializeSolution() {\n    rects.resize(D);\n    for (int d = 0; d < D; d++) {\n        rects[d].resize(N);\n        \n        // Sort reservations by area (descending) for better packing\n        vector<pair<int, int>> sorted_idx(N);\n        for (int k = 0; k < N; k++) sorted_idx[k] = {a[d][k], k};\n        sort(sorted_idx.rbegin(), sorted_idx.rend());\n        \n        // Use a simple row-based packing\n        int current_i = 0, current_j = 0;\n        for (int idx = 0; idx < N; idx++) {\n            int k = sorted_idx[idx].second;\n            int desired = a[d][k];\n            \n            // Calculate dimensions to minimize perimeter\n            int best_h = 1, best_w = desired;\n            int best_perimeter = 2 * (1 + desired);\n            for (int h = 1; h * h <= desired; h++) {\n                if (desired % h == 0) {\n                    int w = desired / h;\n                    int perimeter = 2 * (h + w);\n                    if (perimeter < best_perimeter) {\n                        best_perimeter = perimeter;\n                        best_h = h;\n                        best_w = w;\n                    }\n                }\n            }\n            \n            // Try to fit in current row\n            if (current_j + best_w <= W) {\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            } else {\n                // Move to next row\n                current_i += best_h;\n                current_j = 0;\n                if (current_i + best_h > W) {\n                    // Need to reorganize - use simpler approach\n                    current_i = 0;\n                    current_j = 0;\n                    for (int x = 0; x < idx; x++) {\n                        int pk = sorted_idx[x].second;\n                        int ph = rects[d][pk].i1 - rects[d][pk].i0;\n                        current_i += ph;\n                        if (current_i >= W) {\n                            current_i = 0;\n                            current_j = 0;\n                        }\n                    }\n                }\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            }\n        }\n    }\n}\n\n// Simulated Annealing optimization\nvoid optimizeSolution() {\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    uniform_int_distribution<int> int_dist(0, W - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double initial_temp = 5000.0;\n    const double cooling_rate = 0.998;\n    const double final_temp = 0.1;\n    \n    double temp = initial_temp;\n    long long current_cost = calculateTotalCost();\n    long long best_cost = current_cost;\n    \n    while (temp > final_temp) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > 2.8) break;  // Leave margin for output\n        \n        // Randomly select a day and rectangle\n        int d = dist(gen) * D;\n        int k = dist(gen) * N;\n        \n        Rect original = rects[d][k];\n        int attempts = 0;\n        bool valid = false;\n        Rect new_rect = original;\n        \n        while (attempts < 200 && !valid) {\n            int h = original.i1 - original.i0;\n            int w = original.j1 - original.j0;\n            \n            // Random perturbation with bias toward stability\n            int di = (dist(gen) * 15 - 7);\n            int dj = (dist(gen) * 15 - 7);\n            int dh = (dist(gen) * 8 - 4);\n            int dw = (dist(gen) * 8 - 4);\n            \n            int ni0 = max(0, min(W - 1, original.i0 + di));\n            int nj0 = max(0, min(W - 1, original.j0 + dj));\n            int ni1 = max(ni0 + 1, min(W, original.i1 + dh));\n            int nj1 = max(nj0 + 1, min(W, original.j1 + dw));\n            \n            new_rect = {ni0, nj0, ni1, nj1};\n            \n            if (!checkOverlap(rects[d])) {\n                valid = true;\n            } else {\n                attempts++;\n            }\n        }\n        \n        rects[d][k] = new_rect;\n        long long new_cost = calculateTotalCost();\n        double delta = new_cost - current_cost;\n        \n        if (delta < 0 || dist(gen) < exp(-delta / temp)) {\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n            }\n        } else {\n            rects[d][k] = original;\n        }\n        \n        temp *= cooling_rate;\n    }\n}\n\n// Local search for area satisfaction\nvoid improveAreaSatisfaction() {\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int current_area = rects[d][k].area();\n            if (current_area < a[d][k]) {\n                int needed = a[d][k] - current_area;\n                int h = rects[d][k].i1 - rects[d][k].i0;\n                int w = rects[d][k].j1 - rects[d][k].j0;\n                \n                // Try expanding in different directions\n                int[] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};\n                for (int dir = 0; dir < 4; dir++) {\n                    int di = dirs[dir][0];\n                    int dj = dirs[dir][1];\n                    \n                    int ni0 = rects[d][k].i0 + di * h;\n                    int nj0 = rects[d][k].j0 + dj * w;\n                    int ni1 = rects[d][k].i1 + di * h;\n                    int nj1 = rects[d][k].j1 + dj * w;\n                    \n                    if (ni0 >= 0 && ni1 <= W && nj0 >= 0 && nj1 <= W) {\n                        if (!checkOverlap(rects[d])) {\n                            rects[d][k] = {ni0, nj0, ni1, nj1};\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Try to reduce partition costs by aligning with previous day\nvoid improvePartitionStability() {\n    for (int d = 1; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            // Try to match previous day's partition pattern\n            if (d - 1 >= 0) {\n                int best_cost = 1e18;\n                Rect best_rect = rects[d][k];\n                \n                // Try small adjustments\n                for (int di = -3; di <= 3; di++) {\n                    for (int dj = -3; dj <= 3; dj++) {\n                        int ni0 = max(0, min(W - 1, rects[d][k].i0 + di));\n                        int nj0 = max(0, min(W - 1, rects[d][k].j0 + dj));\n                        int ni1 = max(ni0 + 1, min(W, rects[d][k].i1 + di));\n                        int nj1 = max(nj0 + 1, min(W, rects[d][k].j1 + dj));\n                        \n                        Rect test_rect = {ni0, nj0, ni1, nj1};\n                        if (!checkOverlap(rects[d])) {\n                            long long test_cost = calculateTotalCost();\n                            if (test_cost < best_cost) {\n                                best_cost = test_cost;\n                                best_rect = test_rect;\n                            }\n                        }\n                    }\n                }\n                rects[d][k] = best_rect;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n    \n    // Initialize solution\n    initializeSolution();\n    \n    // Optimize\n    optimizeSolution();\n    \n    // Final improvements\n    improveAreaSatisfaction();\n    improvePartitionStability();\n    \n    // Output\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[d][k].i0 << \" \" << rects[d][k].j0 << \" \"\n                 << rects[d][k].i1 << \" \" << rects[d][k].j1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst long long MOD = 998244353;\n\n// Structures\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\n// Global variables for solver state\nint board[N][N];\nint stamps[M][3][3];\nvector<Op> current_ops;\nlong long current_score;\nvector<Op> best_ops;\nlong long best_score;\n\n// Random number generator\nmt19937_64 rng;\n\n// Function to calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += (board[i][j] % MOD);\n        }\n    }\n    return score;\n}\n\n// Function to apply an operation\nvoid apply_op(const Op& op, int val) {\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            board[op.p + i][op.q + j] += val * stamps[op.m][i][j];\n        }\n    }\n}\n\n// Function to calculate delta score for an operation\nlong long get_delta_score(const Op& op, int val) {\n    long long delta = 0;\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            int r = op.p + i;\n            int c = op.q + j;\n            long long old_val = board[r][c] % MOD;\n            long long new_val = (board[r][c] + val * stamps[op.m][i][j]) % MOD;\n            delta += new_val - old_val;\n        }\n    }\n    return delta;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    // Read board\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> board[i][j];\n        }\n    }\n\n    // Read stamps\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            for (int l = 0; l < 3; ++l) {\n                cin >> stamps[i][j][l];\n            }\n        }\n    }\n\n    // Initialize current_ops with K random operations\n    // Actually, let's start with 0 and add K operations greedily or randomly.\n    // Random initialization is better for SA to avoid local optima early.\n    // But we can also do a greedy initialization.\n    // Let's try greedy initialization first to get a decent starting point.\n    \n    // Greedy initialization\n    current_ops.clear();\n    for (int i = 0; i < k; ++i) {\n        long long max_delta = -1e18;\n        Op best_op;\n        best_op.m = 0; best_op.p = 0; best_op.q = 0;\n        \n        // Find best operation to add\n        // We can iterate over all possible operations\n        // But 20 * 7 * 7 = 980 is small enough.\n        for (int sm = 0; sm < m; ++sm) {\n            for (int sp = 0; sp <= n - 3; ++sp) {\n                for (int sq = 0; sq <= n - 3; ++sq) {\n                    Op op = {sm, sp, sq};\n                    long long delta = get_delta_score(op, 1);\n                    if (delta > max_delta) {\n                        max_delta = delta;\n                        best_op = op;\n                    }\n                }\n            }\n        }\n        \n        // If max_delta is negative, we might still want to add to reach K?\n        // Or we can stop adding.\n        // Let's add if delta > 0. If all are negative, we can pick the least negative one\n        // or just stop.\n        // But we need to output at most K.\n        // If we stop early, we use fewer operations.\n        // Let's just add the best one regardless.\n        \n        current_ops.push_back(best_op);\n        apply_op(best_op, 1);\n    }\n    \n    current_score = calculate_score();\n    best_ops = current_ops;\n    best_score = current_score;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1900); // Leave 100ms for output\n    \n    double temperature = 1000000000.0; // High initial temperature\n    double cooling_rate = 0.9995;\n    double min_temp = 1e-9;\n\n    // Distributions\n    uniform_int_distribution<int> dist_m(0, m - 1);\n    uniform_int_distribution<int> dist_p(0, n - 3);\n    uniform_int_distribution<int> dist_q(0, n - 3);\n    uniform_int_distribution<int> dist_idx(0, k - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Select a random operation index to change\n        int idx = dist_idx(rng);\n        Op old_op = current_ops[idx];\n        \n        // Generate a new random operation\n        Op new_op;\n        new_op.m = dist_m(rng);\n        new_op.p = dist_p(rng);\n        new_op.q = dist_q(rng);\n        \n        // Calculate delta\n        long long delta = 0;\n        \n        // Remove old op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = old_op.p + i;\n                int c = old_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                if (new_val < 0) new_val += MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Add new op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = new_op.p + i;\n                int c = new_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Acceptance probability\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / temperature);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_ops[idx] = new_op;\n            // Apply the change to the board\n            // Remove old\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = old_op.p + i;\n                    int c = old_op.q + j;\n                    board[r][c] -= stamps[old_op.m][i][j];\n                }\n            }\n            // Add new\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = new_op.p + i;\n                    int c = new_op.q + j;\n                    board[r][c] += stamps[new_op.m][i][j];\n                }\n            }\n            current_score += delta;\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ops = current_ops;\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < min_temp) temperature = min_temp;\n    }\n\n    // Output best solution\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int INF = 1e9;\n\n// Container ID\nconst int EMPTY = -1;\n\nstruct Crane {\n    int id;\n    int x, y;\n    int holding; // Container ID or EMPTY\n    bool is_large;\n    bool active;\n};\n\nstruct State {\n    int grid[N][N]; // Container IDs\n    vector<Crane> cranes;\n    vector<vector<int>> input_queue; // input_queue[i] = list of containers for row i\n    vector<int> dispatch_expected; // dispatch_expected[i] = next expected container for row i\n    vector<vector<int>> dispatch_order; // To calculate M1 later if needed, but heuristic focuses on current state\n    int turn;\n    int dispatched_count;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = EMPTY;\n            input_queue.push_back({});\n            dispatch_expected.push_back(N * i);\n            dispatch_order.push_back({});\n        }\n        cranes.resize(N);\n        for(int i=0; i<N; ++i) {\n            cranes[i] = {i, i, 0, EMPTY, (i == 0), true};\n        }\n        turn = 0;\n        dispatched_count = 0;\n    }\n};\n\n// Check if a move is valid for a specific crane in isolation (ignoring other crane collisions)\nbool isMoveValidForCrane(const Crane& c, char action, const State& s) {\n    if (!c.active) return false;\n    int nx = c.x, ny = c.y;\n    int holding = c.holding;\n\n    if (action == 'P') {\n        if (holding != EMPTY) return false;\n        if (s.grid[c.x][c.y] == EMPTY) return false;\n        return true;\n    }\n    if (action == 'Q') {\n        if (holding == EMPTY) return false;\n        if (s.grid[c.x][c.y] != EMPTY) return false;\n        return true;\n    }\n    if (action == 'B') {\n        if (holding != EMPTY) return false;\n        return true;\n    }\n    if (action == 'U') ny--;\n    else if (action == 'D') ny++;\n    else if (action == 'L') nx--;\n    else if (action == 'R') nx++;\n    else if (action == '.') return true;\n    else return false;\n\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    \n    // Small crane carrying container cannot move to occupied square\n    if (!c.is_large && holding != EMPTY && s.grid[nx][ny] != EMPTY) return false;\n\n    return true;\n}\n\n// Check if a combination of actions is valid (collisions)\nbool isComboValid(const vector<char>& actions, const State& s, vector<Crane>& next_cranes) {\n    int N_cranes = s.cranes.size();\n    vector<pair<int, int>> start_pos(N_cranes);\n    vector<pair<int, int>> end_pos(N_cranes);\n    \n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        start_pos[i] = {s.cranes[i].x, s.cranes[i].y};\n        \n        int nx = s.cranes[i].x;\n        int ny = s.cranes[i].y;\n        char act = actions[i];\n        if (act == 'U') ny--;\n        else if (act == 'D') ny++;\n        else if (act == 'L') nx--;\n        else if (act == 'R') nx++;\n        \n        end_pos[i] = {nx, ny};\n    }\n\n    // Check overlap and swap\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        for(int j=i+1; j<N_cranes; ++j) {\n            if (!s.cranes[j].active) continue;\n            \n            // Overlap\n            if (end_pos[i] == end_pos[j]) return false;\n            \n            // Swap\n            if (start_pos[i] == end_pos[j] && start_pos[j] == end_pos[i]) return false;\n        }\n    }\n    \n    // Apply to next_cranes for simulation\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) {\n            next_cranes[i] = s.cranes[i];\n            continue;\n        }\n        next_cranes[i] = s.cranes[i];\n        char act = actions[i];\n        if (act == 'P') {\n            next_cranes[i].holding = s.grid[s.cranes[i].x][s.cranes[i].y];\n        } else if (act == 'Q') {\n            next_cranes[i].holding = EMPTY;\n        } else if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    return true;\n}\n\n// Calculate Heuristic Score\nint calculateScore(const State& s) {\n    int score = 0;\n    int undispatched = 0;\n    int wrong_gate = 0;\n    int inversions = 0;\n    int dist_sum = 0;\n    \n    // Check dispatched containers\n    // We simulate the dispatch step for the heuristic\n    // Actually, we can just check current state.\n    // If container at (i, 4) is correct, it counts as dispatched for next turn.\n    \n    vector<int> current_dispatched(N, 0); // Count of dispatched for each row\n    \n    for(int i=0; i<N; ++i) {\n        int cx = i;\n        int cy = N-1;\n        int container = s.grid[cx][cy];\n        if (container != EMPTY) {\n            int expected = N * i + s.dispatch_order[i].size(); // This is tricky, we need to know order\n            // Simplified: Check if container belongs to this row\n            if (container / N == i) {\n                // It belongs to this row.\n                // To check inversion, we need to know previous dispatched.\n                // For heuristic, we just count if it's at correct gate.\n                // We assume if it's at correct gate, it's good.\n                // Inversion penalty is small compared to M2, M3.\n                // We can estimate inversions by checking if container < last dispatched.\n                // But we don't store history in State efficiently here.\n                // Let's just count containers at wrong gates.\n            } else {\n                wrong_gate++;\n            }\n        }\n    }\n    \n    // Count undispatched\n    // Total containers = 25.\n    // Count how many are still on grid or in input queue.\n    int on_grid = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) on_grid++;\n        }\n    }\n    int in_queue = 0;\n    for(int i=0; i<N; ++i) in_queue += s.input_queue[i].size();\n    undispatched = on_grid + in_queue;\n    \n    // Distance\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) {\n                int c = s.grid[i][j];\n                int target_r = c / N;\n                int target_c = N - 1;\n                dist_sum += abs(i - target_r) + abs(j - target_c);\n            }\n        }\n    }\n    \n    // Input Blocking Penalty\n    // If a crane is at (i, 0), it blocks input.\n    // If a container is at (i, 0), it blocks input (until picked).\n    for(int i=0; i<N; ++i) {\n        bool blocked = false;\n        if (s.grid[i][0] != EMPTY) blocked = true;\n        for(const auto& c : s.cranes) {\n            if (c.active && c.x == i && c.y == 0) blocked = true;\n        }\n        if (blocked && !s.input_queue[i].empty()) {\n            // Huge penalty for blocking input\n            score += 100000; \n        }\n    }\n    \n    // Dispatch Gate Penalty\n    // If container at (i, 4) is not the expected one, it blocks dispatch.\n    // Expected for row i is N*i, N*i+1, ...\n    // We can track expected in State.\n    for(int i=0; i<N; ++i) {\n        int expected = N * i + s.dispatch_order[i].size();\n        int container = s.grid[i][4];\n        if (container != EMPTY && container != expected) {\n            // Wrong container at dispatch gate\n            score += 100000;\n        }\n    }\n    \n    score += 1000000 * undispatched;\n    score += 10000 * wrong_gate;\n    score += 100 * dist_sum;\n    score += s.turn; // Minimize turns\n    \n    return score;\n}\n\n// Simulate one turn and return new state\nState simulateTurn(const State& s, const vector<char>& actions) {\n    State next = s;\n    next.turn = s.turn + 1;\n    \n    // Step 1: Receiving Gates\n    for(int i=0; i<N; ++i) {\n        if (!next.input_queue[i].empty()) {\n            bool blocked = false;\n            if (next.grid[i][0] != EMPTY) blocked = true;\n            for(const auto& c : next.cranes) {\n                if (c.active && c.x == i && c.y == 0) blocked = true;\n            }\n            if (!blocked) {\n                next.grid[i][0] = next.input_queue[i].front();\n                next.input_queue[i].erase(next.input_queue[i].begin());\n            }\n        }\n    }\n    \n    // Step 2: Crane Actions\n    // We need to update grid and cranes based on actions\n    // Since we already validated actions in isComboValid, we can apply them.\n    // But we need to handle P/Q on grid correctly.\n    \n    vector<Crane> next_cranes = next.cranes;\n    vector<int> next_grid[N]; // Temporary to handle P/Q order? No, simultaneous.\n    // Actually, P/Q updates grid.\n    // We should apply moves first, then P/Q? No, P/Q happens at current square.\n    // Move happens to adjacent.\n    // The problem says \"Perform the actions of each crane\".\n    // It implies P/Q/Move are atomic per crane.\n    // So we update grid based on P/Q at current pos, then move cranes.\n    // Wait, if P happens, container leaves grid. If Q happens, container enters grid.\n    // If Move happens, crane changes pos.\n    // Order:\n    // 1. Check P/Q validity (already done).\n    // 2. Apply P: remove from grid, set crane holding.\n    // 3. Apply Q: set crane holding to EMPTY, put to grid.\n    // 4. Apply Move: update crane pos.\n    // Note: If a crane moves from A to B, and another Q at B?\n    // \"Cranes cannot overlap\". So if A moves to B, B must be empty of cranes.\n    // But can B have a container? Yes.\n    // If crane Q at B, it puts container at B.\n    // If crane A moves to B, it arrives at B.\n    // If A moves to B, and B was empty, now A is at B.\n    // If Q happens at B (by crane C), C must be at B.\n    // So A cannot move to B if C is at B.\n    // So Crane positions are updated simultaneously.\n    // Grid updates:\n    // - P removes from grid.\n    // - Q adds to grid.\n    // - Container at (i,0) added in Step 1.\n    // - Container at (i,4) removed in Step 3.\n    \n    // Apply P\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'P') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = EMPTY;\n            next_cranes[i].holding = s.grid[next_cranes[i].x][next_cranes[i].y];\n        }\n    }\n    // Apply Q\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'Q') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = next_cranes[i].holding;\n            next_cranes[i].holding = EMPTY;\n        }\n    }\n    // Apply Move / Bomb\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        char act = actions[i];\n        if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    next.cranes = next_cranes;\n    \n    // Step 3: Dispatch\n    for(int i=0; i<N; ++i) {\n        int container = next.grid[i][4];\n        if (container != EMPTY) {\n            // Check if correct\n            int expected = N * i + next.dispatch_order[i].size();\n            if (container == expected) {\n                next.dispatch_order[i].push_back(container);\n                next.grid[i][4] = EMPTY;\n                next.dispatched_count++;\n            }\n        }\n    }\n    \n    return next;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int N_in;\n    if (!(cin >> N_in)) return 0;\n    \n    State s;\n    // Read Input\n    // A_{i,j}\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int val;\n            cin >> val;\n            s.input_queue[i].push_back(val);\n        }\n    }\n    \n    vector<string> result(N, \"\");\n    \n    // Precompute valid actions for each crane to speed up\n    // But valid actions depend on state.\n    \n    // Loop\n    for(int t=0; t<MAX_TURNS; ++t) {\n        if (s.dispatched_count == N*N) break;\n        \n        // Generate candidate actions for each crane\n        vector<vector<pair<char, int>>> candidates(N);\n        \n        for(int i=0; i<N; ++i) {\n            if (!s.cranes[i].active) {\n                candidates[i].push_back({'.', 0});\n                continue;\n            }\n            const Crane& c = s.cranes[i];\n            vector<char> moves = {'P', 'Q', 'U', 'D', 'L', 'R', '.'};\n            for(char m : moves) {\n                if (isMoveValidForCrane(c, m, s)) {\n                    // Estimate score for this move alone (others do '.')\n                    // To save time, we can use a simpler heuristic or just add to list.\n                    // Let's just collect valid moves.\n                    candidates[i].push_back({m, 0});\n                }\n            }\n            // Sort candidates by some priority?\n            // Priority:\n            // 1. If at (i,0) and container exists: P\n            // 2. If holding: Q or Move towards target\n            // 3. If empty: Move towards (i,0) or container\n            // We can sort here to pick top K.\n            // For now, take all valid.\n            // Limit to top 5 to keep 5^5 small.\n            if (candidates[i].size() > 5) {\n                // Sort by heuristic improvement\n                // We can't compute full heuristic for each.\n                // Use simple priority.\n                // Just take first 5.\n                candidates[i].resize(5);\n            }\n        }\n        \n        // Iterate combinations\n        // We need to find the best valid combination.\n        // Since candidates are small (<=5), 5^5 = 3125.\n        // We can use a recursive search or nested loops.\n        // To find BEST, we can iterate all and track best.\n        \n        int best_score = INF;\n        vector<char> best_actions(N, '.');\n        bool found = false;\n        \n        // Use a simple iterative approach with indices\n        vector<int> idx(N, 0);\n        vector<int> sizes(N);\n        for(int i=0; i<N; ++i) sizes[i] = candidates[i].size();\n        \n        // We can use a priority queue to explore combinations in order of estimated utility?\n        // No, just iterate all valid ones and pick best.\n        // 3125 is small enough.\n        \n        // To optimize, we can prune invalid combos early.\n        // But 3125 is very small.\n        \n        // We need to generate all combinations.\n        // Recursive function\n        auto search = [&](auto&& self, int crane_idx, vector<char>& current_actions, State& temp_s, vector<Crane>& temp_cranes) -> void {\n            if (crane_idx == N) {\n                // Check validity of full combo\n                if (isComboValid(current_actions, s, temp_cranes)) {\n                    // Calculate score\n                    // We can simulate the turn to get exact score\n                    // But simulation is expensive.\n                    // Let's use calculateScore on the resulting state.\n                    // To avoid full simulation, we can approximate.\n                    // But for correctness, simulate.\n                    // Actually, we can just calculate score on 's' with modifications.\n                    // Let's just simulate.\n                    State next_s = simulateTurn(s, current_actions);\n                    int sc = calculateScore(next_s);\n                    if (sc < best_score) {\n                        best_score = sc;\n                        best_actions = current_actions;\n                        found = true;\n                    }\n                }\n                return;\n            }\n            \n            for(int i=0; i<sizes[crane_idx]; ++i) {\n                current_actions[crane_idx] = candidates[crane_idx][i].first;\n                self(self, crane_idx + 1, current_actions, temp_s, temp_cranes);\n            }\n        };\n        \n        vector<char> current_actions(N);\n        State temp_s = s;\n        vector<Crane> temp_cranes = s.cranes;\n        search(search, 0, current_actions, temp_s, temp_cranes);\n        \n        if (!found) {\n            // Fallback: all '.'\n            best_actions.assign(N, '.');\n        }\n        \n        // Apply best actions\n        for(int i=0; i<N; ++i) {\n            result[i] += best_actions[i];\n        }\n        \n        s = simulateTurn(s, best_actions);\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << result[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Point {\n    int x, y;\n    int id;\n};\n\nint dist(Point p1, Point p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<vector<int>> h(N, vector<int>(N));\n    vector<Point> sources, sinks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j, i * N + j});\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j, i * N + j});\n            }\n        }\n    }\n\n    int num_sources = sources.size();\n    int num_sinks = sinks.size();\n\n    // Build Min-Cost Flow Graph\n    // Nodes: 0..N*N-1 (Grid Cells), N*N (Source S), N*N+1 (Sink T)\n    // However, MCF works better with a bipartite structure for this problem.\n    // Let's map:\n    // S -> SourceCell (cap = h, cost = 0)\n    // SourceCell -> SinkCell (cap = inf, cost = dist)\n    // SinkCell -> T (cap = |h|, cost = 0)\n    \n    // To use AC Library MCF, we need to map grid cells to nodes.\n    // Let's use:\n    // 0..num_sources-1 : Source Cells\n    // num_sources..num_sources+num_sinks-1 : Sink Cells\n    // num_sources+num_sinks : S\n    // num_sources+num_sinks+1 : T\n    \n    int S = num_sources + num_sinks;\n    int T = num_sources + num_sinks + 1;\n    MCF mcf(T + 1);\n\n    long long total_supply = 0;\n    for (int i = 0; i < num_sources; ++i) {\n        int supply = h[sources[i].x][sources[i].y];\n        total_supply += supply;\n        mcf.add_edge(S, i, supply, 0);\n    }\n\n    for (int i = 0; i < num_sinks; ++i) {\n        int demand = abs(h[sinks[i].x][sinks[i].y]);\n        mcf.add_edge(num_sources + i, T, demand, 0);\n    }\n\n    for (int i = 0; i < num_sources; ++i) {\n        for (int j = 0; j < num_sinks; ++j) {\n            int d = dist(sources[i], sinks[j]);\n            mcf.add_edge(i, num_sources + j, 1e9, d);\n        }\n    }\n\n    auto result = mcf.min_cost_flow(S, T, total_supply);\n    // result.first is flow, result.second is cost\n\n    // Extract flow\n    // requests[u_idx] = vector of {v_idx, flow_amount}\n    vector<vector<pair<int, int>>> requests(num_sources);\n    \n    // Iterate over edges from SourceCells to SinkCells\n    // In MCF, edges are stored in a list. We need to find which ones are relevant.\n    // The edges from SourceCells (0..num_sources-1) to SinkCells (num_sources..) are the ones we care about.\n    // However, MCF adds edges in order.\n    // S->Source: 0..num_sources-1\n    // Sink->T: num_sources..num_sources+num_sinks-1\n    // Source->Sink: num_sources+num_sinks .. end\n    \n    // Let's iterate all edges and check indices\n    for (const auto &e : mcf.edges()) {\n        if (e.from >= 0 && e.from < num_sources && e.to >= num_sources && e.to < num_sources + num_sinks) {\n            if (e.flow > 0) {\n                int u_idx = e.from;\n                int v_idx = e.to - num_sources;\n                requests[u_idx].push_back({v_idx, (int)e.flow});\n            }\n        }\n    }\n\n    // Routing\n    // Current position\n    int cur_x = 0, cur_y = 0;\n    // Visited sources\n    vector<bool> source_done(num_sources, false);\n    // Remaining sources count\n    int remaining_sources = num_sources;\n    \n    // We will store operations\n    vector<string> ops;\n    \n    // Helper to move from (cx, cy) to (tx, ty)\n    auto move_to = [&](int tx, int ty) {\n        while (cur_x < tx) {\n            cur_x++;\n            ops.push_back(\"D\");\n        }\n        while (cur_x > tx) {\n            cur_x--;\n            ops.push_back(\"U\");\n        }\n        while (cur_y < ty) {\n            cur_y++;\n            ops.push_back(\"R\");\n        }\n        while (cur_y > ty) {\n            cur_y--;\n            ops.push_back(\"L\");\n        }\n    };\n\n    // Helper to load\n    auto load = [&](int amount) {\n        ops.push_back(\"+\" + to_string(amount));\n    };\n\n    // Helper to unload\n    auto unload = [&](int amount) {\n        ops.push_back(\"-\" + to_string(amount));\n    };\n\n    // Main Loop\n    while (remaining_sources > 0) {\n        // Find nearest source that is not done\n        int best_u = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < num_sources; ++i) {\n            if (!source_done[i]) {\n                int d = dist({cur_x, cur_y, -1}, sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_u = i;\n                }\n            }\n        }\n\n        if (best_u == -1) break; // Should not happen\n\n        // Move to source\n        move_to(sources[best_u].x, sources[best_u].y);\n\n        // Load soil\n        // We load all soil assigned to this source\n        // But we can load it in one go since capacity is effectively infinite\n        // However, we need to track how much we load to unload later.\n        // Actually, we can just load the total amount needed for this source's sinks.\n        int total_load = 0;\n        for (auto &p : requests[best_u]) {\n            total_load += p.second;\n        }\n        load(total_load);\n\n        // Plan Sink Tour\n        // We have a list of sinks to visit: requests[best_u]\n        // We want to visit them in an order that minimizes distance.\n        // Start at sources[best_u].\n        // End at some sink, then move to next source.\n        // Since we pick next source based on distance from current end, \n        // we just need to minimize the tour length from source to sinks.\n        // We use Nearest Neighbor for sinks.\n        \n        vector<int> sink_order;\n        vector<bool> sink_done_local(requests[best_u].size(), false);\n        int cur_sink_x = sources[best_u].x;\n        int cur_sink_y = sources[best_u].y;\n        \n        // Nearest Neighbor\n        for (int k = 0; k < requests[best_u].size(); ++k) {\n            int best_v = -1;\n            int min_d_sink = 1e9;\n            for (int i = 0; i < requests[best_u].size(); ++i) {\n                if (!sink_done_local[i]) {\n                    int d = dist({cur_sink_x, cur_sink_y, -1}, sinks[requests[best_u][i].first]);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                        best_v = i;\n                    }\n                }\n            }\n            if (best_v != -1) {\n                sink_done_local[best_v] = true;\n                sink_order.push_back(best_v);\n                int v_idx = requests[best_u][best_v].first;\n                cur_sink_x = sinks[v_idx].x;\n                cur_sink_y = sinks[v_idx].y;\n            }\n        }\n\n        // Execute Sink Tour\n        for (int idx : sink_order) {\n            int v_idx = requests[best_u][idx].first;\n            int amount = requests[best_u][idx].second;\n            int tx = sinks[v_idx].x;\n            int ty = sinks[v_idx].y;\n            \n            move_to(tx, ty);\n            unload(amount);\n        }\n\n        // Mark source as done\n        source_done[best_u] = true;\n        remaining_sources--;\n    }\n\n    // Output\n    for (const string &s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_int(0, 35);\nuniform_real_distribution<double> dist_real(0.0, 1.0);\n\nint N, M, T;\nint seed_count;\nvector<vector<int>> seeds;\nvector<int> seed_val;\nvector<vector<int>> adj;\nvector<int> pos_order;\nvector<int> grid;\nlong long current_score;\n\nlong long calc_edge_score(int u, int v) {\n    long long s = 0;\n    for (int l = 0; l < M; ++l) {\n        s += max(seeds[u][l], seeds[v][l]);\n    }\n    return s;\n}\n\nvoid init_adj() {\n    adj.assign(N * N, vector<int>());\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (i > 0) adj[u].push_back((i - 1) * N + j);\n            if (i < N - 1) adj[u].push_back((i + 1) * N + j);\n            if (j > 0) adj[u].push_back(i * N + (j - 1));\n            if (j < N - 1) adj[u].push_back(i * N + (j + 1));\n        }\n    }\n}\n\nvoid init_pos_order() {\n    pos_order.resize(N * N);\n    iota(pos_order.begin(), pos_order.end(), 0);\n    sort(pos_order.begin(), pos_order.end(), [&](int a, int b) {\n        return adj[a].size() > adj[b].size();\n    });\n}\n\nvoid init_grid() {\n    vector<int> p(seed_count);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        return seed_val[a] > seed_val[b];\n    });\n\n    for (int k = 0; k < N * N; ++k) {\n        grid[pos_order[k]] = p[k];\n    }\n\n    current_score = 0;\n    for (int i = 0; i < N * N; ++i) {\n        for (int n : adj[i]) {\n            if (i < n) {\n                current_score += calc_edge_score(grid[i], grid[n]);\n            }\n        }\n    }\n}\n\nvoid sa() {\n    double temp = 10000.0;\n    double cooling = 0.995;\n    int iterations = 50000;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int u = dist_int(gen);\n        int v = dist_int(gen);\n        if (u == v) continue;\n\n        long long delta = 0;\n        \n        // Remove contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta -= calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta -= calc_edge_score(grid[v], grid[n]);\n        }\n\n        swap(grid[u], grid[v]);\n\n        // Add contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta += calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta += calc_edge_score(grid[v], grid[n]);\n        }\n\n        if (delta >= 0 || dist_real(gen) < exp(delta / temp)) {\n            current_score += delta;\n        } else {\n            swap(grid[u], grid[v]);\n        }\n\n        temp *= cooling;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> T;\n    seed_count = 2 * N * (N - 1);\n    seeds.resize(seed_count, vector<int>(M));\n    seed_val.resize(seed_count);\n\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n            seed_val[i] += seeds[i][j];\n        }\n    }\n\n    init_adj();\n    init_pos_order();\n    grid.resize(N * N);\n\n    for (int t = 0; t < T; ++t) {\n        // Recalculate seed_val in case we need to re-sort (though we do it inside init_grid)\n        // Actually, seeds change every turn, so we must update seed_val\n        for (int i = 0; i < seed_count; ++i) {\n            seed_val[i] = 0;\n            for (int j = 0; j < M; ++j) {\n                seed_val[i] += seeds[i][j];\n            }\n        }\n\n        init_grid();\n        sa();\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << grid[i * N + j] << (j == N - 1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Takoyaki {\n    Point src, tgt;\n    int id;\n    bool done = false;\n};\n\nint N, M, V;\nvector<string> s_grid, t_grid;\nvector<Takoyaki> takoyakis;\nvector<int> edge_len;\nint root_x, root_y;\nint dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // R, D, L, U\nchar dir_char[4] = {'R', 'D', 'L', 'U'};\n\n// Current state\nint arm_dir[16]; // direction of each edge (0-3)\nbool holding[16]; // whether each fingertip is holding\nPoint fingertip_pos[16]; // current position of each fingertip\n\n// Calculate fingertip positions based on root and directions\nvoid update_fingertip_positions() {\n    for (int i = 1; i < edge_len.size() + 1; i++) {\n        int fx = root_x + dir[arm_dir[i]][0] * edge_len[i];\n        int fy = root_y + dir[arm_dir[i]][1] * edge_len[i];\n        fingertip_pos[i] = {fx, fy};\n    }\n}\n\n// Check if position is valid\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there's a takoyaki at position\nbool has_takoyaki(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1';\n}\n\n// Check if position is a target\nbool is_target(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return t_grid[x][y] == '1';\n}\n\n// Check if position has been filled (target completed)\nbool is_filled(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1' && t_grid[x][y] == '1';\n}\n\n// Find nearest available source for a fingertip\nPoint find_nearest_source(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].src.x) + abs(fp.y - takoyakis[i].src.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].src;\n        }\n    }\n    return best;\n}\n\n// Find nearest available target for a fingertip\nPoint find_nearest_target(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].tgt.x) + abs(fp.y - takoyakis[i].tgt.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].tgt;\n        }\n    }\n    return best;\n}\n\n// Get direction to move towards a target\nint get_direction(Point current, Point target) {\n    if (current.x < target.x) return 1; // D\n    if (current.x > target.x) return 3; // U\n    if (current.y < target.y) return 0; // R\n    if (current.y > target.y) return 2; // L\n    return 0; // Default\n}\n\n// Get rotation to achieve desired direction\nchar get_rotation(int current_dir, int target_dir) {\n    int diff = (target_dir - current_dir + 4) % 4;\n    if (diff == 0) return '.';\n    if (diff == 1 || diff == 3) return 'R'; // clockwise\n    return 'L'; // counterclockwise\n}\n\n// Check if all takoyaki are delivered\nbool all_delivered() {\n    for (int i = 0; i < M; i++) {\n        if (!takoyakis[i].done) return false;\n    }\n    return true;\n}\n\n// Check if a source still has takoyaki\nbool source_has_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return s_grid[p.x][p.y] == '1' && t_grid[p.x][p.y] == '0';\n}\n\n// Check if a target needs takoyaki\nbool target_needs_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return t_grid[p.x][p.y] == '1' && s_grid[p.x][p.y] == '0';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> V;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    \n    for (int i = 0; i < N; i++) cin >> s_grid[i];\n    for (int i = 0; i < N; i++) cin >> t_grid[i];\n    \n    // Parse takoyaki positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                takoyakis.push_back({{i, j}, {0, 0}, (int)takoyakis.size()});\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (t_grid[i][j] == '1' && s_grid[i][j] == '0') {\n                // Find matching source\n                for (auto& t : takoyakis) {\n                    if (t.tgt.x == 0 && t.tgt.y == 0) {\n                        t.tgt = {i, j};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Design star topology robot\n    int num_fingertips = min(V - 1, M); // Each fingertip handles one takoyaki\n    \n    // Output robot design\n    cout << num_fingertips + 1 << \"\\n\";\n    edge_len.resize(num_fingertips + 1);\n    \n    // Use different edge lengths for better coverage\n    for (int i = 1; i <= num_fingertips; i++) {\n        edge_len[i] = min(i * 2, N - 1);\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Initial position: center of grid\n    root_x = N / 2;\n    root_y = N / 2;\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Initialize directions (all pointing right initially)\n    for (int i = 0; i <= num_fingertips; i++) {\n        arm_dir[i] = 0;\n        holding[i] = false;\n    }\n    \n    update_fingertip_positions();\n    \n    // Main operation loop\n    int turn = 0;\n    int max_turns = 80000; // Leave margin for system test\n    \n    while (turn < max_turns && !all_delivered()) {\n        string cmd = \"\";\n        \n        // Step 1: Decide arm movement\n        // Find average direction to move towards pending sources/targets\n        int total_dx = 0, total_dy = 0;\n        int count = 0;\n        \n        for (int i = 0; i < M; i++) {\n            if (takoyakis[i].done) continue;\n            if (holding[i % (num_fingertips + 1)]) {\n                // Moving towards target\n                total_dx += takoyakis[i].tgt.x - root_x;\n                total_dy += takoyakis[i].tgt.y - root_y;\n            } else {\n                // Moving towards source\n                total_dx += takoyakis[i].src.x - root_x;\n                total_dy += takoyakis[i].src.y - root_y;\n                count++;\n            }\n        }\n        \n        // Determine movement direction\n        char move = '.';\n        if (count > 0) {\n            if (abs(total_dx) > abs(total_dy)) {\n                if (total_dx > 0) move = 'D';\n                else if (total_dx < 0) move = 'U';\n            } else {\n                if (total_dy > 0) move = 'R';\n                else if (total_dy < 0) move = 'L';\n            }\n        }\n        \n        // Check if movement is valid\n        int nx = root_x, ny = root_y;\n        if (move == 'D') nx++;\n        else if (move == 'U') nx--;\n        else if (move == 'R') ny++;\n        else if (move == 'L') ny--;\n        \n        if (!is_valid(nx, ny)) move = '.';\n        else { root_x = nx; root_y = ny; }\n        \n        cmd += move;\n        \n        // Step 2: Decide rotations for each fingertip\n        for (int i = 1; i <= num_fingertips; i++) {\n            char rot = '.';\n            \n            // Find what this fingertip should do\n            Point fp = fingertip_pos[i];\n            \n            if (holding[i]) {\n                // Try to drop at target\n                Point tgt = find_nearest_target(fp);\n                if (tgt.x >= 0 && target_needs_takoyaki(tgt)) {\n                    // Calculate direction to reach target\n                    int dx = tgt.x - root_x;\n                    int dy = tgt.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            } else {\n                // Try to pick from source\n                Point src = find_nearest_source(fp);\n                if (src.x >= 0 && source_has_takoyaki(src)) {\n                    // Calculate direction to reach source\n                    int dx = src.x - root_x;\n                    int dy = src.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            }\n            \n            cmd += rot;\n        }\n        \n        // Step 3: Decide pick/place actions\n        for (int i = 1; i <= num_fingertips; i++) {\n            update_fingertip_positions();\n            Point fp = fingertip_pos[i];\n            char action = '.';\n            \n            if (is_valid(fp.x, fp.y)) {\n                if (holding[i] && target_needs_takoyaki(fp.x, fp.y)) {\n                    // Drop takoyaki\n                    action = 'P';\n                    holding[i] = false;\n                    s_grid[fp.x][fp.y] = '1';\n                    \n                    // Mark as done\n                    for (int j = 0; j < M; j++) {\n                        if (!takoyakis[j].done && \n                            takoyakis[j].tgt.x == fp.x && \n                            takoyakis[j].tgt.y == fp.y) {\n                            takoyakis[j].done = true;\n                            break;\n                        }\n                    }\n                } else if (!holding[i] && source_has_takoyaki(fp.x, fp.y)) {\n                    // Pick takoyaki\n                    action = 'P';\n                    holding[i] = true;\n                    s_grid[fp.x][fp.y] = '0';\n                }\n            }\n            \n            cmd += action;\n        }\n        \n        // Add '.' for root (not a fingertip)\n        cmd += '.';\n        \n        cout << cmd << \"\\n\";\n        turn++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Distance squared\nlong long distSq(Point p1, Point p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Check if point is inside or on boundary of orthogonal polygon\nbool isInside(const vector<Point>& poly, Point p) {\n    int n = poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        bool cond1 = ((poly[i].y > p.y) != (poly[j].y > p.y));\n        // Avoid division by zero\n        if (poly[j].y != poly[i].y) {\n            bool cond2 = (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (double)(poly[j].y - poly[i].y) + poly[i].x);\n            if (cond1 && cond2) inside = !inside;\n        }\n    }\n    // Handle boundary explicitly\n    if (!inside) {\n        for (int i = 0; i < n; ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % n];\n            if (p1.x == p2.x) {\n                if (p.x == p1.x && min(p1.y, p2.y) <= p.y && p.y <= max(p1.y, p2.y)) return true;\n            } else {\n                if (p.y == p1.y && min(p1.x, p2.x) <= p.x && p.x <= max(p1.x, p2.x)) return true;\n            }\n        }\n    }\n    return inside;\n}\n\n// Simple DSU for clustering\nstruct SimpleDSU {\n    vector<int> parent;\n    SimpleDSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx != ry) parent[rx] = ry;\n    }\n};\n\nstruct ClusterInfo {\n    int id;\n    vector<int> indices;\n    long long minX, maxX, minY, maxY;\n    int m_count, s_count;\n    long long score;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // 1. Cluster Mackerels\n    const long long CLUSTER_DIST_SQ = 6000LL * 6000LL;\n    SimpleDSU dsu_m(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (distSq(mackerels[i], mackerels[j]) <= CLUSTER_DIST_SQ) {\n                dsu_m.unite(i, j);\n            }\n        }\n    }\n\n    vector<vector<int>> m_clusters(N);\n    for (int i = 0; i < N; ++i) {\n        m_clusters[dsu_m.find(i)].push_back(i);\n    }\n\n    // 2. Evaluate Clusters\n    vector<ClusterInfo> good_clusters;\n    for (int i = 0; i < N; ++i) {\n        if (m_clusters[i].empty()) continue;\n        \n        long long minX = 1e9, maxX = -1e9, minY = 1e9, maxY = -1e9;\n        for (int idx : m_clusters[i]) {\n            minX = min(minX, mackerels[idx].x);\n            maxX = max(maxX, mackerels[idx].x);\n            minY = min(minY, mackerels[idx].y);\n            maxY = max(maxY, mackerels[idx].y);\n        }\n\n        int m_cnt = m_clusters[i].size();\n        int s_cnt = 0;\n        for (const auto& s : sardines) {\n            if (s.x >= minX && s.x <= maxX && s.y >= minY && s.y <= maxY) {\n                s_cnt++;\n            }\n        }\n\n        long long sc = (long long)m_cnt - s_cnt;\n        if (sc > 0) {\n            good_clusters.push_back({i, m_clusters[i], minX, maxX, minY, maxY, m_cnt, s_cnt, sc});\n        }\n    }\n\n    // 3. Merge Good Clusters\n    sort(good_clusters.begin(), good_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n        return a.score > b.score;\n    });\n\n    vector<int> used(N, 0);\n    vector<ClusterInfo> final_clusters;\n    \n    auto distBox = [](const ClusterInfo& a, const ClusterInfo& b) {\n        long long dx = max(0LL, max(a.minX, b.minX) - min(a.maxX, b.maxX));\n        long long dy = max(0LL, max(a.minY, b.minY) - min(a.maxY, b.maxY));\n        return dx * dx + dy * dy;\n    };\n\n    for (int i = 0; i < (int)good_clusters.size(); ++i) {\n        if (used[i]) continue;\n        \n        ClusterInfo current = good_clusters[i];\n        used[i] = 1;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int j = 0; j < (int)good_clusters.size(); ++j) {\n                if (i == j || used[j]) continue;\n                \n                long long d2 = distBox(current, good_clusters[j]);\n                if (d2 <= 2000LL * 2000LL) { \n                    current.minX = min(current.minX, good_clusters[j].minX);\n                    current.maxX = max(current.maxX, good_clusters[j].maxX);\n                    current.minY = min(current.minY, good_clusters[j].minY);\n                    current.maxY = max(current.maxY, good_clusters[j].maxY);\n                    \n                    int m_cnt = 0;\n                    int s_cnt = 0;\n                    for (const auto& m : mackerels) {\n                        if (m.x >= current.minX && m.x <= current.maxX && m.y >= current.minY && m.y <= current.maxY) m_cnt++;\n                    }\n                    for (const auto& s : sardines) {\n                        if (s.x >= current.minX && s.x <= current.maxX && s.y >= current.minY && s.y <= current.maxY) s_cnt++;\n                    }\n                    current.m_count = m_cnt;\n                    current.s_count = s_cnt;\n                    current.score = (long long)m_cnt - s_cnt;\n                    \n                    used[j] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (current.score > 0) {\n            final_clusters.push_back(current);\n        }\n    }\n\n    if (final_clusters.empty()) {\n        cout << 4 << \"\\n\";\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    sort(final_clusters.begin(), final_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n        return a.score > b.score;\n    });\n\n    ClusterInfo best = final_clusters[0];\n    long long cur_minX = best.minX;\n    long long cur_maxX = best.maxX;\n    long long cur_minY = best.minY;\n    long long cur_maxY = best.maxY;\n\n    // Shrink Phase\n    for (const auto& s : sardines) {\n        if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_minX) cur_minX = s.x + 1;\n        if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_maxX) cur_maxX = s.x - 1;\n        if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_minY) cur_minY = s.y + 1;\n        if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_maxY) cur_maxY = s.y - 1;\n    }\n    \n    vector<Point> poly;\n    if (cur_minX <= cur_maxX && cur_minY <= cur_maxY) {\n        poly.push_back({cur_minX, cur_minY});\n        poly.push_back({cur_maxX, cur_minY});\n        poly.push_back({cur_maxX, cur_maxY});\n        poly.push_back({cur_minX, cur_maxY});\n    } else {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Notch Phase\n    int max_notches = 250;\n    int notches_applied = 0;\n    \n    // Maintain bounding box for optimization\n    long long poly_minX = cur_minX, poly_maxX = cur_maxX;\n    long long poly_minY = cur_minY, poly_maxY = cur_maxY;\n\n    while (notches_applied < max_notches && poly.size() <= 800) {\n        Point sardine_to_cut = {-1, -1};\n        int edge_idx = -1;\n        \n        // Find a sardine on the boundary\n        // Optimization: only check sardines near the bounding box\n        for (const auto& s : sardines) {\n            if (abs(s.x - poly_minX) > 1 && abs(s.x - poly_maxX) > 1 && \n                abs(s.y - poly_minY) > 1 && abs(s.y - poly_maxY) > 1) continue;\n                \n            if (isInside(poly, s)) {\n                bool on_boundary = false;\n                for (int i = 0; i < poly.size(); ++i) {\n                    Point p1 = poly[i];\n                    Point p2 = poly[(i + 1) % poly.size()];\n                    if (p1.x == p2.x) {\n                        if (s.x == p1.x && min(p1.y, p2.y) <= s.y && s.y <= max(p1.y, p2.y)) {\n                            on_boundary = true;\n                            edge_idx = i;\n                            break;\n                        }\n                    } else {\n                        if (s.y == p1.y && min(p1.x, p2.x) <= s.x && s.x <= max(p1.x, p2.x)) {\n                            on_boundary = true;\n                            edge_idx = i;\n                            break;\n                        }\n                    }\n                }\n                if (on_boundary) {\n                    sardine_to_cut = s;\n                    break;\n                }\n            }\n        }\n        \n        if (sardine_to_cut.x == -1) break; \n        \n        Point p1 = poly[edge_idx];\n        Point p2 = poly[(edge_idx + 1) % poly.size()];\n        \n        long long cx = 0, cy = 0;\n        for (const auto& p : poly) { cx += p.x; cy += p.y; }\n        cx /= poly.size(); cy /= poly.size();\n        \n        long long notch_x = sardine_to_cut.x;\n        long long notch_y = sardine_to_cut.y;\n        \n        if (p1.x == p2.x) {\n            if (cx > p1.x) notch_x = p1.x - 1;\n            else notch_x = p1.x + 1;\n            \n            vector<Point> new_poly;\n            for (int i = 0; i < poly.size(); ++i) {\n                if (i == edge_idx) {\n                    new_poly.push_back(p1);\n                    new_poly.push_back({p1.x, sardine_to_cut.y});\n                    new_poly.push_back({notch_x, sardine_to_cut.y});\n                    new_poly.push_back({p2.x, sardine_to_cut.y});\n                } else {\n                    new_poly.push_back(poly[i]);\n                }\n            }\n            poly = new_poly;\n        } else {\n            if (cx > p1.y) notch_y = p1.y - 1;\n            else notch_y = p1.y + 1;\n            \n            vector<Point> new_poly;\n            for (int i = 0; i < poly.size(); ++i) {\n                if (i == edge_idx) {\n                    new_poly.push_back(p1);\n                    new_poly.push_back({sardine_to_cut.x, p1.y});\n                    new_poly.push_back({sardine_to_cut.x, notch_y});\n                    new_poly.push_back({p2.x, p2.y});\n                } else {\n                    new_poly.push_back(poly[i]);\n                }\n            }\n            poly = new_poly;\n        }\n        \n        notches_applied++;\n        // Update bounding box roughly\n        poly_minX = 1e9; poly_maxX = -1e9; poly_minY = 1e9; poly_maxY = -1e9;\n        for(const auto& p : poly) {\n            poly_minX = min(poly_minX, p.x);\n            poly_maxX = max(poly_maxX, p.x);\n            poly_minY = min(poly_minY, p.y);\n            poly_maxY = max(poly_maxY, p.y);\n        }\n    }\n    \n    // Filter duplicates\n    vector<Point> unique_poly;\n    for (int i = 0; i < poly.size(); ++i) {\n        if (i > 0 && poly[i].x == poly[i-1].x && poly[i].y == poly[i-1].y) continue;\n        unique_poly.push_back(poly[i]);\n    }\n    if (unique_poly.size() > 1 && unique_poly.front().x == unique_poly.back().x && unique_poly.front().y == unique_poly.back().y) {\n        unique_poly.pop_back();\n    }\n    poly = unique_poly;\n    \n    if (poly.size() < 4) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << poly.size() << \"\\n\";\n    for (const auto& p : poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Placement {\n    int p;  // rectangle index\n    int r;  // rotation (0 or 1)\n    char d; // direction ('U' or 'L')\n    int b;  // reference rectangle index (-1 or index)\n};\n\nstruct Rect {\n    int id;\n    int w, h;\n    int x, y;\n};\n\nclass Solver {\nprivate:\n    int N, T;\n    double sigma;\n    vector<pair<int, int>> wh;\n    mt19937 rng;\n    int best_W = 2e9, best_H = 2e9;\n    vector<Placement> best_placements;\n    \n    // Calculate actual placement position\n    pair<int, int> calculatePosition(const vector<Rect>& placed, int rw, int rh, \n                                     char dir, int ref) {\n        int x = 0, y = 0;\n        \n        if (dir == 'U') {\n            // Place upward - align left edge with reference's right edge (or x=0)\n            x = (ref == -1) ? 0 : placed[ref].x + placed[ref].w;\n            y = 0;\n            // Move up until hitting something\n            for (const auto& r : placed) {\n                if (x < r.x + r.w && x + rw > r.x) {\n                    y = max(y, r.y + r.h);\n                }\n            }\n        } else {\n            // Place leftward - align top edge with reference's bottom edge (or y=0)\n            y = (ref == -1) ? 0 : placed[ref].y + placed[ref].h;\n            x = 0;\n            // Move left until hitting something\n            for (const auto& r : placed) {\n                if (y < r.y + r.h && y + rh > r.y) {\n                    x = max(x, r.x + r.w);\n                }\n            }\n        }\n        \n        return {x, y};\n    }\n    \n    // Calculate bounding box\n    pair<int, int> getBoundingBox(const vector<Rect>& placed) {\n        if (placed.empty()) return {0, 0};\n        int W = 0, H = 0;\n        for (const auto& r : placed) {\n            W = max(W, r.x + r.w);\n            H = max(H, r.y + r.h);\n        }\n        return {W, H};\n    }\n    \n    // Try greedy placement with given strategy\n    vector<Placement> greedyPlacement(int strategy, bool trySkip = false) {\n        vector<Placement> placements;\n        vector<Rect> placed;\n        \n        for (int i = 0; i < N; i++) {\n            // Decide whether to skip this rectangle\n            bool skip = false;\n            if (trySkip && strategy == 2 && rng() % 5 == 0) {\n                skip = true;\n            }\n            \n            if (skip) continue;\n            \n            int best_score = 2e9;\n            Placement best_p = {i, 0, 'U', -1};\n            \n            for (int rot = 0; rot < 2; rot++) {\n                int rw = rot ? wh[i].second : wh[i].first;\n                int rh = rot ? wh[i].first : wh[i].second;\n                \n                for (char dir : {'U', 'L'}) {\n                    // Try different reference rectangles\n                    int max_ref = (int)placed.size() - 1;\n                    for (int ref = -1; ref <= max_ref; ref++) {\n                        auto [x, y] = calculatePosition(placed, rw, rh, dir, ref);\n                        \n                        // Calculate bounding box with this placement\n                        int W = 0, H = 0;\n                        for (const auto& r : placed) {\n                            W = max(W, r.x + r.w);\n                            H = max(H, r.y + r.h);\n                        }\n                        W = max(W, x + rw);\n                        H = max(H, y + rh);\n                        \n                        int score = W + H;\n                        if (score < best_score) {\n                            best_score = score;\n                            best_p = {i, rot, dir, ref};\n                        }\n                    }\n                }\n            }\n            \n            placements.push_back(best_p);\n            int rw = best_p.r ? wh[i].second : wh[i].first;\n            int rh = best_p.r ? wh[i].first : wh[i].second;\n            auto [x, y] = calculatePosition(placed, rw, rh, best_p.d, best_p.b);\n            placed.push_back({i, rw, rh, x, y});\n        }\n        \n        return placements;\n    }\n    \n    // Try multiple strategies and return best\n    vector<Placement> findBestPlacement() {\n        vector<Placement> best = greedyPlacement(0);\n        int best_score = 2e9;\n        \n        // Calculate score for initial best\n        vector<Rect> placed;\n        for (const auto& p : best) {\n            int rw = p.r ? wh[p.p].second : wh[p.p].first;\n            int rh = p.r ? wh[p.p].first : wh[p.p].second;\n            auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n            placed.push_back({p.p, rw, rh, x, y});\n        }\n        auto [W, H] = getBoundingBox(placed);\n        best_score = W + H;\n        \n        // Try different strategies\n        for (int s = 1; s <= 3; s++) {\n            vector<Placement> cur = greedyPlacement(s, s == 2);\n            placed.clear();\n            for (const auto& p : cur) {\n                int rw = p.r ? wh[p.p].second : wh[p.p].first;\n                int rh = p.r ? wh[p.p].first : wh[p.p].second;\n                auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n                placed.push_back({p.p, rw, rh, x, y});\n            }\n            auto [W, H] = getBoundingBox(placed);\n            int score = W + H;\n            \n            if (score < best_score) {\n                best_score = score;\n                best = cur;\n            }\n        }\n        \n        // Try with some random variations\n        for (int iter = 0; iter < 5; iter++) {\n            vector<Placement> cur = greedyPlacement(0);\n            // Randomly modify some placements\n            for (int i = 0; i < (int)cur.size(); i++) {\n                if (rng() % 3 == 0) {\n                    cur[i].r ^= 1;\n                }\n            }\n            \n            placed.clear();\n            for (const auto& p : cur) {\n                int rw = p.r ? wh[p.p].second : wh[p.p].first;\n                int rh = p.r ? wh[p.p].first : wh[p.p].second;\n                auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n                placed.push_back({p.p, rw, rh, x, y});\n            }\n            auto [W, H] = getBoundingBox(placed);\n            int score = W + H;\n            \n            if (score < best_score) {\n                best_score = score;\n                best = cur;\n            }\n        }\n        \n        return best;\n    }\n    \npublic:\n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void solve() {\n        cin >> N >> T >> sigma;\n        wh.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> wh[i].first >> wh[i].second;\n        }\n        \n        // Track time to avoid TLE\n        auto startTime = chrono::steady_clock::now();\n        const double MAX_TIME = 2.8; // Leave margin for system test\n        \n        for (int t = 0; t < T; t++) {\n            // Check time limit\n            auto currentTime = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed > MAX_TIME) break;\n            \n            // Find best placement\n            vector<Placement> placements = findBestPlacement();\n            \n            // Output placements\n            cout << placements.size() << \"\\n\";\n            for (const auto& p : placements) {\n                cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n            }\n            cout.flush();\n            \n            // Read feedback\n            int W, H;\n            cin >> W >> H;\n            \n            // Track best solution\n            if (W + H < best_W + best_H) {\n                best_W = W;\n                best_H = H;\n                best_placements = placements;\n            }\n            \n            // Optional: Output debug info\n            // cout << \"# Turn \" << t+1 << \" W=\" << W << \" H=\" << H << \" Score=\" << W+H << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.solve();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Global buffers to avoid reallocation overhead\nconst int MAXN = 1005;\nvector<int> adj[MAXN];\nint A[MAXN];\nint L[MAXN];\nint pc[MAXN]; // parent count: number of neighbors u with L[u] == L[v] - 1\nint p[MAXN];  // output parent array\nint x[MAXN], y[MAXN];\n\nvoid solve() {\n    int N, M, H;\n    // Read until EOF\n    while (cin >> N >> M >> H) {\n        // Read Beauty values\n        for (int i = 0; i < N; ++i) {\n            cin >> A[i];\n        }\n        // Read Edges\n        for (int i = 0; i < M; ++i) {\n            int u, v;\n            cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // Read Coordinates (ignored but must be read)\n        for (int i = 0; i < N; ++i) {\n            cin >> x[i] >> y[i];\n        }\n\n        // Initialize State\n        // L[v] = 0 for all v\n        // pc[v] = 0 for all v\n        for (int i = 0; i < N; ++i) {\n            adj[i].clear();\n            L[i] = 0;\n            pc[i] = 0;\n        }\n\n        // Random number generator\n        static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_int_distribution<int> dist_idx(0, N - 1);\n        uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n        // Simulated Annealing\n        // Parameters tuned for 150 test cases in 2.0s\n        // Approx 13ms per case.\n        // We aim for ~500-800 iterations per case.\n        int iterations = 600;\n        double T = 500.0;\n        double decay = 0.95;\n\n        long long current_score = 0;\n        // Initial score is 0 since L[v]=0 -> sum (0+1)*A[v] = sum A[v]\n        // But we maximize sum L[v]*A[v].\n        // Let's track sum L[v]*A[v] as score.\n        // Actually, we can track sum (L[v]+1)*A[v] but constant offset doesn't matter.\n        // Let's track sum L[v]*A[v].\n        \n        // Wait, initial L is all 0, so score is 0.\n        \n        for (int iter = 0; iter < iterations; ++iter) {\n            // Pick random vertex\n            int v = dist_idx(rng);\n            \n            // Try to change L[v]\n            // Options: L[v] + 1 (if < H), L[v] - 1 (if > 0)\n            // We prefer increasing if possible, but SA allows decreasing.\n            \n            int old_L = L[v];\n            int best_new_L = -1;\n            long long best_delta = -1e18;\n            \n            // Candidate moves\n            vector<int> candidates;\n            if (old_L < H) candidates.push_back(old_L + 1);\n            if (old_L > 0) candidates.push_back(old_L - 1);\n            \n            // Shuffle candidates to avoid bias\n            shuffle(candidates.begin(), candidates.end(), rng);\n            \n            bool move_accepted = false;\n            \n            for (int new_L : candidates) {\n                if (new_L == old_L) continue;\n                \n                // Check validity\n                bool valid = true;\n                \n                // 1. Check v's own parent requirement\n                if (new_L > 0) {\n                    bool has_parent = false;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L - 1) {\n                            has_parent = true;\n                            break;\n                        }\n                    }\n                    if (!has_parent) valid = false;\n                }\n                \n                // 2. Check neighbors' parent count requirement\n                // If L[v] changes from old to new:\n                // - Neighbors u with L[u] == old + 1 lose v as parent.\n                // - Neighbors u with L[u] == new + 1 gain v as parent.\n                \n                if (valid) {\n                    for (int u : adj[v]) {\n                        if (L[u] == old_L + 1) {\n                            // v was a parent, now not\n                            if (pc[u] == 1) {\n                                valid = false;\n                                break;\n                            }\n                        }\n                        if (L[u] == new_L + 1) {\n                            // v becomes a parent, pc[u] increases, no risk\n                        }\n                    }\n                }\n                \n                if (valid) {\n                    long long delta = (long long)(new_L - old_L) * A[v];\n                    // Calculate acceptance probability\n                    double prob = 1.0;\n                    if (delta < 0) {\n                        prob = exp((double)delta / T);\n                    }\n                    \n                    if (dist_prob(rng) < prob) {\n                        // Accept move\n                        L[v] = new_L;\n                        current_score += delta;\n                        \n                        // Update pc for neighbors\n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                pc[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                pc[u]++;\n                            }\n                        }\n                        move_accepted = true;\n                        break; // Accept first valid move\n                    }\n                }\n            }\n            \n            // Cool down\n            T *= decay;\n        }\n\n        // Construct parent array\n        for (int i = 0; i < N; ++i) {\n            if (L[i] == 0) {\n                p[i] = -1;\n            } else {\n                // Find a neighbor with L[u] == L[i] - 1\n                int parent = -1;\n                for (int u : adj[i]) {\n                    if (L[u] == L[i] - 1) {\n                        parent = u;\n                        break;\n                    }\n                }\n                p[i] = parent;\n            }\n        }\n\n        // Output\n        for (int i = 0; i < N; ++i) {\n            cout << p[i] << (i == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\n// Structure to represent a move\nstruct Move {\n    char d;\n    int p;\n};\n\n// Structure to represent a candidate move\nstruct Candidate {\n    int cost;\n    int oni_removed;\n    char d;\n    int p;\n    int shift_amount;\n};\n\nint N;\nvector<string> board;\nvector<Move> moves;\n\n// Count total Oni on the board\nint count_oni() {\n    int c = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\n// Get position of the first Fuku in a specific direction\n// Returns N if no Fuku found (for left/up), -1 if no Fuku found (for right/down)\nint get_first_fuku_row_left(int r) {\n    for (int j = 0; j < N; ++j) {\n        if (board[r][j] == 'o') return j;\n    }\n    return N;\n}\n\nint get_first_fuku_row_right(int r) {\n    for (int j = N - 1; j >= 0; --j) {\n        if (board[r][j] == 'o') return j;\n    }\n    return -1;\n}\n\nint get_first_fuku_col_up(int c) {\n    for (int i = 0; i < N; ++i) {\n        if (board[i][c] == 'o') return i;\n    }\n    return N;\n}\n\nint get_first_fuku_col_down(int c) {\n    for (int i = N - 1; i >= 0; --i) {\n        if (board[i][c] == 'o') return i;\n    }\n    return -1;\n}\n\n// Apply a shift operation k times\nvoid apply_move(char d, int p, int k) {\n    for (int step = 0; step < k; ++step) {\n        if (d == 'L') {\n            moves.push_back({'L', p});\n            for (int j = 0; j < N - 1; ++j) {\n                board[p][j] = board[p][j + 1];\n            }\n            board[p][N - 1] = '.';\n        } else if (d == 'R') {\n            moves.push_back({'R', p});\n            for (int j = N - 1; j > 0; --j) {\n                board[p][j] = board[p][j - 1];\n            }\n            board[p][0] = '.';\n        } else if (d == 'U') {\n            moves.push_back({'U', p});\n            for (int i = 0; i < N - 1; ++i) {\n                board[i][p] = board[i + 1][p];\n            }\n            board[N - 1][p] = '.';\n        } else if (d == 'D') {\n            moves.push_back({'D', p});\n            for (int i = N - 1; i > 0; --i) {\n                board[i][p] = board[i - 1][p];\n            }\n            board[0][p] = '.';\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n    board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> board[i];\n    }\n\n    // Greedy strategy to remove Oni\n    while (count_oni() > 0) {\n        Candidate best;\n        best.cost = 1e9;\n        best.oni_removed = 0;\n        best.shift_amount = 0;\n        bool found = false;\n\n        // Check Rows\n        for (int r = 0; r < N; ++r) {\n            // Left direction\n            int fuku_pos = get_first_fuku_row_left(r);\n            vector<int> oni_pos;\n            for (int j = 0; j < N; ++j) {\n                if (board[r][j] == 'x') oni_pos.push_back(j);\n            }\n            for (int p : oni_pos) {\n                if (p < fuku_pos) {\n                    int k = p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op < k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'L', r, k};\n                        found = true;\n                    }\n                } else {\n                    break; \n                }\n            }\n\n            // Right direction\n            fuku_pos = get_first_fuku_row_right(r);\n            oni_pos.clear();\n            for (int j = N - 1; j >= 0; --j) {\n                if (board[r][j] == 'x') oni_pos.push_back(j);\n            }\n            // oni_pos is sorted descending\n            for (int p : oni_pos) {\n                if (p > fuku_pos) {\n                    int k = (N - 1) - p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op > (N - 1) - k) benefit++; // op >= N - k\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'R', r, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n        }\n\n        // Check Cols\n        for (int c = 0; c < N; ++c) {\n            // Up direction\n            int fuku_pos = get_first_fuku_col_up(c);\n            vector<int> oni_pos;\n            for (int i = 0; i < N; ++i) {\n                if (board[i][c] == 'x') oni_pos.push_back(i);\n            }\n            for (int p : oni_pos) {\n                if (p < fuku_pos) {\n                    int k = p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op < k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'U', c, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n\n            // Down direction\n            fuku_pos = get_first_fuku_col_down(c);\n            oni_pos.clear();\n            for (int i = N - 1; i >= 0; --i) {\n                if (board[i][c] == 'x') oni_pos.push_back(i);\n            }\n            for (int p : oni_pos) {\n                if (p > fuku_pos) {\n                    int k = (N - 1) - p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op > (N - 1) - k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'D', c, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (!found) {\n            // If no valid move is found, we cannot proceed safely.\n            // This should theoretically not happen given the problem constraints.\n            break;\n        }\n\n        apply_move(best.d, best.p, best.shift_amount);\n    }\n\n    for (const auto& m : moves) {\n        cout << m.d << \" \" << m.p << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables to store problem data and state\nint N, L;\nint T[105];\nint A[105], B[105];\nint current_cnt[105];\n\n// Function to simulate the cleaning process and calculate error\nlong long evaluate() {\n    // Reset counts\n    memset(current_cnt, 0, sizeof(current_cnt));\n    int cur = 0;\n    for(int w=0; w<L; ++w) {\n        current_cnt[cur]++;\n        // If count is odd, go to A[cur], else B[cur]\n        if (current_cnt[cur] & 1) cur = A[cur];\n        else cur = B[cur];\n    }\n    // Calculate total absolute error\n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(current_cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // Initialize RNG\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_node(0, N-1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Initialization based on target frequencies T[i]\n    // We want to distribute 2*N edges such that in-degree of i is proportional to T[i]\n    vector<int> targets;\n    targets.reserve(2 * N);\n    vector<int> base_counts(N, 0);\n    long long distributed = 0;\n    for(int i=0; i<N; ++i) {\n        long long k = (2LL * N * T[i]) / L;\n        base_counts[i] = k;\n        distributed += k;\n    }\n    long long remainder = 2 * N - distributed;\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    // Sort indices by T[i] descending to distribute remainder\n    sort(p.begin(), p.end(), [&](int i, int j){\n        return T[i] > T[j];\n    });\n    for(int i=0; i<remainder && i<N; ++i) {\n        base_counts[p[i]]++;\n    }\n    for(int i=0; i<N; ++i) {\n        for(int k=0; k<base_counts[i]; ++k) {\n            targets.push_back(i);\n        }\n    }\n    // Shuffle to avoid deterministic structure\n    shuffle(targets.begin(), targets.end(), rng);\n    // Assign A and B\n    for(int i=0; i<N; ++i) {\n        A[i] = targets[2*i];\n        B[i] = targets[2*i+1];\n    }\n\n    // Initial evaluation\n    long long current_err = evaluate();\n    long long best_err = current_err;\n    vector<int> best_A(N), best_B(N);\n    for(int i=0; i<N; ++i) {\n        best_A[i] = A[i];\n        best_B[i] = B[i];\n    }\n\n    // Simulated Annealing parameters\n    double temp = 1e7;\n    double cooling = 0.999;\n    \n    // Time limit handling\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Save current counts for potential revert\n        vector<int> saved_cnt(N);\n        for(int i=0; i<N; ++i) saved_cnt[i] = current_cnt[i];\n        \n        // Pick node u to modify (biased by error)\n        int u = dist_node(rng);\n        long long total_err = 0;\n        for(int i=0; i<N; ++i) total_err += abs(current_cnt[i] - T[i]);\n        if (total_err > 0) {\n            long long r = rng() % total_err;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = abs(current_cnt[i] - T[i]);\n                sum += w;\n                if (sum > r) {\n                    u = i;\n                    break;\n                }\n            }\n        }\n\n        // Pick target node v (biased by need)\n        int v = dist_node(rng);\n        long long total_need = 0;\n        for(int i=0; i<N; ++i) {\n            if (T[i] > current_cnt[i]) total_need += (T[i] - current_cnt[i]);\n        }\n        if (total_need > 0) {\n            long long r = rng() % total_need;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = max(0, T[i] - current_cnt[i]);\n                sum += w;\n                if (sum > r) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n\n        // Propose change: modify A[u] or B[u]\n        int edge_type = dist_node(rng) % 2;\n        int old_target = (edge_type == 0) ? A[u] : B[u];\n        \n        if (edge_type == 0) A[u] = v;\n        else B[u] = v;\n\n        // Evaluate new state\n        long long new_err = evaluate();\n        \n        // Acceptance probability\n        double delta = new_err - current_err;\n        double prob = exp(-delta / temp);\n        \n        if (delta < 0 || dist_prob(rng) < prob) {\n            current_err = new_err;\n            if (current_err < best_err) {\n                best_err = current_err;\n                for(int i=0; i<N; ++i) {\n                    best_A[i] = A[i];\n                    best_B[i] = B[i];\n                }\n            }\n        } else {\n            // Revert change\n            if (edge_type == 0) A[u] = old_target;\n            else B[u] = old_target;\n            // Restore counts\n            for(int i=0; i<N; ++i) current_cnt[i] = saved_cnt[i];\n        }\n        \n        // Cool down\n        temp *= cooling;\n        if (temp < 1e-3) temp = 1e-3;\n    }\n\n    // Output best solution\n    for(int i=0; i<N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Structure to represent a city\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    double cx, cy; // Estimated center coordinates\n};\n\n// Structure to represent an edge\nstruct Edge {\n    int u, v;\n    int dist;\n    bool operator<(const Edge& other) const {\n        if (dist != other.dist) return dist < other.dist;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\n// Union-Find data structure\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) {\n            parent[rootX] = rootY;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<City> cities;\nvector<vector<int>> groups; // groups[i] contains list of city IDs for group i\nint query_cnt = 0;\n\n// Calculate estimated distance between two cities\nint calc_dist(int i, int j) {\n    double dx = cities[i].cx - cities[j].cx;\n    double dy = cities[i].cy - cities[j].cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Function to perform a query\nvoid perform_query(const vector<int>& subset) {\n    if (query_cnt >= Q) return;\n    cout << \"? \" << subset.size();\n    for (int id : subset) {\n        cout << \" \" << id;\n    }\n    cout << endl;\n    query_cnt++;\n}\n\n// Function to read query response\nvector<pair<int, int>> read_query_response(int size) {\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < size - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.push_back({u, v});\n    }\n    return edges;\n}\n\n// Function to build MST for a group using estimated distances\n// Returns vector of edges\nvector<pair<int, int>> build_estimated_mst(const vector<int>& group) {\n    vector<Edge> all_edges;\n    int sz = group.size();\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = calc_dist(u, v);\n            all_edges.push_back({u, v, d});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n\n    DSU dsu(N); // We can use global DSU or local, local is safer for reset\n    // Actually, DSU should be local to the group size, but mapping IDs is needed.\n    // Since N is small, we can use a DSU of size N and only unite relevant nodes.\n    // But we need to reset it. Let's use a map or just a vector of size N.\n    // To avoid O(N) reset, we can use a versioned DSU or just reset the used nodes.\n    // Given N=800, O(N) reset is fine.\n    \n    // Re-implement DSU locally for this group to avoid global state issues\n    vector<int> p(sz);\n    iota(p.begin(), p.end(), 0);\n    auto find = [&](int x, auto&& find_ref) -> int {\n        if (p[x] == x) return x;\n        return p[x] = find_ref(p[x], find_ref);\n    };\n    auto unite = [&](int x, int y) -> bool {\n        int rx = find(x, find);\n        int ry = find(y, find);\n        if (rx != ry) {\n            p[rx] = ry;\n            return true;\n        }\n        return false;\n    };\n\n    vector<pair<int, int>> mst_edges;\n    for (const auto& e : all_edges) {\n        int u_idx = -1, v_idx = -1;\n        // Find indices in group\n        // Since group is small, linear scan is okay, but we can pre-map.\n        // For simplicity, let's map IDs to indices 0..sz-1\n        // Actually, we can just use the global IDs in DSU if we reset properly.\n        // Let's use a local DSU with size N, but only touch group nodes.\n    }\n    \n    // Better DSU approach for this function:\n    // Use a vector<int> parent(N, -1). Initialize with -1.\n    // When accessing node u, if parent[u] == -1, parent[u] = u.\n    // This avoids O(N) reset.\n    \n    vector<int> parent(N, -1);\n    auto find_local = [&](int x) -> int {\n        if (parent[x] == -1) parent[x] = x;\n        if (parent[x] == x) return x;\n        return parent[x] = find_local(parent[x]);\n    };\n    auto unite_local = [&](int x, int y) -> bool {\n        int rx = find_local(x);\n        int ry = find_local(y);\n        if (rx != ry) {\n            parent[rx] = ry;\n            return true;\n        }\n        return false;\n    };\n\n    for (const auto& e : all_edges) {\n        if (unite_local(e.u, e.v)) {\n            mst_edges.push_back({e.u, e.v});\n            if (mst_edges.size() == sz - 1) break;\n        }\n    }\n    return mst_edges;\n}\n\n// Function to calculate estimated MST cost for a group\nint calc_estimated_cost(const vector<int>& group) {\n    int sz = group.size();\n    if (sz <= 1) return 0;\n    vector<Edge> all_edges;\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = calc_dist(u, v);\n            all_edges.push_back({u, v, d});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n    \n    // Simple DSU\n    vector<int> p(sz);\n    iota(p.begin(), p.end(), 0);\n    auto find = [&](int x, auto&& find_ref) -> int {\n        if (p[x] == x) return x;\n        return p[x] = find_ref(p[x], find_ref);\n    };\n    auto unite = [&](int x, int y) -> bool {\n        int rx = find(x, find);\n        int ry = find(y, find);\n        if (rx != ry) {\n            p[rx] = ry;\n            return true;\n        }\n        return false;\n    };\n    \n    int cost = 0;\n    int edges = 0;\n    for (const auto& e : all_edges) {\n        // Map global IDs to local indices\n        // This is slow if done naively.\n        // Since we just need cost, we can use a map or just search.\n        // Given small group size, search is okay.\n        int u_idx = -1, v_idx = -1;\n        for(int k=0; k<sz; ++k) { if(group[k] == e.u) u_idx = k; if(group[k] == e.v) v_idx = k; }\n        \n        if (unite(u_idx, v_idx)) {\n            cost += e.dist;\n            edges++;\n        }\n    }\n    return cost;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2.0;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2.0;\n    }\n\n    // Sort cities by X then Y to form spatially contiguous groups\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (cities[a].cx != cities[b].cx) return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n\n    // Assign cities to groups\n    groups.resize(M);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(p[current_idx++]);\n        }\n    }\n\n    // Local Search Optimization: Swap boundary cities between adjacent groups\n    // Run for a few iterations\n    int iterations = 5;\n    auto start_time = chrono::high_resolution_clock::now();\n    auto time_limit = chrono::high_resolution_clock::now() + chrono::milliseconds(1900);\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        bool improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            // Try swapping last of group i with first of group i+1\n            if (groups[i].empty() || groups[i+1].empty()) continue;\n            \n            int u = groups[i].back();\n            int v = groups[i+1].front();\n            \n            // Calculate cost before swap\n            int cost_before = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            // Swap\n            swap(groups[i].back(), groups[i+1].front());\n            \n            // Calculate cost after swap\n            int cost_after = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            if (cost_after < cost_before) {\n                improved = true;\n            } else {\n                // Revert\n                swap(groups[i].back(), groups[i+1].front());\n            }\n        }\n        if (!improved) break;\n        \n        auto now = chrono::high_resolution_clock::now();\n        if (now > time_limit) break;\n    }\n\n    // Query Phase\n    // Priority 1: Groups with 3 <= size <= L\n    // Priority 2: Large groups (size > L), query subsets\n    \n    vector<vector<pair<int, int>>> group_mst_edges(M);\n    vector<bool> group_queried(M, false);\n\n    // 1. Query small groups\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] >= 3 && G[i] <= L) {\n            perform_query(groups[i]);\n            group_mst_edges[i] = read_query_response(G[i]);\n            group_queried[i] = true;\n        }\n    }\n\n    // 2. Query subsets of large groups\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] > L) {\n            // Query disjoint subsets of size L\n            for (int start = 0; start < G[i]; start += L) {\n                if (query_cnt >= Q) break;\n                int end = min(start + L, G[i]);\n                if (end - start < 2) continue; // Need at least 2 cities\n                \n                vector<int> subset;\n                for (int k = start; k < end; ++k) {\n                    subset.push_back(groups[i][k]);\n                }\n                \n                perform_query(subset);\n                vector<pair<int, int>> sub_edges = read_query_response(end - start);\n                \n                // Add these edges to the group's edge list\n                // We will merge them later with estimated edges\n                for (auto& e : sub_edges) {\n                    group_mst_edges[i].push_back(e);\n                }\n            }\n        }\n    }\n\n    // Final Output\n    cout << \"!\" << endl;\n\n    for (int i = 0; i < M; ++i) {\n        // Output cities\n        for (int j = 0; j < G[i]; ++j) {\n            cout << groups[i][j] << (j == G[i] - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n\n        // Output edges\n        if (G[i] <= 1) continue;\n\n        // If we have queried edges, we should prioritize them.\n        // But we need to form a connected graph of size G[i].\n        // Strategy:\n        // 1. Start with queried edges (if any).\n        // 2. Add estimated edges to complete the MST.\n        \n        vector<pair<int, int>> final_edges;\n        \n        if (!group_mst_edges[i].empty()) {\n            // Use queried edges. They are guaranteed to be part of the true MST for the subset.\n            // However, they might form cycles if we add estimated edges carelessly?\n            // No, queried edges are from a subset. They form a forest.\n            // We should include them.\n            // But we need to ensure we don't exceed G[i]-1 edges.\n            // And ensure connectivity.\n            \n            // Let's run Kruskal's including queried edges with weight 0 (or very high priority).\n            // But queried edges are exact. Estimated edges are estimates.\n            // We should prefer queried edges.\n            \n            // Create edge list\n            vector<Edge> all_edges;\n            \n            // Add queried edges with weight 0 (to prioritize)\n            // Wait, if we set weight 0, Kruskal's picks them first.\n            // But we must ensure they don't form cycles with other queried edges.\n            // The query response is an MST for the subset, so it's a tree (no cycles).\n            // But if we query multiple subsets, they might overlap and form cycles.\n            // So we need to run Kruskal's on ALL edges (queried + estimated).\n            // Queried edges get weight 0. Estimated edges get estimated weight.\n            \n            for (auto& e : group_mst_edges[i]) {\n                all_edges.push_back({e.first, e.second, 0});\n            }\n            \n            // Add estimated edges\n            int sz = G[i];\n            for (int u_idx = 0; u_idx < sz; ++u_idx) {\n                for (int v_idx = u_idx + 1; v_idx < sz; ++v_idx) {\n                    int u = groups[i][u_idx];\n                    int v = groups[i][v_idx];\n                    // Check if already added as queried edge?\n                    // To avoid duplicates, we can check.\n                    // Or just let Kruskal's handle it (duplicate edges with different weights).\n                    // If queried edge exists, it has weight 0. Estimated has weight > 0.\n                    // Kruskal's will pick weight 0 first.\n                    // So duplicates are fine.\n                    int d = calc_dist(u, v);\n                    all_edges.push_back({u, v, d});\n                }\n            }\n            \n            sort(all_edges.begin(), all_edges.end());\n            \n            // DSU\n            vector<int> p(sz);\n            iota(p.begin(), p.end(), 0);\n            auto find = [&](int x, auto&& find_ref) -> int {\n                if (p[x] == x) return x;\n                return p[x] = find_ref(p[x], find_ref);\n            };\n            auto unite = [&](int x, int y) -> bool {\n                int rx = find(x, find);\n                int ry = find(y, find);\n                if (rx != ry) {\n                    p[rx] = ry;\n                    return true;\n                }\n                return false;\n            };\n            \n            int edges_count = 0;\n            for (const auto& e : all_edges) {\n                // Map global IDs to local indices\n                int u_idx = -1, v_idx = -1;\n                for(int k=0; k<sz; ++k) { if(groups[i][k] == e.u) u_idx = k; if(groups[i][k] == e.v) v_idx = k; }\n                \n                if (unite(u_idx, v_idx)) {\n                    final_edges.push_back({e.u, e.v});\n                    edges_count++;\n                    if (edges_count == sz - 1) break;\n                }\n            }\n        } else {\n            // No queried edges, use estimated MST\n            final_edges = build_estimated_mst(groups[i]);\n        }\n        \n        for (const auto& e : final_edges) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 20;\nconst int M = 40;\n\n// Directions\nconst int dx[] = {-1, 1, 0, 0};  // U, D, L, R\nconst int dy[] = {0, 0, -1, 1};\nconst char dirChar[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nclass SkatingSolver {\nprivate:\n    int n;\n    vector<Point> targets;\n    Point currentPos;\n    vector<vector<bool>> blocks;\n    vector<pair<char, char>> actions;\n    int actionCount = 0;\n    \n    // Check if position is valid\n    bool isValid(int x, int y) const {\n        return x >= 0 && x < n && y >= 0 && y < n;\n    }\n    \n    // Check if position has a block\n    bool hasBlock(int x, int y) const {\n        return isValid(x, y) && blocks[x][y];\n    }\n    \n    // Execute an action and return new position\n    Point executeAction(char action, char dir) {\n        int d = 0;\n        if (dir == 'U') d = 0;\n        else if (dir == 'D') d = 1;\n        else if (dir == 'L') d = 2;\n        else if (dir == 'R') d = 3;\n        \n        Point newPos = currentPos;\n        \n        if (action == 'M') {\n            // Move one square\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (isValid(nx, ny) && !hasBlock(nx, ny)) {\n                newPos = {nx, ny};\n            }\n        } else if (action == 'S') {\n            // Slide until hitting a block\n            int x = currentPos.x;\n            int y = currentPos.y;\n            while (true) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                    break;\n                }\n                x = nx;\n                y = ny;\n            }\n            newPos = {x, y};\n        } else if (action == 'A') {\n            // Alter block on adjacent square\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (isValid(nx, ny)) {\n                blocks[nx][ny] = !blocks[nx][ny];\n            }\n        }\n        \n        currentPos = newPos;\n        return newPos;\n    }\n    \n    // Find shortest path to target using BFS with block manipulation\n    vector<pair<char, char>> findPathToTarget(Point target) {\n        vector<pair<char, char>> path;\n        \n        // Try sliding first in each direction\n        for (int d = 0; d < 4; d++) {\n            int x = currentPos.x;\n            int y = currentPos.y;\n            bool canSlideToTarget = false;\n            \n            // Check if sliding in this direction can reach target\n            while (true) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                if (!isValid(nx, ny)) break;\n                \n                if (nx == target.x && ny == target.y) {\n                    canSlideToTarget = true;\n                    break;\n                }\n                \n                if (hasBlock(nx, ny)) break;\n                x = nx;\n                y = ny;\n            }\n            \n            if (canSlideToTarget) {\n                // Place block after target to stop slide\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                if (isValid(stopX, stopY) && !hasBlock(stopX, stopY)) {\n                    path.push_back({'A', dirChar[d]});\n                    blocks[stopX][stopY] = true;\n                }\n                \n                path.push_back({'S', dirChar[d]});\n                currentPos = target;\n                \n                // Remove block after visiting\n                if (isValid(stopX, stopY)) {\n                    path.push_back({'A', dirChar[d]});\n                    blocks[stopX][stopY] = false;\n                }\n                \n                return path;\n            }\n        }\n        \n        // BFS to find path with minimal moves\n        using State = tuple<int, int, int>; // x, y, dist\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                // Reconstruct path\n                vector<pair<int, int>> pathPoints;\n                int cx = x, cy = y;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    pathPoints.push_back({cx, cy});\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                // Convert to actions\n                for (int i = pathPoints.size() - 1; i >= 0; i--) {\n                    int nx = pathPoints[i].first;\n                    int ny = pathPoints[i].second;\n                    int prevX = (i == 0) ? target.x : pathPoints[i-1].first;\n                    int prevY = (i == 0) ? target.y : pathPoints[i-1].second;\n                    \n                    int dx = nx - prevX;\n                    int dy = ny - prevY;\n                    \n                    if (dx == -1) path.push_back({'M', 'U'});\n                    else if (dx == 1) path.push_back({'M', 'D'});\n                    else if (dy == -1) path.push_back({'M', 'L'});\n                    else if (dy == 1) path.push_back({'M', 'R'});\n                }\n                \n                currentPos = target;\n                return path;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return path;\n    }\n    \n    // Optimized pathfinding with sliding\n    vector<pair<char, char>> findOptimalPath(Point target) {\n        vector<pair<char, char>> path;\n        \n        // Check if we can slide directly to target\n        for (int d = 0; d < 4; d++) {\n            int x = currentPos.x;\n            int y = currentPos.y;\n            bool canReach = false;\n            \n            while (true) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                if (!isValid(nx, ny)) break;\n                \n                if (nx == target.x && ny == target.y) {\n                    canReach = true;\n                    break;\n                }\n                \n                if (hasBlock(nx, ny)) break;\n                x = nx;\n                y = ny;\n            }\n            \n            if (canReach) {\n                // Place block after target\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                if (isValid(stopX, stopY)) {\n                    if (!hasBlock(stopX, stopY)) {\n                        path.push_back({'A', dirChar[d]});\n                        blocks[stopX][stopY] = true;\n                    }\n                    \n                    path.push_back({'S', dirChar[d]});\n                    currentPos = target;\n                    \n                    if (hasBlock(stopX, stopY)) {\n                        path.push_back({'A', dirChar[d]});\n                        blocks[stopX][stopY] = false;\n                    }\n                } else {\n                    path.push_back({'S', dirChar[d]});\n                    currentPos = target;\n                }\n                \n                return path;\n            }\n        }\n        \n        // BFS with limited depth for move-only path\n        using State = tuple<int, int, int>;\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                vector<pair<int, int>> pathPoints;\n                int cx = x, cy = y;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    pathPoints.push_back({cx, cy});\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                for (int i = pathPoints.size() - 1; i >= 0; i--) {\n                    int nx = pathPoints[i].first;\n                    int ny = pathPoints[i].second;\n                    int prevX = (i == 0) ? target.x : pathPoints[i-1].first;\n                    int prevY = (i == 0) ? target.y : pathPoints[i-1].second;\n                    \n                    int dx = nx - prevX;\n                    int dy = ny - prevY;\n                    \n                    if (dx == -1) path.push_back({'M', 'U'});\n                    else if (dx == 1) path.push_back({'M', 'D'});\n                    else if (dy == -1) path.push_back({'M', 'L'});\n                    else if (dy == 1) path.push_back({'M', 'R'});\n                }\n                \n                currentPos = target;\n                return path;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return path;\n    }\n\npublic:\n    SkatingSolver(int n) : n(n) {\n        blocks.assign(n, vector<bool>(n, false));\n    }\n    \n    void setInitialPosition(int x, int y) {\n        currentPos = {x, y};\n    }\n    \n    void addTarget(int x, int y) {\n        targets.push_back({x, y});\n    }\n    \n    void solve() {\n        for (const auto& target : targets) {\n            if (actionCount >= 2 * N * M) break;\n            \n            auto path = findOptimalPath(target);\n            \n            for (const auto& action : path) {\n                if (actionCount >= 2 * N * M) break;\n                \n                executeAction(action.first, action.second);\n                actions.push_back(action);\n                actionCount++;\n            }\n        }\n    }\n    \n    void output() const {\n        for (const auto& action : actions) {\n            cout << action.first << \" \" << action.second << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    SkatingSolver solver(n);\n    \n    int x, y;\n    cin >> x >> y;\n    solver.setInitialPosition(x, y);\n    \n    for (int i = 0; i < m; i++) {\n        cin >> x >> y;\n        solver.addTarget(x, y);\n    }\n    \n    solver.solve();\n    solver.output();\n    \n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\ndouble calculate_p(int r, int s) {\n    if (s == 0) return 0.0;\n    double ratio = (double)min(r, s) / max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble calculate_total_p(const vector<Company>& companies) {\n    double total = 0;\n    for (auto& c : companies) {\n        int s = (c.c - c.a) * (c.d - c.b);\n        total += calculate_p(c.r, s);\n    }\n    return total;\n}\n\nbool can_place(const vector<tuple<int, int, int, int>>& placed, int a, int b, int c, int d) {\n    for (auto& [pa, pb, pc, pd] : placed) {\n        if (!(c <= pa || a >= pc || d <= pb || b >= pd)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid place_rectangles(vector<Company>& companies, const vector<int>& order) {\n    vector<tuple<int, int, int, int>> placed;\n    \n    for (int idx : order) {\n        int x = companies[idx].x;\n        int y = companies[idx].y;\n        int r = companies[idx].r;\n        \n        // Find all dimension pairs (w, h) such that w * h = r\n        vector<pair<int, int>> dims;\n        for (int w = 1; w * w <= r; w++) {\n            if (r % w == 0) {\n                dims.push_back({w, r / w});\n                if (w * w != r) {\n                    dims.push_back({r / w, w});\n                }\n            }\n        }\n        \n        // Prefer more square-like rectangles (better packing)\n        sort(dims.begin(), dims.end(), [](auto& p1, auto& p2) {\n            return abs(p1.first - p1.second) < abs(p2.first - p2.second);\n        });\n        \n        bool placed_rect = false;\n        for (auto [w, h] : dims) {\n            // Try all positions that contain (x, y)\n            for (int offset_x = 0; offset_x < w && !placed_rect; offset_x++) {\n                for (int offset_y = 0; offset_y < h && !placed_rect; offset_y++) {\n                    int a = x - offset_x;\n                    int b = y - offset_y;\n                    int c = a + w;\n                    int d = b + h;\n                    \n                    if (a >= 0 && c <= 10000 && b >= 0 && d <= 10000) {\n                        if (can_place(placed, a, b, c, d)) {\n                            companies[idx].a = a;\n                            companies[idx].b = b;\n                            companies[idx].c = c;\n                            companies[idx].d = d;\n                            placed.emplace_back(a, b, c, d);\n                            placed_rect = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        companies[i].a = 0;\n        companies[i].b = 0;\n        companies[i].c = 0;\n        companies[i].d = 0;\n    }\n    \n    vector<Company> best_companies = companies;\n    double best_p = -1;\n    \n    // Strategy 1: Sort by r (largest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r > current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 2: Sort by position (x then y)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].x != current[j].x) return current[i].x < current[j].x;\n            return current[i].y < current[j].y;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 3: Sort by position (y then x)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].y != current[j].y) return current[i].y < current[j].y;\n            return current[i].x < current[j].x;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 4: Random order (multiple times)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 100; trial++) {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 5: Sort by r (smallest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r < current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 6: Sort by distance from center\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 7: Sort by r * distance from center (combined heuristic)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            if (current[i].r != current[j].r) return current[i].r > current[j].r;\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Output best solution\n    for (int i = 0; i < n; i++) {\n        cout << best_companies[i].a << \" \" << best_companies[i].b << \" \" \n             << best_companies[i].c << \" \" << best_companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\n// Global problem data\nint si, sj;\nint t[50][50];\nint p[50][50];\nint adj[50][50][4];\nint adj_count[50][50];\nchar move_char[4] = {'U', 'D', 'L', 'R'};\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\n// Path state (no copying - rollback instead)\nint path_r[2505];\nint path_c[2505];\nchar path_moves[2505];\nbool visited_tile[2505];\nint path_len;\nlong long current_score;\n\n// Best path\nint best_path_len;\nlong long best_score;\nstring best_moves;\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < 50 && c >= 0 && c < 50;\n}\n\nvoid precompute_adj() {\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            adj_count[i][j] = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (is_valid(ni, nj)) {\n                    adj[i][j][adj_count[i][j]++] = k;\n                }\n            }\n        }\n    }\n}\n\nvoid save_best() {\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_path_len = path_len;\n        best_moves.clear();\n        best_moves.reserve(path_len - 1);\n        for (int i = 0; i < path_len - 1; ++i) {\n            best_moves += path_moves[i];\n        }\n    }\n}\n\nvoid reset_visited() {\n    memset(visited_tile, 0, sizeof(visited_tile));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> t[i][j];\n        }\n    }\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    precompute_adj();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1950);\n\n    best_score = -1;\n    best_path_len = 0;\n    best_moves.clear();\n\n    // Multiple restarts with greedy + random exploration\n    int restart = 0;\n    while (chrono::steady_clock::now() < end_time && restart < 200) {\n        reset_visited();\n        path_len = 0;\n        current_score = 0;\n\n        // Start from initial position\n        path_r[0] = si;\n        path_c[0] = sj;\n        visited_tile[t[si][sj]] = true;\n        path_len = 1;\n        current_score = p[si][sj];\n\n        save_best();\n\n        // Greedy exploration with occasional backtracking\n        while (path_len > 0 && chrono::steady_clock::now() < end_time) {\n            int r = path_r[path_len - 1];\n            int c = path_c[path_len - 1];\n            \n            // Find valid neighbors\n            int valid_count = 0;\n            int valid_dirs[4];\n            int valid_vals[4];\n            for (int k = 0; k < adj_count[r][c]; ++k) {\n                int dir = adj[r][c][k];\n                int nr = r + di[dir];\n                int nc = c + dj[dir];\n                int tile = t[nr][nc];\n                if (!visited_tile[tile]) {\n                    valid_dirs[valid_count] = dir;\n                    valid_vals[valid_count] = p[nr][nc];\n                    valid_count++;\n                }\n            }\n\n            if (valid_count > 0) {\n                // Greedy bias: 80% pick highest value, 20% random\n                int chosen_idx = 0;\n                if (valid_count > 1) {\n                    int max_idx = 0;\n                    int max_val = valid_vals[0];\n                    for (int i = 1; i < valid_count; ++i) {\n                        if (valid_vals[i] > max_val) {\n                            max_val = valid_vals[i];\n                            max_idx = i;\n                        }\n                    }\n                    if (prob_dist(rng) < 0.8) {\n                        chosen_idx = max_idx;\n                    } else {\n                        chosen_idx = rng() % valid_count;\n                    }\n                }\n                \n                int chosen_dir = valid_dirs[chosen_idx];\n                int nr = r + di[chosen_dir];\n                int nc = c + dj[chosen_dir];\n                int tile = t[nr][nc];\n                \n                // Add to path\n                path_r[path_len] = nr;\n                path_c[path_len] = nc;\n                path_moves[path_len - 1] = move_char[chosen_dir];\n                visited_tile[tile] = true;\n                path_len++;\n                current_score += p[nr][nc];\n                \n                save_best();\n            } else {\n                // Backtrack: remove last step\n                if (path_len <= 1) break;\n                \n                int last_r = path_r[path_len - 1];\n                int last_c = path_c[path_len - 1];\n                int last_tile = t[last_r][last_c];\n                \n                path_len--;\n                current_score -= p[last_r][last_c];\n                visited_tile[last_tile] = false;\n            }\n        }\n        restart++;\n    }\n\n    cout << best_moves << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <string>\n#include <tuple>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst double INIT_W = 5000.0;\nconst double K = 5.0; // Blending factor for row/col average\n\n// Edge weight estimates\n// h[i][j] stores stats for horizontal edge between (i, j) and (i, j+1)\n// v[i][j] stores stats for vertical edge between (i, j) and (i+1, j)\nstruct Stats {\n    double log_sum = 0.0;\n    int cnt = 0;\n};\n\nStats h_stats[N][N]; // 30x30, though j only goes to 28\nStats v_stats[N][N]; // 30x30, though i only goes to 28\nStats h_avg_stats[N]; // Row averages\nStats v_avg_stats[N]; // Col averages\n\n// Helper to get weight from stats\ndouble get_weight(const Stats& s) {\n    if (s.cnt == 0) return INIT_W;\n    return INIT_W * exp(s.log_sum / s.cnt);\n}\n\n// Helper to get effective weight blending edge and average\ndouble get_h_weight(int i, int j) {\n    double w_edge = get_weight(h_stats[i][j]);\n    double w_avg = get_weight(h_avg_stats[i]);\n    return (h_stats[i][j].cnt * w_edge + K * w_avg) / (h_stats[i][j].cnt + K);\n}\n\ndouble get_v_weight(int i, int j) {\n    double w_edge = get_weight(v_stats[i][j]);\n    double w_avg = get_weight(v_avg_stats[j]);\n    return (v_stats[i][j].cnt * w_edge + K * w_avg) / (v_stats[i][j].cnt + K);\n}\n\n// Update stats with ratio\nvoid update_h(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    h_stats[i][j].log_sum += log(ratio);\n    h_stats[i][j].cnt++;\n    h_avg_stats[i].log_sum += log(ratio);\n    h_avg_stats[i].cnt++;\n}\n\nvoid update_v(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    v_stats[i][j].log_sum += log(ratio);\n    v_stats[i][j].cnt++;\n    v_avg_stats[j].log_sum += log(ratio);\n    v_avg_stats[j].cnt++;\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int queries = 1000;\n    for (int k = 0; k < queries; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // Dijkstra\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n        vector<vector<char>> move_dir(N, vector<char>(N, 0));\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[si][sj] = 0.0;\n        pq.push({0.0, si, sj});\n\n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        char dirs[] = {'U', 'D', 'L', 'R'};\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n\n            if (current.dist > dist[r][c]) continue;\n            if (r == ti && c == tj) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    double w = 0.0;\n                    if (d == 0) { // U: from (r, c) to (r-1, c). Edge is v[r-1][c]\n                        w = get_v_weight(nr, nc);\n                    } else if (d == 1) { // D: from (r, c) to (r+1, c). Edge is v[r][c]\n                        w = get_v_weight(r, c);\n                    } else if (d == 2) { // L: from (r, c) to (r, c-1). Edge is h[r][c-1]\n                        w = get_h_weight(r, nc);\n                    } else if (d == 3) { // R: from (r, c) to (r, c+1). Edge is h[r][c]\n                        w = get_h_weight(r, c);\n                    }\n\n                    if (dist[r][c] + w < dist[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + w;\n                        parent[nr][nc] = {r, c};\n                        move_dir[nr][nc] = dirs[d];\n                        pq.push({dist[nr][nc], nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path\n        string path = \"\";\n        int curr_r = ti, curr_c = tj;\n        double path_est = 0.0;\n        vector<pair<int, int>> path_edges_h; // Store (i, j) for h edges\n        vector<pair<int, int>> path_edges_v; // Store (i, j) for v edges\n\n        while (curr_r != si || curr_c != sj) {\n            int pr = parent[curr_r][curr_c].first;\n            int pc = parent[curr_r][curr_c].second;\n            char d = move_dir[curr_r][curr_c];\n            path += d;\n\n            // Identify edge and update estimate\n            if (d == 'U') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r + 1.\n                // Edge is v[curr_r][curr_c]\n                path_edges_v.push_back({curr_r, curr_c});\n                path_est += get_v_weight(curr_r, curr_c);\n            } else if (d == 'D') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r - 1.\n                // Edge is v[pr][pc] = v[curr_r-1][curr_c]\n                path_edges_v.push_back({pr, pc});\n                path_est += get_v_weight(pr, pc);\n            } else if (d == 'L') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c + 1.\n                // Edge is h[pr][curr_c]\n                path_edges_h.push_back({pr, curr_c});\n                path_est += get_h_weight(pr, curr_c);\n            } else if (d == 'R') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c - 1.\n                // Edge is h[pr][pc]\n                path_edges_h.push_back({pr, pc});\n                path_est += get_h_weight(pr, pc);\n            }\n\n            curr_r = pr;\n            curr_c = pc;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << endl;\n\n        // Read feedback\n        int result;\n        cin >> result;\n\n        // Update weights\n        if (path_est > 0) {\n            double ratio = (double)result / path_est;\n            if (ratio <= 0) ratio = 1.0; \n\n            for (auto& e : path_edges_h) {\n                update_h(e.first, e.second, ratio);\n            }\n            for (auto& e : path_edges_v) {\n                update_v(e.first, e.second, ratio);\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\nconst int NUM_CHARS = 8; // A-H\n\n// State\nint matrix[N][N]; // 0-7 for A-H\nint string_counts[MAX_M]; // Number of valid placements for each string\nint total_matched = 0;\nint M;\n\n// Valid placements tracking\n// valid_placements[s] is a bitset where bit k is 1 if placement k is valid for string s\n// Placement ID encoding:\n// dir (0: horiz, 1: vert) * N * N * MAX_LEN + row * N * MAX_LEN + col * MAX_LEN + offset\n// Max ID: 2 * 20 * 20 * 12 = 9600. Let's use 10000.\nbitset<10000> valid_placements[MAX_M];\n\n// cell_active[r*N+c] stores list of placements that cover this cell and are currently valid\n// To save memory and time, we store a compact representation.\n// struct PlacementInfo { int s; int id; };\n// But we need to know dir/offset to check validity.\n// We can store {s, id}. id encodes dir, row, col, offset.\nstruct PlacementInfo {\n    int s;\n    int id;\n};\nvector<PlacementInfo> cell_active[N * N];\n\n// Potential lists for fast lookup\n// potential_lists[char][cell] stores list of {s, id} that could match at this cell with this char\n// id encodes the placement details.\nvector<PlacementInfo> potential_lists[NUM_CHARS][N * N];\n\n// Helper to encode placement ID\nint encode_id(int r, int c, int dir, int offset) {\n    return dir * N * N * MAX_LEN + r * N * MAX_LEN + c * MAX_LEN + offset;\n}\n\n// Helper to decode placement ID\nvoid decode_id(int id, int &r, int &c, int &dir, int &offset) {\n    offset = id % MAX_LEN;\n    id /= MAX_LEN;\n    c = id % N;\n    id /= N;\n    r = id % N;\n    dir = id / N;\n}\n\n// Strings data\nvector<string> strings;\nvector<int> string_lens;\n\n// Random number generator\nmt19937 rng(1337);\nuniform_int_distribution<int> dist_char(0, NUM_CHARS - 1);\nuniform_int_distribution<int> dist_cell(0, N * N - 1);\n\n// Check if a placement is valid\nbool is_placement_valid(int s, int r, int c, int dir, int offset) {\n    int len = string_lens[s];\n    const string &str = strings[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) { // Horizontal\n            cr = r;\n            cc = (c + k) % N;\n        } else { // Vertical\n            cr = (r + k) % N;\n            cc = c;\n        }\n        if (matrix[cr][cc] != (str[k] - 'A')) return false;\n    }\n    return true;\n}\n\n// Add a valid placement\nvoid add_placement(int s, int r, int c, int dir, int offset) {\n    int id = encode_id(r, c, dir, offset);\n    if (valid_placements[s].test(id)) return; // Already valid\n\n    valid_placements[s].set(id);\n    string_counts[s]++;\n    if (string_counts[s] == 1) total_matched++;\n\n    // Add to cell_active for all covered cells\n    int len = string_lens[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        cell_active[cr * N + cc].push_back({s, id});\n    }\n}\n\n// Remove a valid placement (mark as invalid)\nvoid remove_placement(int s, int r, int c, int dir, int offset) {\n    int id = encode_id(r, c, dir, offset);\n    if (!valid_placements[s].test(id)) return;\n\n    valid_placements[s].reset(id);\n    string_counts[s]--;\n    if (string_counts[s] == 0) total_matched--;\n\n    // We do NOT remove from cell_active immediately to save time.\n    // Stale entries will be ignored.\n}\n\n// Initialize potential lists\nvoid init_potential_lists() {\n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        const string &str = strings[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal placements covering (r, c)\n                // Start col j such that c is in [j, j+len-1]\n                // j = (c - k) mod N for k in [0, len-1]\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_c = (c - k);\n                    if (start_c < 0) start_c += N;\n                    int id = encode_id(r, start_c, 0, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n                // Vertical placements covering (r, c)\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_r = (r - k);\n                    if (start_r < 0) start_r += N;\n                    int id = encode_id(start_r, c, 1, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n            }\n        }\n    }\n}\n\n// Initialize matrix and state\nvoid init_state() {\n    // Fill with random chars\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            matrix[i][j] = dist_char(rng);\n        }\n    }\n\n    // Find all valid placements\n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal\n                if (is_placement_valid(s, r, c, 0, 0)) {\n                    add_placement(s, r, c, 0, 0);\n                }\n                // Vertical\n                if (is_placement_valid(s, r, c, 1, 0)) {\n                    add_placement(s, r, c, 1, 0);\n                }\n            }\n        }\n    }\n}\n\n// Update cell (r, c) from old_char to new_char\n// Returns true if accepted\nbool update_cell(int r, int c, int new_char) {\n    int old_char = matrix[r][c];\n    if (old_char == new_char) return true;\n\n    int cell_idx = r * N + c;\n\n    // 1. Invalidate existing placements covering this cell\n    // We iterate a copy of cell_active to avoid modification issues\n    // But we need to be careful.\n    // We can just iterate and check.\n    // To avoid reallocation, we can swap with back for removal.\n    // But we decided to leave stale entries.\n    // So we just iterate.\n    for (auto &p : cell_active[cell_idx]) {\n        if (valid_placements[p.s].test(p.id)) {\n            // Check if this placement matches new_char\n            // We need to know the offset relative to this cell\n            // Decode id\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            \n            // Calculate relative offset k for this cell\n            int k = -1;\n            if (tdir == 0) {\n                // Horizontal: row is tr, start col is tc. Cell is (r, c).\n                // c = (tc + k) % N => k = (c - tc) mod N\n                k = (c - tc);\n                if (k < 0) k += N;\n            } else {\n                // Vertical: col is tc, start row is tr. Cell is (r, c).\n                // r = (tr + k) % N => k = (r - tr) mod N\n                k = (r - tr);\n                if (k < 0) k += N;\n            }\n            \n            // Check if k is within string length\n            if (k >= string_lens[p.s]) {\n                // Should not happen if logic is correct\n                continue;\n            }\n\n            int required_char = strings[p.s][k] - 'A';\n            if (required_char != new_char) {\n                // Placement broken\n                remove_placement(p.s, tr, tc, tdir, 0); // offset 0 in add/remove is relative to start\n            }\n        }\n    }\n\n    // 2. Find new valid placements\n    // Iterate potential lists for new_char at this cell\n    for (auto &p : potential_lists[new_char][cell_idx]) {\n        if (!valid_placements[p.s].test(p.id)) {\n            // Check if valid\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            // Note: toffset in id is the offset of the char at (r, c) relative to start\n            // Wait, in encode_id we used offset as the offset of the char at (r, c)?\n            // Let's recheck encode_id usage.\n            // In init_potential_lists:\n            // Horizontal: start_c = (c - k). id = encode_id(r, start_c, 0, k).\n            // Here k is the offset of the char at (r, c).\n            // So decode_id gives us k.\n            // So we can check validity by checking the whole string.\n            // But we know (r, c) matches. We just need to check others.\n            // Since only (r, c) changed, we can just check the whole string.\n            // Optimization: check only if it was valid except at (r, c).\n            // But we don't track that.\n            // Just check full validity.\n            if (is_placement_valid(p.s, tr, tc, tdir, 0)) {\n                add_placement(p.s, tr, tc, tdir, 0);\n            }\n        }\n    }\n\n    matrix[r][c] = new_char;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M;\n    strings.resize(M);\n    string_lens.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        string_lens[i] = strings[i].length();\n    }\n\n    init_potential_lists();\n    init_state();\n\n    // Simulated Annealing\n    double temperature = 100.0;\n    double cooling_rate = 0.995;\n    int max_iter = 200000; // Adjust based on time\n    int iter = 0;\n\n    while (iter < max_iter && temperature > 0.01) {\n        int r = dist_cell(rng) / N;\n        int c = dist_cell(rng) % N;\n        \n        int old_char = matrix[r][c];\n        int new_char = dist_char(rng);\n        \n        // Save state for rollback\n        // We need to save total_matched and string_counts and valid_placements\n        // This is expensive.\n        // Instead, we can just revert the cell and re-run update logic in reverse?\n        // Or just accept the cost of rollback.\n        // Rollback involves:\n        // 1. Revert cell char.\n        // 2. Re-run update logic to restore counts.\n        // This is basically running update_cell again.\n        // So we can just call update_cell(r, c, old_char) if rejected.\n        \n        int old_total_matched = total_matched;\n        // We need to track changes to string_counts to revert accurately?\n        // update_cell modifies global state.\n        // If we reject, we need to revert.\n        // Since update_cell is deterministic given the matrix state,\n        // we can just call update_cell(r, c, old_char) to revert.\n        // But update_cell assumes the cell is currently new_char.\n        // So:\n        // 1. Save old_total_matched.\n        // 2. Call update_cell(r, c, new_char).\n        // 3. Check score.\n        // 4. If reject, call update_cell(r, c, old_char).\n        // 5. Update temperature.\n        \n        update_cell(r, c, new_char);\n        \n        double delta_score = total_matched - old_total_matched;\n        // Score is proportional to total_matched.\n        // If total_matched == M, we prefer fewer '.'. But we don't use '.'.\n        // So score is just total_matched.\n        \n        double prob = 1.0;\n        if (delta_score < 0) {\n            prob = exp(delta_score / temperature);\n        }\n        \n        double rand_val = (double)dist_char(rng) / (double)NUM_CHARS; // 0 to 1 approx\n        if (rand_val < prob) {\n            // Accept\n        } else {\n            // Reject, revert\n            update_cell(r, c, old_char);\n        }\n\n        temperature *= cooling_rate;\n        iter++;\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << (char)('A' + matrix[i][j]);\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> roads;\nint total_roads = 0;\n\n// Direction arrays: U, D, L, R\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\nconst char dc[] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && grid[i][j] != '#';\n}\n\nbool isVisible(int ci, int cj, int ti, int tj) {\n    if (ci == ti) {\n        for (int j = min(cj, tj); j <= max(cj, tj); j++) {\n            if (grid[ci][j] == '#') return false;\n        }\n        return true;\n    }\n    if (cj == tj) {\n        for (int i = min(ci, ti); i <= max(ci, ti); i++) {\n            if (grid[i][cj] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\nint getCost(int i, int j) {\n    return grid[i][j] - '0';\n}\n\n// Calculate total travel time of a path\nlong long calcPathCost(const vector<pair<int,int>>& path) {\n    if (path.empty()) return 0;\n    long long cost = 0;\n    for (size_t i = 1; i < path.size(); i++) {\n        cost += getCost(path[i].first, path[i].second);\n    }\n    return cost;\n}\n\n// Get all squares visible from a position\nvector<pair<int,int>> getVisibleSquares(int ci, int cj) {\n    vector<pair<int,int>> visible;\n    for (const auto& [ri, rj] : roads) {\n        if (isVisible(ci, cj, ri, rj)) {\n            visible.push_back({ri, rj});\n        }\n    }\n    return visible;\n}\n\n// BFS to find shortest path between two points\nvector<pair<int,int>> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {{si, sj}};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    queue<pair<int,int>> q;\n    \n    dist[si][sj] = 0;\n    q.push({si, sj});\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) {\n            vector<pair<int,int>> path;\n            int i = ti, j = tj;\n            while (!(i == si && j == sj)) {\n                path.push_back({i, j});\n                auto [pi, pj] = parent[i][j];\n                i = pi; j = pj;\n            }\n            path.push_back({si, sj});\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (isValid(ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                parent[ni][nj] = {ci, cj};\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    return {{si, sj}};\n}\n\nint main() {\n    srand(42);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n    }\n    \n    // Collect all road squares\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                roads.push_back({i, j});\n            }\n        }\n    }\n    total_roads = roads.size();\n    \n    // Phase 1: Greedy coverage\n    vector<pair<int,int>> path = {{si, sj}};\n    set<pair<int,int>> covered;\n    \n    // Mark initially visible squares\n    for (const auto& [ri, rj] : roads) {\n        if (isVisible(si, sj, ri, rj)) {\n            covered.insert({ri, rj});\n        }\n    }\n    \n    int ci = si, cj = sj;\n    int max_iter = 200000;\n    int iter = 0;\n    \n    while ((int)covered.size() < total_roads && iter < max_iter) {\n        iter++;\n        \n        int best_d = -1;\n        int max_new = -1;\n        int min_cost = 1000000;\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (!isValid(ni, nj)) continue;\n            \n            int new_covered = 0;\n            for (const auto& [ri, rj] : roads) {\n                if (covered.find({ri, rj}) == covered.end()) {\n                    if (isVisible(ni, nj, ri, rj)) {\n                        new_covered++;\n                    }\n                }\n            }\n            \n            if (new_covered > max_new || (new_covered == max_new && new_covered > 0)) {\n                max_new = new_covered;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1) {\n            // No new coverage, move randomly\n            best_d = rand() % 4;\n        }\n        \n        ci += di[best_d];\n        cj += dj[best_d];\n        path.push_back({ci, cj});\n        \n        for (const auto& [ri, rj] : roads) {\n            if (isVisible(ci, cj, ri, rj)) {\n                covered.insert({ri, rj});\n            }\n        }\n    }\n    \n    // Phase 2: Return to start using BFS\n    vector<pair<int,int>> returnPath = bfsPath(path.back().first, path.back().second, si, sj);\n    for (size_t i = 1; i < returnPath.size(); i++) {\n        path.push_back(returnPath[i]);\n    }\n    \n    // Phase 3: Simulated Annealing optimization\n    long long currentCost = calcPathCost(path);\n    long long bestCost = currentCost;\n    double temperature = 10000.0;\n    double coolingRate = 0.995;\n    \n    auto evaluate = [&]() {\n        set<pair<int,int>> tempCovered;\n        for (const auto& [ri, rj] : roads) {\n            if (isVisible(si, sj, ri, rj)) {\n                tempCovered.insert({ri, rj});\n            }\n        }\n        for (const auto& [ci, cj] : path) {\n            for (const auto& [ri, rj] : roads) {\n                if (isVisible(ci, cj, ri, rj)) {\n                    tempCovered.insert({ri, rj});\n                }\n            }\n        }\n        return (int)tempCovered.size() == total_roads;\n    };\n    \n    while (temperature > 1.0) {\n        // Try 2-opt swap\n        int n = path.size();\n        int i1 = rand() % (n - 2);\n        int i2 = rand() % (n - i1 - 2) + i1 + 1;\n        \n        vector<pair<int,int>> newPath = path;\n        reverse(newPath.begin() + i1 + 1, newPath.begin() + i2 + 1);\n        \n        if (evaluate()) {\n            long long newCost = calcPathCost(newPath);\n            long long delta = newCost - currentCost;\n            \n            if (delta < 0 || rand() % 1000 < (int)(1000.0 * exp(-delta / temperature))) {\n                path = newPath;\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    // Phase 4: Convert path to movement string\n    string result;\n    for (size_t i = 1; i < path.size(); i++) {\n        int di_val = path[i].first - path[i-1].first;\n        int dj_val = path[i].second - path[i-1].second;\n        \n        if (di_val == -1) result += 'U';\n        else if (di_val == 1) result += 'D';\n        else if (dj_val == -1) result += 'L';\n        else if (dj_val == 1) result += 'R';\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    vector<int> dependents;\n    int indegree;\n    int status; // 0: available, 1: assigned, 2: done\n    int start_day;\n};\n\nstruct Member {\n    int id;\n    vector<double> estimate;\n    vector<int> lower_bound;\n    int current_task; // -1 if free\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<vector<int>> adj;\nint day = 0;\n\ndouble calculate_cost(int task_idx, int member_idx) {\n    double cost = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            cost += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n        }\n    }\n    return max(1.0, cost);\n}\n\nvoid update_costs_for_member(int member_idx) {\n    // Re-calculate costs for all tasks for this member\n    // This is O(N * K)\n    // We don't store costs explicitly to save memory and update time, \n    // we calculate on demand or update a cache if needed.\n    // Given N=1000, M=20, calculating on demand is O(N*K) = 20000 ops.\n    // Doing this for all members is 400000 ops.\n    // Doing this every day is 2000 * 400000 = 8e8 ops. Too slow.\n    // We need to cache costs.\n    // But costs only change when skills change.\n    // Skills change when a task completes.\n    // So we update costs only when skills update.\n    // This is O(N*K) per completion. Total N completions.\n    // Total O(N^2 * K) = 1000^2 * 20 = 2e7 ops. Acceptable.\n    // So we maintain a cost matrix.\n}\n\nvector<vector<double>> cost_matrix;\n\nvoid update_cost_matrix(int member_idx) {\n    for (int i = 0; i < N; ++i) {\n        cost_matrix[i][member_idx] = calculate_cost(i, member_idx);\n    }\n}\n\nvoid update_skills(int member_idx, int task_idx, int t) {\n    // Update lower bounds and estimates\n    // t is the actual time taken\n    \n    // If t=1, we know w=0, so s >= d for all k\n    if (t == 1) {\n        for (int k = 0; k < K; ++k) {\n            if (tasks[task_idx].d[k] > members[member_idx].lower_bound[k]) {\n                members[member_idx].lower_bound[k] = tasks[task_idx].d[k];\n                // Update estimate to be at least lower bound\n                if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                    members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n                }\n            }\n        }\n    }\n    \n    // Update estimate based on observed time\n    // w_obs approx t (if t > 1)\n    // w_pred = sum(max(0, d - estimate))\n    \n    double w_pred = 0;\n    int count_non_zero = 0;\n    vector<int> contributing_skills;\n    \n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            w_pred += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n            count_non_zero++;\n            contributing_skills.push_back(k);\n        }\n    }\n    \n    double w_obs = 0;\n    if (t > 1) {\n        // w = t - r, r in [-3, 3]. So w in [t-3, t+3].\n        // Expectation is t.\n        // But if t=1, w=0.\n        w_obs = t; \n        // Conservative: if t is small, w might be 0.\n        // But if t=1, handled above.\n        // If t=2, w could be 0 (if r=2) or 5 (if r=-3).\n        // But if w=0, t=1 always. So if t>1, w>0.\n        // So w_obs = t is reasonable.\n    } else {\n        w_obs = 0;\n    }\n    \n    if (count_non_zero > 0) {\n        double diff = w_pred - w_obs;\n        // If diff > 0, we overestimated skills (predicted less work than observed). Decrease estimate.\n        // If diff < 0, we underestimated skills. Increase estimate.\n        // Adjustment per skill\n        double adjust = diff / count_non_zero;\n        \n        for (int k : contributing_skills) {\n            members[member_idx].estimate[k] -= adjust;\n            // Clamp to lower bound\n            if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n            }\n            // Also ensure non-negative\n            if (members[member_idx].estimate[k] < 0) {\n                members[member_idx].estimate[k] = 0;\n            }\n        }\n    }\n    \n    // Update cost matrix for this member\n    update_cost_matrix(member_idx);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n        }\n        tasks[i].indegree = 0;\n        tasks[i].status = 0;\n        tasks[i].start_day = 0;\n    }\n\n    adj.resize(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        tasks[v].indegree++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].estimate.assign(K, 0.0);\n        members[i].lower_bound.assign(K, 0);\n        members[i].current_task = -1;\n    }\n\n    cost_matrix.assign(N, vector<double>(M, 0.0));\n    // Initialize cost matrix\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cost_matrix[i][j] = calculate_cost(i, j);\n        }\n    }\n\n    // Count dependents for priority\n    vector<int> outdegree(N, 0);\n    for (int i = 0; i < N; ++i) {\n        outdegree[i] = adj[i].size();\n    }\n\n    while (true) {\n        day++;\n        if (day > 2000) break;\n\n        // Identify free members\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (members[j].current_task == -1) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Identify available tasks\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (tasks[i].status == 0 && tasks[i].indegree == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Assign tasks\n        // We want to match free_members to available_tasks to minimize cost\n        // Priority: cost first, then outdegree (tasks that unlock more)\n        \n        struct Assignment {\n            double cost;\n            int task_idx;\n            int member_idx;\n            int priority; // outdegree\n            bool operator<(const Assignment& other) const {\n                if (abs(cost - other.cost) > 1e-9) return cost < other.cost;\n                return priority > other.priority; // Higher outdegree first\n            }\n        };\n\n        vector<Assignment> candidates;\n        candidates.reserve(free_members.size() * available_tasks.size());\n\n        for (int j : free_members) {\n            for (int i : available_tasks) {\n                candidates.push_back({cost_matrix[i][j], i, j, outdegree[i]});\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n\n        vector<int> assigned_tasks(N, -1); // -1 if not assigned in this round\n        vector<int> assigned_members(M, -1); // -1 if not assigned in this round\n        vector<pair<int, int>> output_assignments;\n\n        for (const auto& cand : candidates) {\n            if (assigned_tasks[cand.task_idx] == -1 && assigned_members[cand.member_idx] == -1) {\n                assigned_tasks[cand.task_idx] = cand.task_idx;\n                assigned_members[cand.member_idx] = cand.member_idx;\n                output_assignments.push_back({cand.member_idx, cand.task_idx});\n                \n                // Update status\n                tasks[cand.task_idx].status = 1;\n                tasks[cand.task_idx].start_day = day;\n                members[cand.member_idx].current_task = cand.task_idx;\n            }\n        }\n\n        // Output\n        cout << output_assignments.size();\n        for (const auto& p : output_assignments) {\n            cout << \" \" << (p.first + 1) << \" \" << (p.second + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completions\n        int n_completions;\n        cin >> n_completions;\n        if (n_completions == -1) break;\n\n        vector<int> completed_members(n_completions);\n        for (int i = 0; i < n_completions; ++i) {\n            cin >> completed_members[i];\n            --completed_members[i]; // 0-indexed\n        }\n\n        for (int j : completed_members) {\n            int task_idx = members[j].current_task;\n            if (task_idx != -1) {\n                int t = day - tasks[task_idx].start_day + 1;\n                \n                // Update skills\n                update_skills(j, task_idx, t);\n                \n                // Update task status\n                tasks[task_idx].status = 2;\n                members[j].current_task = -1;\n                \n                // Update dependencies\n                for (int v : adj[task_idx]) {\n                    tasks[v].indegree--;\n                    if (tasks[v].indegree == 0) {\n                        // Task v becomes available\n                        // No need to do anything, it will be picked up next day\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n    int orderId; // -1 for office\n    int type; // 0 for pickup, 1 for dropoff, 2 for office\n};\n\nint dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    vector<Order> orders(1000);\n    for (int i = 0; i < 1000; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n    \n    int ox = 400, oy = 400;\n    \n    // Selected orders\n    vector<int> selected;\n    vector<bool> isSelected(1000, false);\n    vector<int> notSelected;\n    \n    // Initial selection: pick orders with short pickup-dropoff distance\n    vector<pair<int, int>> orderDist;\n    for (int i = 0; i < 1000; i++) {\n        int d = dist(orders[i].a, orders[i].b, orders[i].c, orders[i].d);\n        orderDist.push_back({d, i});\n    }\n    sort(orderDist.begin(), orderDist.end());\n    for (int i = 0; i < 50; i++) {\n        selected.push_back(orderDist[i].second);\n        isSelected[orderDist[i].second] = true;\n    }\n    for (int i = 50; i < 1000; i++) {\n        notSelected.push_back(orderDist[i].second);\n    }\n    \n    // Build initial route: office -> all pickups -> all dropoffs -> office\n    auto buildRoute = [&](const vector<int>& sel) {\n        vector<Point> route;\n        route.reserve(2 * sel.size() + 2);\n        route.push_back({ox, oy, -1, 2});\n        for (int idx : sel) {\n            route.push_back({orders[idx].a, orders[idx].b, idx, 0});\n        }\n        for (int idx : sel) {\n            route.push_back({orders[idx].c, orders[idx].d, idx, 1});\n        }\n        route.push_back({ox, oy, -1, 2});\n        return route;\n    };\n    \n    vector<Point> route = buildRoute(selected);\n    \n    // Calculate route cost\n    auto calcCost = [&]() {\n        int cost = 0;\n        for (size_t i = 0; i + 1 < route.size(); i++) {\n            cost += dist(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n        }\n        return cost;\n    };\n    \n    int currentCost = calcCost();\n    int bestCost = currentCost;\n    vector<Point> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // Simulated annealing parameters\n    random_device rd;\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> randDist(0.0, 1.0);\n    \n    double temperature = 3000.0;\n    double coolingRate = 0.99992;\n    \n    auto startTime = chrono::high_resolution_clock::now();\n    double timeLimit = 1.95;\n    \n    // Check if route is valid (pickup before dropoff for each order)\n    auto isValidRoute = [&](const vector<Point>& r, const vector<int>& sel) {\n        vector<int> pickupPos(1000, -1), dropoffPos(1000, -1);\n        for (size_t k = 0; k < r.size(); k++) {\n            if (r[k].orderId >= 0) {\n                if (r[k].type == 0) pickupPos[r[k].orderId] = k;\n                else dropoffPos[r[k].orderId] = k;\n            }\n        }\n        for (int idx : sel) {\n            if (pickupPos[idx] >= dropoffPos[idx]) return false;\n        }\n        return true;\n    };\n    \n    // Incremental cost calculation for 2-opt\n    auto calc2optDelta = [&](const vector<Point>& r, int i, int j) {\n        int delta = 0;\n        if (i > 0) {\n            delta -= dist(r[i-1].x, r[i-1].y, r[i].x, r[i].y);\n        }\n        if (j + 1 < (int)r.size()) {\n            delta -= dist(r[j].x, r[j].y, r[j+1].x, r[j+1].y);\n        }\n        if (i > 0) {\n            delta += dist(r[i-1].x, r[i-1].y, r[j].x, r[j].y);\n        }\n        if (j + 1 < (int)r.size()) {\n            delta += dist(r[i].x, r[i].y, r[j+1].x, r[j+1].y);\n        }\n        return delta;\n    };\n    \n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed >= timeLimit) break;\n        \n        // Try different moves\n        int moveType = randDist(gen) < 0.4 ? 0 : (randDist(gen) < 0.75 ? 1 : 2);\n        \n        if (moveType == 0) {\n            // Swap: exchange an order in/out of selected set\n            int inIdx = (int)(randDist(gen) * selected.size());\n            int outIdx = (int)(randDist(gen) * notSelected.size());\n            \n            int inOrder = selected[inIdx];\n            int outOrder = notSelected[outIdx];\n            \n            // Try swap\n            auto oldSelected = selected;\n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            selected[inIdx] = outOrder;\n            isSelected[inOrder] = false;\n            isSelected[outOrder] = true;\n            notSelected[outIdx] = inOrder;\n            \n            route = buildRoute(selected);\n            \n            if (!isValidRoute(route, selected)) {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n                isSelected[inOrder] = true;\n                isSelected[outOrder] = false;\n                notSelected[outIdx] = outOrder;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n                isSelected[inOrder] = true;\n                isSelected[outOrder] = false;\n                notSelected[outIdx] = outOrder;\n            }\n        } else if (moveType == 1) {\n            // 2-opt: reverse a segment of the route (excluding first and last)\n            int i = 1 + (int)(randDist(gen) * (route.size() - 4));\n            int j = i + 1 + (int)(randDist(gen) * (route.size() - i - 3));\n            \n            // Ensure we don't include first or last point\n            i = max(1, i);\n            j = min((int)route.size() - 2, j);\n            \n            if (i >= j) continue;\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            reverse(route.begin() + i, route.begin() + j + 1);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        } else {\n            // Insert: move a non-office point to different position\n            int pos1 = 1 + (int)(randDist(gen) * (route.size() - 3));\n            int pos2 = 1 + (int)(randDist(gen) * (route.size() - 3));\n            \n            if (pos1 == pos2) continue;\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            Point p = route[pos1];\n            route.erase(route.begin() + pos1);\n            route.insert(route.begin() + pos2, p);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        }\n        \n        temperature *= coolingRate;\n        \n        // Periodically output for visualization (optional)\n        if (elapsed > 0.5 && elapsed < 0.6) {\n            cout << bestSelected.size();\n            for (int idx : bestSelected) {\n                cout << \" \" << orders[idx].id;\n            }\n            cout << \"\\n\";\n            cout << bestRoute.size();\n            for (auto& p : bestRoute) {\n                cout << \" \" << p.x << \" \" << p.y;\n            }\n            cout << \"\\n\";\n        }\n    }\n    \n    // Output final best solution\n    cout << bestSelected.size();\n    for (int idx : bestSelected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (auto& p : bestRoute) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    // Optimization for faster I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<pair<int, int>> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        // Calculate rounded Euclidean distance\n        long long dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        long long dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = (int)round(sqrt(dx * dx + dy * dy));\n    }\n\n    dsu d(N);\n    vector<int> degree(N);\n    vector<long long> min_d_vec(N); // Not strictly needed as we scan, but for clarity\n\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int root_u = d.find(u);\n        int root_v = d.find(v);\n\n        if (root_u == root_v) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Scan future edges to analyze connectivity and potential costs\n        fill(degree.begin(), degree.end(), 0);\n        long long min_d = 1e18;\n        long long min_d_all = 1e18;\n        bool has_direct = false;\n\n        for (int j = i + 1; j < M; ++j) {\n            int u_j = edges[j].u;\n            int v_j = edges[j].v;\n            int ru = d.find(u_j);\n            int rv = d.find(v_j);\n\n            if (ru != rv) {\n                degree[ru]++;\n                degree[rv]++;\n                min_d_all = min(min_d_all, (long long)edges[j].d);\n                \n                if ((ru == root_u && rv == root_v) || (ru == root_v && rv == root_u)) {\n                    min_d = min(min_d, (long long)edges[j].d);\n                    has_direct = true;\n                }\n            }\n        }\n\n        bool accept = false;\n\n        // Safety Check: If a component is a leaf or isolated in the remaining graph, we must accept.\n        if (degree[root_u] <= 1 || degree[root_v] <= 1) {\n            accept = true;\n        }\n        // Cost Check 1: Direct connection available\n        else if (has_direct) {\n            if (l_i <= 2.0 * min_d) {\n                accept = true;\n            }\n        }\n        // Cost Check 2: No direct connection, rely on indirect (fallback)\n        else {\n            if (min_d_all != 1e18) {\n                if (l_i <= 3.0 * min_d_all) {\n                    accept = true;\n                }\n            } else {\n                // No edges remaining, must accept to connect\n                accept = true;\n            }\n        }\n\n        cout << (accept ? \"1\" : \"0\") << \"\\n\";\n        cout.flush();\n\n        if (accept) {\n            d.unite(u, v);\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Pet {\n    int x, y, type;\n    bool operator<(const Pet& other) const {\n        return type < other.type;\n    }\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct State {\n    int turn;\n    vector<Pet> pets;\n    vector<Human> humans;\n    vector<vector<bool>> wall;\n    vector<vector<bool>> passable;\n};\n\nState state;\nmt19937 rng;\n\n// Directions: up, down, left, right\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char moveChars[] = {'U', 'D', 'L', 'R'};\nconst char wallChars[] = {'u', 'd', 'l', 'r'};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;\n}\n\nbool isPassable(int x, int y) {\n    if (!isValid(x, y)) return false;\n    return !state.wall[x][y];\n}\n\nbool hasPetAt(int x, int y) {\n    for (const auto& pet : state.pets) {\n        if (pet.x == x && pet.y == y) return true;\n    }\n    return false;\n}\n\nbool hasHumanAt(int x, int y) {\n    for (const auto& human : state.humans) {\n        if (human.x == x && human.y == y) return true;\n    }\n    return false;\n}\n\nbool hasPetAdjacent(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (hasPetAt(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canPlaceWall(int x, int y) {\n    if (!isValid(x, y)) return false;\n    if (state.wall[x][y]) return false;\n    if (hasPetAt(x, y)) return false;\n    if (hasHumanAt(x, y)) return false;\n    if (hasPetAdjacent(x, y)) return false;\n    return true;\n}\n\nint bfsReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint countPetsInReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (hasPetAt(x, y)) count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint getDistance(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint bfsDistance(int x1, int y1, int x2, int y2) {\n    if (!isValid(x1, y1) || !isValid(x2, y2)) return 1e9;\n    if (x1 == x2 && y1 == y2) return 0;\n    \n    vector<vector<int>> dist(GRID_SIZE, vector<int>(GRID_SIZE, 1e9));\n    queue<pair<int, int>> q;\n    \n    dist[x1][y1] = 0;\n    q.push({x1, y1});\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == x2 && y == y2) return dist[x][y];\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny] && dist[nx][ny] == 1e9) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return 1e9;\n}\n\ndouble evaluateAction(int humanIdx, char action) {\n    // Simulate the action and evaluate the result\n    State simState = state;\n    \n    // Apply human action\n    if (action == '.') {\n        // Stay\n    } else if (action >= 'A' && action <= 'Z') {\n        // Move\n        int d = 0;\n        if (action == 'U') d = 0;\n        else if (action == 'D') d = 1;\n        else if (action == 'L') d = 2;\n        else if (action == 'R') d = 3;\n        \n        int nx = simState.humans[humanIdx].x + dx[d];\n        int ny = simState.humans[humanIdx].y + dy[d];\n        \n        if (isValid(nx, ny) && !simState.wall[nx][ny]) {\n            simState.humans[humanIdx].x = nx;\n            simState.humans[humanIdx].y = ny;\n        }\n    } else if (action >= 'a' && action <= 'z') {\n        // Place wall\n        int d = 0;\n        if (action == 'u') d = 0;\n        else if (action == 'd') d = 1;\n        else if (action == 'l') d = 2;\n        else if (action == 'r') d = 3;\n        \n        int wx = simState.humans[humanIdx].x + dx[d];\n        int wy = simState.humans[humanIdx].y + dy[d];\n        \n        if (canPlaceWall(wx, wy)) {\n            simState.wall[wx][wy] = true;\n        }\n    }\n    \n    // Calculate score\n    int reachable = bfsReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    int petsInArea = countPetsInReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    \n    double score = (double)reachable / 900.0 * pow(0.5, petsInArea);\n    \n    // Penalty for being close to dogs\n    for (const auto& pet : simState.pets) {\n        if (pet.type == 4) { // Dog\n            int dist = bfsDistance(simState.humans[humanIdx].x, simState.humans[humanIdx].y, pet.x, pet.y);\n            if (dist < 10) {\n                score -= 0.1 * (10 - dist);\n            }\n        }\n    }\n    \n    return score;\n}\n\nchar decideAction(int humanIdx) {\n    vector<char> possibleActions = {'.', 'U', 'D', 'L', 'R', 'u', 'd', 'l', 'r'};\n    char bestAction = '.';\n    double bestScore = -1e9;\n    \n    for (char action : possibleActions) {\n        // Check if action is valid\n        if (action >= 'A' && action <= 'Z') {\n            int d = 0;\n            if (action == 'U') d = 0;\n            else if (action == 'D') d = 1;\n            else if (action == 'L') d = 2;\n            else if (action == 'R') d = 3;\n            \n            int nx = state.humans[humanIdx].x + dx[d];\n            int ny = state.humans[humanIdx].y + dy[d];\n            \n            if (!isValid(nx, ny) || state.wall[nx][ny]) continue;\n        } else if (action >= 'a' && action <= 'z') {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n        }\n        \n        double score = evaluateAction(humanIdx, action);\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestAction = action;\n        }\n    }\n    \n    return bestAction;\n}\n\nchar decideActionStrategic(int humanIdx) {\n    // Strategic decision based on turn phase\n    int turn = state.turn;\n    \n    // Early phase: Build walls around humans\n    if (turn < 50) {\n        // Prioritize wall placement\n        vector<char> wallActions = {'u', 'd', 'l', 'r'};\n        char bestWall = '.';\n        double bestScore = -1e9;\n        \n        for (char action : wallActions) {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateAction(humanIdx, action);\n            \n            // Bonus for blocking dogs\n            for (const auto& pet : state.pets) {\n                if (pet.type == 4) { // Dog\n                    int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                    if (dist < 15) {\n                        score += 0.5;\n                    }\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestWall = action;\n            }\n        }\n        \n        if (bestWall != '.') return bestWall;\n        \n        // If no good wall placement, stay\n        return '.';\n    }\n    \n    // Middle phase: Expand and defend\n    if (turn < 200) {\n        // Mix of wall placement and movement\n        char action = decideAction(humanIdx);\n        \n        // Bias towards walls if close to pets\n        for (const auto& pet : state.pets) {\n            if (pet.type == 4) { // Dog\n                int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                if (dist < 10) {\n                    // Prefer wall placement\n                    vector<char> wallActions = {'u', 'd', 'l', 'r'};\n                    for (char wall : wallActions) {\n                        int d = 0;\n                        if (wall == 'u') d = 0;\n                        else if (wall == 'd') d = 1;\n                        else if (wall == 'l') d = 2;\n                        else if (wall == 'r') d = 3;\n                        \n                        int wx = state.humans[humanIdx].x + dx[d];\n                        int wy = state.humans[humanIdx].y + dy[d];\n                        \n                        if (canPlaceWall(wx, wy)) {\n                            return wall;\n                        }\n                    }\n                }\n            }\n        }\n        \n        return action;\n    }\n    \n    // Late phase: Fine-tune\n    return decideAction(humanIdx);\n}\n\nvoid updateState(const vector<string>& petMoves) {\n    // Update pet positions based on their moves\n    for (int i = 0; i < state.pets.size(); i++) {\n        const string& move = petMoves[i];\n        int x = state.pets[i].x;\n        int y = state.pets[i].y;\n        \n        for (char c : move) {\n            int d = 0;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            \n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                x = nx;\n                y = ny;\n            }\n        }\n        \n        state.pets[i].x = x;\n        state.pets[i].y = y;\n    }\n    \n    state.turn++;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    // Read input\n    int N;\n    cin >> N;\n    \n    state.pets.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> state.pets[i].x >> state.pets[i].y >> state.pets[i].type;\n        state.pets[i].x--; // Convert to 0-indexed\n        state.pets[i].y--;\n    }\n    \n    int M;\n    cin >> M;\n    \n    state.humans.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> state.humans[i].x >> state.humans[i].y;\n        state.humans[i].x--; // Convert to 0-indexed\n        state.humans[i].y--;\n    }\n    \n    // Initialize state\n    state.turn = 0;\n    state.wall.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    state.passable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Main game loop\n    for (int turn = 0; turn < MAX_TURNS; turn++) {\n        // Check time limit\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2800) {\n            // Output stay for all humans to avoid TLE\n            for (int i = 0; i < M; i++) {\n                cout << '.';\n            }\n            cout << endl;\n            flush(cout);\n            \n            // Read pet moves\n            vector<string> petMoves(M);\n            for (int i = 0; i < N; i++) {\n                cin >> petMoves[i];\n            }\n            continue;\n        }\n        \n        // Decide actions for each human\n        string actions = \"\";\n        for (int i = 0; i < M; i++) {\n            char action = decideActionStrategic(i);\n            actions += action;\n        }\n        \n        cout << actions << endl;\n        flush(cout);\n        \n        // Read pet moves\n        vector<string> petMoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petMoves[i];\n        }\n        \n        // Update state\n        updateState(petMoves);\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int INF = 1e9;\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    if (!(cin >> si >> sj >> ti >> tj >> p)) return 0;\n\n    // Read horizontal walls\n    // h[i][j] is 1 if there is a wall between (i, j) and (i, j+1)\n    vector<string> h(MAX_N);\n    for (int i = 0; i < MAX_N; ++i) {\n        cin >> h[i];\n    }\n\n    // Read vertical walls\n    // v[i][j] is 1 if there is a wall between (i, j) and (i+1, j)\n    vector<string> v(MAX_N - 1);\n    for (int i = 0; i < MAX_N - 1; ++i) {\n        cin >> v[i];\n    }\n\n    // BFS to compute shortest path distances from all cells to the target (ti, tj)\n    // This is used as a heuristic to guide the agent towards the target.\n    vector<vector<int>> dist(MAX_N, vector<int>(MAX_N, INF));\n    queue<pair<int, int>> q;\n\n    dist[ti][tj] = 0;\n    q.push({ti, tj});\n\n    // Directions: R, L, D, U\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    char moves[] = {'R', 'L', 'D', 'U'};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k];\n            int nj = j + dj[k];\n\n            if (ni >= 0 && ni < MAX_N && nj >= 0 && nj < MAX_N) {\n                bool wall = false;\n                if (k == 0) { // R: check wall between (i,j) and (i,j+1)\n                    if (h[i][j] == '1') wall = true;\n                } else if (k == 1) { // L: check wall between (i,j-1) and (i,j)\n                    if (h[i][j-1] == '1') wall = true;\n                } else if (k == 2) { // D: check wall between (i,j) and (i+1,j)\n                    if (v[i][j] == '1') wall = true;\n                } else if (k == 3) { // U: check wall between (i-1,j) and (i,j)\n                    if (v[i-1][j] == '1') wall = true;\n                }\n\n                if (!wall && dist[ni][nj] == INF) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n\n    // Probability distribution of the agent's position\n    // prob[i][j] is the probability that the agent is at (i, j)\n    vector<vector<double>> prob(MAX_N, vector<double>(MAX_N, 0.0));\n    prob[si][sj] = 1.0;\n\n    string result = \"\";\n    double move_prob = 1.0 - p;\n\n    // Buffer for next probability distribution\n    vector<vector<double>> next_prob(MAX_N, vector<double>(MAX_N));\n\n    // Greedily choose the move for each of the 200 steps\n    for (int step = 0; step < 200; ++step) {\n        int best_move = 0;\n        double min_expected_dist = 1e18;\n        double max_reach_prob = -1.0;\n        vector<vector<double>> best_next_prob;\n\n        // Evaluate all 4 possible moves\n        for (int k = 0; k < 4; ++k) {\n            // Reset next_prob buffer\n            for(int i = 0; i < MAX_N; ++i) \n                for(int j = 0; j < MAX_N; ++j) \n                    next_prob[i][j] = 0.0;\n\n            // Simulate the move\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (prob[i][j] == 0.0) continue;\n                    // If already at target, stay there (absorbing state)\n                    if (i == ti && j == tj) {\n                        next_prob[i][j] += prob[i][j];\n                        continue;\n                    }\n\n                    int ni = i + di[k];\n                    int nj = j + dj[k];\n                    bool blocked = false;\n                    \n                    // Check boundaries\n                    if (ni < 0 || ni >= MAX_N || nj < 0 || nj >= MAX_N) blocked = true;\n                    else {\n                        // Check walls\n                        if (k == 0) { if (h[i][j] == '1') blocked = true; }\n                        else if (k == 1) { if (h[i][j-1] == '1') blocked = true; }\n                        else if (k == 2) { if (v[i][j] == '1') blocked = true; }\n                        else if (k == 3) { if (v[i-1][j] == '1') blocked = true; }\n                    }\n\n                    if (blocked) {\n                        // If blocked, agent stays in current square with probability 1\n                        // (p from forgetting + (1-p) from blocked move)\n                        next_prob[i][j] += prob[i][j];\n                    } else {\n                        // Move with probability (1-p)\n                        next_prob[ni][nj] += prob[i][j] * move_prob;\n                        // Stay with probability p (forgetting)\n                        next_prob[i][j] += prob[i][j] * p;\n                    }\n                }\n            }\n\n            // Calculate evaluation metrics\n            double ed = 0.0; // Expected distance to target\n            double rp = 0.0; // Probability of being at target\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (i == ti && j == tj) {\n                        rp = next_prob[i][j];\n                    } else {\n                        if (dist[i][j] != INF) {\n                            ed += next_prob[i][j] * dist[i][j];\n                        }\n                    }\n                }\n            }\n\n            // Select the best move based on metrics\n            // Primary: Minimize expected distance\n            // Secondary: Maximize probability of reaching target (tie-breaker)\n            if (ed < min_expected_dist - 1e-9) {\n                min_expected_dist = ed;\n                max_reach_prob = rp;\n                best_move = k;\n                best_next_prob = next_prob;\n            } else if (abs(ed - min_expected_dist) < 1e-9) {\n                if (rp > max_reach_prob) {\n                    max_reach_prob = rp;\n                    best_move = k;\n                    best_next_prob = next_prob;\n                }\n            }\n        }\n\n        // Append the best move to the result string\n        result += moves[best_move];\n        // Update the probability distribution\n        prob = best_next_prob;\n    }\n\n    cout << result << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to table from problem statement\nconst int to[8][4] = {\n    {1, 0, -1, -1}, // 0\n    {3, -1, -1, 0}, // 1\n    {-1, -1, 3, 2}, // 2\n    {-1, 2, 1, -1}, // 3\n    {1, 0, 3, 2},   // 4\n    {3, 2, 1, 0},   // 5\n    {2, -1, 0, -1}, // 6\n    {-1, 3, -1, 1}  // 7\n};\n\nint grid_type[30][30];\nint rot[30][30];\nint best_rot[30][30];\n\n// Visited generation array to avoid memset every time\nint vis_gen[30][30][4];\nint dist[30][30][4];\nint trace_id = 0;\n\nint get_effective_type(int base, int r) {\n    if (base < 4) return (base + r) % 4;\n    if (base == 4) return 4 + (r % 2);\n    if (base == 5) return 5 - (r % 2);\n    if (base == 6) return 6 + (r % 2);\n    if (base == 7) return 7 - (r % 2);\n    return 0;\n}\n\nlong long calc_score(vector<int>& lengths) {\n    lengths.clear();\n    lengths.reserve(900);\n\n    trace_id++;\n    if (trace_id == 0) {\n        memset(vis_gen, 0, sizeof(vis_gen));\n        trace_id = 1;\n    }\n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (vis_gen[i][j][d] == trace_id) continue;\n\n                int cur_i = i, cur_j = j, cur_d = d;\n                int steps = 0;\n                bool cycle_found = false;\n                int cycle_len = 0;\n\n                while (true) {\n                    if (vis_gen[cur_i][cur_j][cur_d] == trace_id) {\n                        cycle_len = steps - dist[cur_i][cur_j][cur_d];\n                        cycle_found = true;\n                        break;\n                    }\n                    if (vis_gen[cur_i][cur_j][cur_d] != 0) {\n                        break;\n                    }\n\n                    vis_gen[cur_i][cur_j][cur_d] = trace_id;\n                    dist[cur_i][cur_j][cur_d] = steps;\n\n                    int t = get_effective_type(grid_type[cur_i][cur_j], rot[cur_i][cur_j]);\n                    int next_d = to[t][cur_d];\n                    if (next_d == -1) break;\n\n                    int next_i = cur_i + di[next_d];\n                    int next_j = cur_j + dj[next_d];\n\n                    if (next_i < 0 || next_i >= 30 || next_j < 0 || next_j >= 30) break;\n\n                    cur_i = next_i;\n                    cur_j = next_j;\n                    cur_d = (next_d + 2) % 4;\n                    steps++;\n                }\n\n                if (cycle_found) {\n                    lengths.push_back(cycle_len);\n                }\n            }\n        }\n    }\n\n    if (lengths.size() < 2) return 0;\n    sort(lengths.rbegin(), lengths.rend());\n    return (long long)lengths[0] * lengths[1];\n}\n\nvoid copy_rot(int src[30][30], int dst[30][30]) {\n    for (int i = 0; i < 30; ++i)\n        for (int j = 0; j < 30; ++j)\n            dst[i][j] = src[i][j];\n}\n\nvoid randomize_rot(mt19937& rng, int rot[30][30]) {\n    uniform_int_distribution<int> dist_rot(0, 3);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            rot[i][j] = dist_rot(rng);\n        }\n    }\n}\n\nvoid solve() {\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            grid_type[i][j] = s[j] - '0';\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_rot(0, 3);\n    uniform_int_distribution<int> dist_idx(0, 29);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    long long best_score = 0;\n    vector<int> lengths;\n\n    auto start_time = chrono::steady_clock::now();\n    auto limit_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    // Multi-start with different strategies\n    int num_starts = 0;\n    int max_starts = 20;\n\n    while (chrono::steady_clock::now() < limit_time && num_starts < max_starts) {\n        num_starts++;\n\n        // Randomize rotations\n        randomize_rot(rng, rot);\n\n        // Initial score\n        long long current_score = calc_score(lengths);\n\n        // Local search with simulated annealing\n        double T = 5000.0;\n        int no_improve_count = 0;\n        int max_no_improve = 100000;\n\n        while (chrono::steady_clock::now() < limit_time && no_improve_count < max_no_improve) {\n            // Try single tile flip\n            int r = dist_idx(rng);\n            int c = dist_idx(rng);\n\n            int old_rot = rot[r][c];\n            rot[r][c] = (rot[r][c] + 1) % 4;\n\n            long long new_score = calc_score(lengths);\n\n            // Acceptance criteria\n            bool accept = false;\n            if (new_score > current_score) {\n                accept = true;\n                no_improve_count = 0;\n            } else if (new_score == current_score) {\n                accept = true;\n            } else {\n                double prob = exp((new_score - current_score) / T);\n                if (dist_prob(rng) < prob) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    copy_rot(rot, best_rot);\n                }\n            } else {\n                rot[r][c] = old_rot;\n                no_improve_count++;\n            }\n\n            // Occasionally try larger moves (flip 2-3 tiles)\n            if (no_improve_count % 100 == 0 && dist_prob(rng) < 0.1) {\n                int num_tiles = 2 + (dist_idx(rng) % 2);\n                vector<pair<int,int>> flipped;\n                \n                for (int k = 0; k < num_tiles; ++k) {\n                    int rr = dist_idx(rng);\n                    int cc = dist_idx(rng);\n                    flipped.push_back({rr, cc});\n                }\n                \n                // Apply flips\n                for (auto& p : flipped) {\n                    rot[p.first][p.second] = (rot[p.first][p.second] + 1) % 4;\n                }\n                \n                long long new_score2 = calc_score(lengths);\n                \n                if (new_score2 > current_score) {\n                    current_score = new_score2;\n                    no_improve_count = 0;\n                    if (new_score2 > best_score) {\n                        best_score = new_score2;\n                        copy_rot(rot, best_rot);\n                    }\n                } else {\n                    // Revert\n                    for (auto& p : flipped) {\n                        rot[p.first][p.second] = (rot[p.first][p.second] + 3) % 4;\n                    }\n                }\n            }\n\n            T *= 0.9995;\n            if (T < 1.0) T = 1.0;\n        }\n    }\n\n    // Final output\n    string out = \"\";\n    out.reserve(900);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            out += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << out << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <map>\n\nusing namespace std;\n\n// Global variables\nint N, T;\nvector<string> input_board;\nint board[12][12];\nint target[12][12];\nint counts[16];\nstring moves;\nint empty_r, empty_c;\n\n// Directions: U, D, L, R\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dchar[] = {'U', 'D', 'L', 'R'};\n\n// Helper to get tile value from hex char\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return 0;\n}\n\n// Check if a move is valid\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Apply a move\nvoid apply_move(char move) {\n    int dir = -1;\n    if (move == 'U') dir = 0;\n    else if (move == 'D') dir = 1;\n    else if (move == 'L') dir = 2;\n    else if (move == 'R') dir = 3;\n    \n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    \n    if (!is_valid(nr, nc)) return;\n    \n    int tile = board[nr][nc];\n    board[empty_r][empty_c] = tile;\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    moves += move;\n}\n\n// Undo a move (for backtracking in solver if needed, but we don't use it)\n// We will simulate moves directly.\n\n// BFS to find shortest path for empty square\n// Returns sequence of moves to reach (tr, tc)\n// Obstacles are tiles that are already placed correctly (solved)\n// We pass a mask or list of solved cells?\n// Actually, we can just check against the target configuration.\n// But during solving, the board is changing.\n// We need to know which cells are \"locked\" (solved).\n// We can maintain a `solved[N][N]` boolean array.\nbool solved[12][12];\n\nstring bfs_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return \"\";\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\n    \n    // Parent pointers to reconstruct path\n    // Use a map or 2D array\n    // Since N is small, 2D array is fine.\n    // Store move char to reach this cell\n    char parent_move[12][12];\n    bool visited[12][12];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        visited[i][j] = false;\n        parent_move[i][j] = 0;\n    }\n    \n    visited[empty_r][empty_c] = true;\n    \n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            // Reconstruct path\n            string path = \"\";\n            int cr = tr, cc = tc;\n            while(cr != empty_r || cc != empty_c) {\n                char m = parent_move[cr][cc];\n                path += m;\n                // Move back\n                int dir = -1;\n                if (m == 'U') dir = 0;\n                else if (m == 'D') dir = 1;\n                else if (m == 'L') dir = 2;\n                else if (m == 'R') dir = 3;\n                // Reverse direction\n                int rev_dr = -dr[dir];\n                int rev_dc = -dc[dir];\n                cr += rev_dr;\n                cc += rev_dc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (is_valid(nr, nc) && !visited[nr][nc]) {\n                // Check if this cell is solved (locked)\n                // We can only move the empty square into unsolved cells.\n                // Wait, the empty square moves into the cell where a tile is.\n                // So we are swapping empty with a tile.\n                // The tile moves to (r, c).\n                // If (r, c) is solved, we shouldn't move the tile out of it.\n                // So we cannot move empty square FROM a solved cell?\n                // No, the empty square is at (r, c). We move it to (nr, nc).\n                // This means the tile at (nr, nc) moves to (r, c).\n                // If (nr, nc) is a solved tile, we shouldn't move it.\n                // So we cannot move empty square into a solved cell.\n                if (solved[nr][nc]) continue;\n                \n                visited[nr][nc] = true;\n                parent_move[nr][nc] = dchar[i];\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\"; // Should not happen\n}\n\n// Find position of a tile\npair<int, int> find_tile(int val) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == val) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Place a tile at target position\n// This function assumes we can move the empty square freely in unsolved region\n// It brings the tile to (tr, tc)\nvoid place_tile_at(int tr, int tc) {\n    int target_val = target[tr][tc];\n    if (board[tr][tc] == target_val) return;\n    \n    // Find where the target tile is\n    auto pos = find_tile(target_val);\n    int fr = pos.first, fc = pos.second;\n    \n    // We need to move the tile from (fr, fc) to (tr, tc).\n    // This is done by moving the empty square to a position adjacent to (fr, fc),\n    // then moving the tile towards (tr, tc).\n    // However, a simpler strategy is:\n    // 1. Move empty square to (fr, fc) is not possible directly if we want to move tile.\n    //    We need to move empty square to a neighbor of (fr, fc), say (nr, nc).\n    //    Then move tile from (fr, fc) to (nr, nc).\n    //    Then repeat until tile is at (tr, tc).\n    // But this is complex to implement generally.\n    // Instead, we can use the standard approach:\n    // Move empty square to a position such that we can slide the tile into (tr, tc).\n    // Specifically, move empty square to (tr, tc) first? No, (tr, tc) is the target.\n    // We want to bring the tile to (tr, tc).\n    // So we want the empty square to be at a neighbor of (tr, tc), and the tile at the other side.\n    // Or we can move the empty square to (fr, fc) (which is currently occupied by the tile) -> Impossible.\n    // We need to move the empty square to a neighbor of (fr, fc), then swap.\n    // Let's use BFS to find a path for the empty square to reach a neighbor of (fr, fc).\n    // Then move the tile one step.\n    // Repeat until tile is at (tr, tc).\n    // But we must not disturb solved tiles.\n    // The solved tiles are locked.\n    // So we treat solved tiles as obstacles for the empty square.\n    // Also, we must not move the target tile out of the way if it's already placed?\n    // No, we are placing it.\n    \n    // Strategy:\n    // While tile is not at (tr, tc):\n    //   Find a path for empty square to a neighbor of the tile (fr, fc).\n    //   The neighbor must be in the unsolved region (or the target position).\n    //   Move empty square there.\n    //   Move tile into the empty square's position.\n    //   Update (fr, fc).\n    \n    // This is basically moving the tile towards (tr, tc) using the empty square.\n    // We need to ensure we don't block the path.\n    // Since the unsolved region is connected, this should work.\n    \n    // Optimization: Calculate a path for the tile to (tr, tc) avoiding solved tiles.\n    // Then move empty square to facilitate each step.\n    // But BFS for empty square is safer.\n    \n    while (fr != tr || fc != tc) {\n        // We want to move tile from (fr, fc) to a neighbor closer to (tr, tc).\n        // Let's find a neighbor (nr, nc) of (fr, fc) such that:\n        // 1. (nr, nc) is not solved.\n        // 2. (nr, nc) is closer to (tr, tc) or is (tr, tc).\n        // Actually, any unsolved neighbor is fine, but we want to progress.\n        // Let's try to move towards (tr, tc).\n        \n        int best_nr = -1, best_nc = -1;\n        int min_dist = 1e9;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = fr + dr[i];\n            int nc = fc + dc[i];\n            if (is_valid(nr, nc) && !solved[nr][nc]) {\n                int dist = abs(nr - tr) + abs(nc - tc);\n                if (dist < min_dist) {\n                    min_dist = dist;\n                    best_nr = nr;\n                    best_nc = nc;\n                }\n            }\n        }\n        \n        // If no neighbor is unsolved, we are stuck. But this shouldn't happen.\n        if (best_nr == -1) {\n            // Fallback: any unsolved neighbor\n            for (int i = 0; i < 4; ++i) {\n                int nr = fr + dr[i];\n                int nc = fc + dc[i];\n                if (is_valid(nr, nc) && !solved[nr][nc]) {\n                    best_nr = nr;\n                    best_nc = nc;\n                    break;\n                }\n            }\n        }\n        \n        if (best_nr == -1) break; // Should not happen\n        \n        // Move empty square to (best_nr, best_nc)\n        // But wait, (best_nr, best_nc) is currently occupied by some tile.\n        // We want to move the empty square to (best_nr, best_nc).\n        // Then swap with (fr, fc).\n        // So we need path from empty_r, empty_c to best_nr, best_nc.\n        // But we must not pass through (fr, fc) because it's occupied by the tile we want to move.\n        // Actually, BFS handles obstacles. We should mark (fr, fc) as obstacle for empty square path?\n        // No, (fr, fc) is occupied by the tile. Empty square cannot go there.\n        // So (fr, fc) is naturally an obstacle for empty square.\n        // But we need to make sure BFS doesn't consider it as a valid cell for empty square.\n        // Our BFS checks `!visited`. `board[fr][fc]` is not 0, so empty square is not there.\n        // So BFS will not go to (fr, fc).\n        // However, we need to ensure we don't move other tiles that are solved.\n        // `solved` array handles that.\n        \n        string path = bfs_to(best_nr, best_nc);\n        for (char m : path) apply_move(m);\n        \n        // Now empty square is at (best_nr, best_nc).\n        // Tile is at (fr, fc).\n        // We need to move tile to (best_nr, best_nc).\n        // This means moving empty square to (fr, fc).\n        // But (fr, fc) is adjacent to (best_nr, best_nc).\n        // So we just need to apply the reverse move of the last step?\n        // No, we need to move the tile.\n        // The move is: slide tile from (fr, fc) to (best_nr, best_nc).\n        // This corresponds to moving empty square from (best_nr, best_nc) to (fr, fc).\n        // So we find the direction from (best_nr, best_nc) to (fr, fc).\n        \n        int dir = -1;\n        if (fr == best_nr - 1) dir = 0; // Empty moves Up to (fr, fc) -> Tile moves Down\n        else if (fr == best_nr + 1) dir = 1;\n        else if (fc == best_nc - 1) dir = 2;\n        else if (fc == best_nc + 1) dir = 3;\n        \n        apply_move(dchar[dir]);\n        \n        // Update tile position\n        fr = best_nr;\n        fc = best_nc;\n        \n        if (moves.size() > T) {\n            cout << moves << endl;\n            exit(0);\n        }\n    }\n    solved[tr][tc] = true;\n}\n\n// Backtracking to find target configuration\nbool solve_target(int idx) {\n    if (idx == N * N) return true;\n    \n    int r = idx / N;\n    int c = idx % N;\n    \n    // If this is the empty square position\n    if (r == N - 1 && c == N - 1) {\n        if (counts[0] > 0) {\n            target[r][c] = 0;\n            counts[0]--;\n            if (solve_target(idx + 1)) return true;\n            counts[0]++;\n            target[r][c] = -1;\n        }\n        return false;\n    }\n    \n    // Try all tile types\n    for (int t = 1; t <= 15; ++t) {\n        if (counts[t] > 0) {\n            // Check compatibility with left neighbor\n            if (c > 0) {\n                int left = target[r][c - 1];\n                if (left != 0) {\n                    // left must have Right (4) iff t has Left (1)\n                    bool left_has_right = (left & 4) != 0;\n                    bool t_has_left = (t & 1) != 0;\n                    if (left_has_right != t_has_left) continue;\n                }\n            }\n            // Check compatibility with top neighbor\n            if (r > 0) {\n                int top = target[r - 1][c];\n                if (top != 0) {\n                    // top must have Down (8) iff t has Up (2)\n                    bool top_has_down = (top & 8) != 0;\n                    bool t_has_up = (t & 2) != 0;\n                    if (top_has_down != t_has_up) continue;\n                }\n            }\n            \n            target[r][c] = t;\n            counts[t]--;\n            if (solve_target(idx + 1)) return true;\n            counts[t]++;\n            target[r][c] = -1;\n        }\n    }\n    \n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T)) return 0;\n    \n    input_board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> input_board[i];\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(input_board[i][j]);\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n            counts[board[i][j]]++;\n        }\n    }\n    \n    // Initialize target with -1\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            target[i][j] = -1;\n            \n    // Solve target configuration\n    // We assume empty square is at (N-1, N-1) for target\n    // But we must ensure counts[0] is 1.\n    // The input has exactly one 0.\n    \n    if (!solve_target(0)) {\n        // Should not happen based on problem statement\n        return 0;\n    }\n    \n    // Initialize solved array\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            solved[i][j] = false;\n            \n    // Solve puzzle\n    // Phase 1: First N-1 rows, first N-1 cols\n    for (int r = 0; r < N - 1; ++r) {\n        for (int c = 0; c < N - 1; ++c) {\n            place_tile_at(r, c);\n            if (moves.size() > T) {\n                cout << moves << endl;\n                return 0;\n            }\n        }\n    }\n    \n    // Phase 2: Last column, first N-1 rows\n    for (int r = 0; r < N - 1; ++r) {\n        place_tile_at(r, N - 1);\n        if (moves.size() > T) {\n            cout << moves << endl;\n            return 0;\n        }\n    }\n    \n    // Phase 3: Last row, first N-1 cols\n    for (int c = 0; c < N - 1; ++c) {\n        place_tile_at(N - 1, c);\n        if (moves.size() > T) {\n            cout << moves << endl;\n            return 0;\n        }\n    }\n    \n    // The empty square should be at (N-1, N-1) now.\n    // If not, it's fine as long as tiles are correct.\n    // But our target has 0 at (N-1, N-1).\n    // So the last cell is automatically correct.\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\n// Cross product to determine which side of line a point is on\nint point_side(const Line& line, const Point& p) {\n    long long dx = line.qx - line.px;\n    long long dy = line.qy - line.py;\n    long long px = p.x - line.px;\n    long long py = p.y - line.py;\n    long long cp = dx * py - dy * px;\n    if (cp > 0) return 1;\n    if (cp < 0) return -1;\n    return 0;\n}\n\n// Calculate score for current cut configuration\nint calculate_score(const vector<Point>& strawberries, \n                    const vector<Line>& cuts, \n                    const vector<int>& a) {\n    int n = strawberries.size();\n    int k = cuts.size();\n    \n    // For each strawberry, determine its region (bitmask of which side of each cut)\n    vector<int> region(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < k; j++) {\n            int side = point_side(cuts[j], strawberries[i]);\n            if (side == 1) {\n                region[i] |= (1 << j);\n            }\n            // If side == 0, strawberry is on the line (doesn't count)\n        }\n    }\n    \n    // Count strawberries in each region\n    map<int, int> region_count;\n    for (int i = 0; i < n; i++) {\n        region_count[region[i]]++;\n    }\n    \n    // Calculate score\n    int total_attendees = 0;\n    for (int d = 1; d <= 10; d++) {\n        total_attendees += a[d];\n    }\n    \n    if (total_attendees == 0) return 0;\n    \n    // Count pieces with each number of strawberries\n    vector<int> b(11, 0);\n    for (const auto& [region_id, count] : region_count) {\n        if (count >= 1 && count <= 10) {\n            b[count]++;\n        }\n    }\n    \n    int distributed = 0;\n    for (int d = 1; d <= 10; d++) {\n        distributed += min(a[d], b[d]);\n    }\n    \n    return round(1e6 * distributed / total_attendees);\n}\n\n// Generate a random line\nLine generate_random_line(mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    line.px = dist(gen);\n    line.py = dist(gen);\n    line.qx = dist(gen);\n    line.qy = dist(gen);\n    \n    // Ensure points are different\n    while (line.px == line.qx && line.py == line.qy) {\n        line.qx = dist(gen);\n        line.qy = dist(gen);\n    }\n    \n    return line;\n}\n\n// Generate a line that passes between two strawberries\nLine generate_separating_line(const Point& p1, const Point& p2, \n                              mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    \n    // Create a line perpendicular to the segment p1-p2\n    long long dx = p2.x - p1.x;\n    long long dy = p2.y - p1.y;\n    \n    // Midpoint\n    long long mx = (p1.x + p2.x) / 2;\n    long long my = (p1.y + p2.y) / 2;\n    \n    // Perpendicular direction\n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    // Add some randomness\n    long long offset_x = dist(gen) % 100000 - 50000;\n    long long offset_y = dist(gen) % 100000 - 50000;\n    \n    line.px = mx + pdx + offset_x;\n    line.py = my + pdy + offset_y;\n    line.qx = mx - pdx + offset_x;\n    line.qy = my - pdy + offset_y;\n    \n    return line;\n}\n\n// Generate a line that separates a specific group of strawberries\nLine generate_group_separating_line(const vector<Point>& strawberries,\n                                    const vector<int>& group_indices,\n                                    mt19937& gen, uniform_int_distribution<long long>& dist) {\n    if (group_indices.empty()) {\n        return generate_random_line(gen, dist);\n    }\n    \n    // Find centroid of the group\n    long long cx = 0, cy = 0;\n    for (int idx : group_indices) {\n        cx += strawberries[idx].x;\n        cy += strawberries[idx].y;\n    }\n    cx /= group_indices.size();\n    cy /= group_indices.size();\n    \n    // Find a point outside the group\n    int outside_idx = -1;\n    for (int i = 0; i < (int)strawberries.size(); i++) {\n        bool in_group = false;\n        for (int gidx : group_indices) {\n            if (gidx == i) {\n                in_group = true;\n                break;\n            }\n        }\n        if (!in_group) {\n            outside_idx = i;\n            break;\n        }\n    }\n    \n    if (outside_idx == -1) {\n        return generate_random_line(gen, dist);\n    }\n    \n    // Create line perpendicular to centroid-outside direction\n    long long dx = strawberries[outside_idx].x - cx;\n    long long dy = strawberries[outside_idx].y - cy;\n    \n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    long long offset_x = dist(gen) % 50000 - 25000;\n    long long offset_y = dist(gen) % 50000 - 25000;\n    \n    Line line;\n    line.px = cx + pdx + offset_x;\n    line.py = cy + pdy + offset_y;\n    line.qx = cx - pdx + offset_x;\n    line.qy = cy - pdy + offset_y;\n    \n    return line;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(11);\n    for (int i = 1; i <= 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<long long> dist(-1000000000, 1000000000);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = start_time + chrono::milliseconds(2800);\n    \n    vector<Line> best_cuts;\n    int best_score = 0;\n    \n    // Multiple restart strategy\n    int num_restarts = 20;\n    int restarts_done = 0;\n    \n    while (restarts_done < num_restarts && chrono::steady_clock::now() < time_limit) {\n        restarts_done++;\n        vector<Line> cuts;\n        \n        // Phase 1: Generate initial random cuts\n        for (int i = 0; i < min(K, 20); i++) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            cuts.push_back(generate_random_line(gen, dist));\n        }\n        \n        // Phase 2: Iterative improvement\n        int no_improve_count = 0;\n        int max_no_improve = 500;\n        \n        while (chrono::steady_clock::now() < time_limit && no_improve_count < max_no_improve) {\n            no_improve_count++;\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            Line best_new_cut;\n            int best_new_score = old_score;\n            int best_idx = -1;\n            \n            // Try adding a cut\n            if (cuts.size() < (size_t)K) {\n                for (int trial = 0; trial < 50; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    Line new_cut;\n                    if (gen() % 3 == 0 && N >= 2) {\n                        // Strategic cut between two random strawberries\n                        int i1 = gen() % N;\n                        int i2 = gen() % N;\n                        while (i2 == i1) i2 = gen() % N;\n                        new_cut = generate_separating_line(strawberries[i1], strawberries[i2], gen, dist);\n                    } else {\n                        new_cut = generate_random_line(gen, dist);\n                    }\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts.push_back(new_cut);\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = -1; // -1 means add\n                    }\n                }\n            }\n            \n            // Try replacing a cut\n            if (cuts.size() >= 1) {\n                for (int trial = 0; trial < 30; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    int idx = gen() % cuts.size();\n                    Line new_cut = generate_random_line(gen, dist);\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts[idx] = new_cut;\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = idx;\n                    }\n                }\n            }\n            \n            // Apply best improvement\n            if (best_new_score > old_score) {\n                no_improve_count = 0;\n                if (best_idx == -1) {\n                    cuts.push_back(best_new_cut);\n                } else {\n                    cuts[best_idx] = best_new_cut;\n                }\n            }\n        }\n        \n        // Try removing unnecessary cuts\n        for (int i = (int)cuts.size() - 1; i >= 0; i--) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.erase(test_cuts.begin() + i);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n        \n        // Update best solution\n        int current_score = calculate_score(strawberries, cuts, a);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_cuts = cuts;\n        }\n    }\n    \n    // Output\n    cout << best_cuts.size() << endl;\n    for (const auto& cut : best_cuts) {\n        cout << cut.px << \" \" << cut.py << \" \" << cut.qx << \" \" << cut.qy << endl;\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Point structure\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\n// Rectangle edge representation\nstruct Edge {\n    int x1, y1, x2, y2;\n    bool operator<(const Edge& other) const {\n        if (x1 != other.x1) return x1 < other.x1;\n        if (y1 != other.y1) return y1 < other.y1;\n        if (x2 != other.x2) return x2 < other.x2;\n        return y2 < other.y2;\n    }\n};\n\n// Operation record\nstruct Operation {\n    Point p1, p2, p3, p4;\n    double score;\n};\n\nclass RectJoinSolver {\nprivate:\n    int N, M;\n    set<Point> dots;\n    set<Edge> drawnEdges;\n    vector<Operation> operations;\n    int cx, cy;\n    \n    // Calculate weight of a point\n    double weight(int x, int y) const {\n        return (double)(x - cx) * (x - cx) + (double)(y - cy) * (y - cy) + 1.0;\n    }\n    \n    // Check if point is within grid\n    bool inGrid(int x, int y) const {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    }\n    \n    // Check if point has a dot\n    bool hasDot(int x, int y) const {\n        return dots.count({x, y}) > 0;\n    }\n    \n    // Normalize edge for consistent representation\n    Edge normalizeEdge(int x1, int y1, int x2, int y2) const {\n        if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n            return {x2, y2, x1, y1};\n        }\n        return {x1, y1, x2, y2};\n    }\n    \n    // Check if edge already exists\n    bool edgeExists(int x1, int y1, int x2, int y2) const {\n        return drawnEdges.count(normalizeEdge(x1, y1, x2, y2)) > 0;\n    }\n    \n    // Add edge to drawn edges\n    void addEdge(int x1, int y1, int x2, int y2) {\n        drawnEdges.insert(normalizeEdge(x1, y1, x2, y2));\n    }\n    \n    // Check if two edges share a segment of positive length\n    bool edgesOverlap(const Edge& e1, const Edge& e2) const {\n        // Check if edges are on the same line\n        if (e1.x1 == e1.x2 && e2.x1 == e2.x2) {\n            // Both vertical\n            if (e1.x1 != e2.x1) return false;\n            int yMin1 = min(e1.y1, e1.y2), yMax1 = max(e1.y1, e1.y2);\n            int yMin2 = min(e2.y1, e2.y2), yMax2 = max(e2.y1, e2.y2);\n            int overlapMin = max(yMin1, yMin2), overlapMax = min(yMax1, yMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        if (e1.y1 == e1.y2 && e2.y1 == e2.y2) {\n            // Both horizontal\n            if (e1.y1 != e2.y1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            int overlapMin = max(xMin1, xMin2), overlapMax = min(xMax1, xMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        return false;\n    }\n    \n    // Check if any edge of rectangle overlaps with existing edges\n    bool rectangleOverlaps(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const {\n        Edge edges[4] = {\n            normalizeEdge(x1, y1, x2, y2),\n            normalizeEdge(x2, y2, x3, y3),\n            normalizeEdge(x3, y3, x4, y4),\n            normalizeEdge(x4, y4, x1, y1)\n        };\n        \n        for (const auto& e : edges) {\n            for (const auto& existing : drawnEdges) {\n                if (edgesOverlap(e, existing)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n    \n    // Check if there are dots on rectangle perimeter (excluding the 3 existing dots)\n    bool hasDotsOnPerimeter(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,\n                           const Point& p2, const Point& p3, const Point& p4) const {\n        auto checkEdge = [&](int x1, int y1, int x2, int y2) {\n            int dx = x2 - x1, dy = y2 - y1;\n            int steps = max(abs(dx), abs(dy));\n            for (int i = 1; i < steps; i++) {\n                int x = x1 + dx * i / steps;\n                int y = y1 + dy * i / steps;\n                // Skip the three existing dots\n                if ((x == p2.x && y == p2.y) || (x == p3.x && y == p3.y) || \n                    (x == p4.x && y == p4.y)) continue;\n                if (hasDot(x, y)) return true;\n            }\n            return false;\n        };\n        \n        return checkEdge(x1, y1, x2, y2) ||\n               checkEdge(x2, y2, x3, y3) ||\n               checkEdge(x3, y3, x4, y4) ||\n               checkEdge(x4, y4, x1, y1);\n    }\n    \n    // Find 4th point for rectangle given 3 points\n    // Returns true if valid rectangle can be formed\n    bool findRectanglePoint(const Point& p2, const Point& p3, const Point& p4, Point& p1) const {\n        // Try all 6 permutations to find which 3 points form 3 corners of rectangle\n        // and calculate the 4th point\n        \n        // For axis-aligned rectangle: opposite corners have same x or same y\n        // For 45-degree rectangle: diagonal properties differ\n        \n        // Case 1: p2, p3, p4 are consecutive corners\n        // p1 should complete the rectangle\n        \n        // Check if p2-p3 and p3-p4 are perpendicular\n        int dx1 = p3.x - p2.x, dy1 = p3.y - p2.y;\n        int dx2 = p4.x - p3.x, dy2 = p4.y - p3.y;\n        \n        // For axis-aligned: one of dx1,dy1 is 0, one of dx2,dy2 is 0\n        // For 45-degree: |dx1| == |dy1| and |dx2| == |dy2|\n        \n        // Calculate potential p1 for different configurations\n        // Rectangle: p1, p2, p3, p4 in order\n        \n        // Configuration 1: p2, p3, p4 are corners, find p1\n        // p1 = p2 + p4 - p3 (vector addition)\n        p1.x = p2.x + p4.x - p3.x;\n        p1.y = p2.y + p4.y - p3.y;\n        \n        if (!inGrid(p1.x, p1.y)) return false;\n        \n        // Verify rectangle properties\n        int dx21 = p1.x - p2.x, dy21 = p1.y - p2.y;\n        int dx34 = p4.x - p3.x, dy34 = p4.y - p3.y;\n        int dx14 = p4.x - p1.x, dy14 = p4.y - p1.y;\n        int dx23 = p3.x - p2.x, dy23 = p3.y - p2.y;\n        \n        // Check if opposite sides are equal and parallel\n        bool axisAligned = (dx21 == dx34 && dy21 == dy34) && \n                          (dx14 == dx23 && dy14 == dy23);\n        \n        bool diagonal45 = (abs(dx21) == abs(dy21) && abs(dx14) == abs(dy14)) &&\n                         (abs(dx34) == abs(dy34) && abs(dx23) == abs(dy23));\n        \n        if (!axisAligned && !diagonal45) return false;\n        \n        return true;\n    }\n    \n    // Find all valid moves\n    vector<Operation> findValidMoves() {\n        vector<Operation> validMoves;\n        vector<Point> dotList(dots.begin(), dots.end());\n        int nDots = dotList.size();\n        \n        // Try all combinations of 3 dots\n        for (int i = 0; i < nDots; i++) {\n            for (int j = i + 1; j < nDots; j++) {\n                for (int k = j + 1; k < nDots; k++) {\n                    Point p2 = dotList[i];\n                    Point p3 = dotList[j];\n                    Point p4 = dotList[k];\n                    \n                    // Try to find p1 that completes rectangle\n                    Point p1;\n                    if (!findRectanglePoint(p2, p3, p4, p1)) continue;\n                    \n                    // p1 must not have a dot yet\n                    if (hasDot(p1.x, p1.y)) continue;\n                    \n                    // Check rectangle overlaps\n                    if (rectangleOverlaps(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y)) continue;\n                    \n                    // Check dots on perimeter\n                    if (hasDotsOnPerimeter(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y,\n                                          p2, p3, p4)) continue;\n                    \n                    Operation op;\n                    op.p1 = p1;\n                    op.p2 = p2;\n                    op.p3 = p3;\n                    op.p4 = p4;\n                    op.score = weight(p1.x, p1.y);\n                    \n                    validMoves.push_back(op);\n                }\n            }\n        }\n        \n        return validMoves;\n    }\n    \n    // Execute a move\n    void executeMove(const Operation& op) {\n        dots.insert(op.p1);\n        addEdge(op.p1.x, op.p1.y, op.p2.x, op.p2.y);\n        addEdge(op.p2.x, op.p2.y, op.p3.x, op.p3.y);\n        addEdge(op.p3.x, op.p3.y, op.p4.x, op.p4.y);\n        addEdge(op.p4.x, op.p4.y, op.p1.x, op.p1.y);\n        operations.push_back(op);\n    }\n    \npublic:\n    RectJoinSolver(int n, int m, const vector<pair<int,int>>& initial) {\n        N = n; M = m;\n        cx = (N - 1) / 2;\n        cy = (N - 1) / 2;\n        \n        for (const auto& p : initial) {\n            dots.insert({p.first, p.second});\n        }\n    }\n    \n    void solve() {\n        auto startTime = chrono::steady_clock::now();\n        auto timeLimit = chrono::seconds(4); // Leave margin for 5 sec limit\n        \n        int maxIterations = 10000;\n        int iteration = 0;\n        \n        while (iteration < maxIterations) {\n            auto currentTime = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::seconds>(currentTime - startTime).count() >= 4) {\n                break;\n            }\n            \n            vector<Operation> moves = findValidMoves();\n            \n            if (moves.empty()) break;\n            \n            // Sort by weight (higher weight first)\n            sort(moves.begin(), moves.end(), [](const Operation& a, const Operation& b) {\n                return a.score > b.score;\n            });\n            \n            // Execute best move\n            executeMove(moves[0]);\n            iteration++;\n        }\n    }\n    \n    void output() const {\n        cout << operations.size() << endl;\n        for (const auto& op : operations) {\n            cout << op.p1.x << \" \" << op.p1.y << \" \"\n                 << op.p2.x << \" \" << op.p2.y << \" \"\n                 << op.p3.x << \" \" << op.p3.y << \" \"\n                 << op.p4.x << \" \" << op.p4.y << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    \n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initial[i].first >> initial[i].second;\n    }\n    \n    RectJoinSolver solver(N, M, initial);\n    solver.solve();\n    solver.output();\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Board representation: 10x10 grid, 0=empty, 1-3=flavors\nstruct Board {\n    int grid[10][10];\n    \n    Board() {\n        for(int i = 0; i < 10; i++)\n            for(int j = 0; j < 10; j++)\n                grid[i][j] = 0;\n    }\n};\n\n// Count connected components and calculate score\nlong long calculateScore(const Board& b) {\n    int visited[10][10];\n    for(int i = 0; i < 10; i++)\n        for(int j = 0; j < 10; j++)\n            visited[i][j] = 0;\n    \n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n    \n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] != 0 && !visited[i][j]) {\n                // BFS for connected component\n                int flavor = b.grid[i][j];\n                int size = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = 1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    size++;\n                    \n                    for(int d = 0; d < 4; d++) {\n                        int nr = r + dr[d];\n                        int nc = c + dc[d];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10) {\n                            if(!visited[nr][nc] && b.grid[nr][nc] == flavor) {\n                                visited[nr][nc] = 1;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Tilt board in given direction\nvoid tilt(Board& b, char dir) {\n    Board newb = b;\n    \n    if(dir == 'F') { // Forward (up)\n        for(int j = 0; j < 10; j++) {\n            int write = 0;\n            for(int i = 0; i < 10; i++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int i = write; i < 10; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'B') { // Backward (down)\n        for(int j = 0; j < 10; j++) {\n            int write = 9;\n            for(int i = 9; i >= 0; i--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int i = 0; i < write; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'L') { // Left\n        for(int i = 0; i < 10; i++) {\n            int write = 0;\n            for(int j = 0; j < 10; j++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int j = write; j < 10; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'R') { // Right\n        for(int i = 0; i < 10; i++) {\n            int write = 9;\n            for(int j = 9; j >= 0; j--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int j = 0; j < write; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    }\n    \n    b = newb;\n}\n\n// Count candies of each flavor\nvoid countFlavors(const Board& b, int& f1, int& f2, int& f3) {\n    f1 = f2 = f3 = 0;\n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] == 1) f1++;\n            else if(b.grid[i][j] == 2) f2++;\n            else if(b.grid[i][j] == 3) f3++;\n        }\n    }\n}\n\n// Calculate normalized score\ndouble getNormalizedScore(const Board& b) {\n    int f1, f2, f3;\n    countFlavors(b, f1, f2, f3);\n    long long numerator = calculateScore(b);\n    long long denominator = (long long)f1*f1 + (long long)f2*f2 + (long long)f3*f3;\n    if(denominator == 0) return 0;\n    return (double)numerator / denominator;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read all flavors in advance\n    vector<int> flavors(100);\n    for(int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    Board board;\n    char directions[] = {'F', 'B', 'L', 'R'};\n    \n    // Process each candy placement\n    for(int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Place candy in p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int count = 0;\n        for(int i = 0; i < 10; i++) {\n            for(int j = 0; j < 10; j++) {\n                if(board.grid[i][j] == 0) {\n                    count++;\n                    if(count == p) {\n                        board.grid[i][j] = flavors[t];\n                        break;\n                    }\n                }\n                if(count == p) break;\n            }\n            if(count == p) break;\n        }\n        \n        // Skip output for last step (nothing happens)\n        if(t == 99) {\n            cout << \"F\" << endl;\n            continue;\n        }\n        \n        // Try all 4 directions and pick the best\n        double bestScore = -1;\n        char bestDir = 'F';\n        \n        for(char dir : directions) {\n            Board temp = board;\n            tilt(temp, dir);\n            double score = getNormalizedScore(temp);\n            \n            if(score > bestScore) {\n                bestScore = score;\n                bestDir = dir;\n            }\n        }\n        \n        // Apply the best direction\n        tilt(board, bestDir);\n        cout << bestDir << endl;\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <bitset>\n\nusing namespace std;\n\n// Maximum N is 100\nconst int MAX_N = 100;\n\nstruct Graph {\n    int n;\n    vector<bitset<MAX_N>> adj;\n\n    Graph(int n) : n(n), adj(n) {}\n\n    // Parse from string\n    static Graph from_string(int n, const string& s) {\n        Graph g(n);\n        int idx = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (idx < s.size()) {\n                    if (s[idx] == '1') {\n                        g.adj[i][j] = 1;\n                        g.adj[j][i] = 1;\n                    }\n                }\n                idx++;\n            }\n        }\n        return g;\n    }\n\n    // To string\n    string to_string() const {\n        string s;\n        s.reserve(n * (n - 1) / 2);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                s += (adj[i][j] ? '1' : '0');\n            }\n        }\n        return s;\n    }\n\n    // Generate random graph with probability p\n    static Graph random(int n, double p, mt19937& gen) {\n        Graph g(n);\n        uniform_real_distribution<double> dist(0.0, 1.0);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (dist(gen) < p) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                }\n            }\n        }\n        return g;\n    }\n};\n\nstruct Features {\n    double edge_count;\n    double triangle_count;\n    double sum_sq_deg;\n    double sum_cube_deg;\n    vector<double> sorted_degrees;\n\n    Features() : edge_count(0), triangle_count(0), sum_sq_deg(0), sum_cube_deg(0) {}\n};\n\nFeatures compute_features(const Graph& g) {\n    Features f;\n    f.edge_count = 0;\n    f.sum_sq_deg = 0;\n    f.sum_cube_deg = 0;\n    f.sorted_degrees.resize(g.n);\n\n    vector<int> deg(g.n, 0);\n    for (int i = 0; i < g.n; ++i) {\n        deg[i] = g.adj[i].count();\n        f.edge_count += deg[i];\n        f.sum_sq_deg += (double)deg[i] * deg[i];\n        f.sum_cube_deg += (double)deg[i] * deg[i] * deg[i];\n    }\n    f.edge_count /= 2.0;\n    f.sorted_degrees = deg;\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Count triangles\n    // O(N^3 / 64) using bitsets\n    f.triangle_count = 0;\n    for (int i = 0; i < g.n; ++i) {\n        for (int j = i + 1; j < g.n; ++j) {\n            if (g.adj[i][j]) {\n                // Count common neighbors of i and j\n                // Only count neighbors k > j to avoid overcounting\n                // Actually, standard way: sum over i<j<k.\n                // Here we iterate i, j. We need k > j.\n                // bitset::count counts all set bits. We need to mask k > j.\n                // Since we only care about existence, we can just iterate k.\n                // Optimization: bitset AND.\n                // But bitset doesn't support range count efficiently.\n                // For N=100, simple loop is fast enough.\n                for (int k = j + 1; k < g.n; ++k) {\n                    if (g.adj[i][k] && g.adj[j][k]) {\n                        f.triangle_count++;\n                    }\n                }\n            }\n        }\n    }\n    return f;\n}\n\n// Expected features under noise epsilon\nFeatures compute_expected_features(const Graph& g, double eps) {\n    Features f;\n    int n = g.n;\n    int total_edges = n * (n - 1) / 2;\n\n    // Expected Edge Count\n    // E = E_g * (1 - eps) + (Total - E_g) * eps\n    //   = E_g * (1 - 2*eps) + Total * eps\n    double E_g = g.adj[0].count() / 2.0; // Not accurate, need to sum properly\n    // Recompute E_g accurately\n    long long e_g = 0;\n    for(int i=0; i<n; ++i) e_g += g.adj[i].count();\n    e_g /= 2;\n    f.edge_count = e_g * (1.0 - 2.0 * eps) + total_edges * eps;\n\n    // Expected Degree Sequence\n    // E[d_i] = d_i * (1 - 2*eps) + (n - 1) * eps\n    vector<double> exp_deg(n);\n    for (int i = 0; i < n; ++i) {\n        double d_i = (double)g.adj[i].count();\n        exp_deg[i] = d_i * (1.0 - 2.0 * eps) + (n - 1) * eps;\n    }\n    f.sorted_degrees = exp_deg;\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Expected Sum Sq Deg\n    // E[d_i^2] = d_i^2 (1-eps)^2 + (n-1-d_i)^2 eps^2 + 2 d_i (n-1-d_i) eps (1-eps)\n    // Actually, d_i is sum of Bernoulli trials.\n    // Var(d_i) = (n-1) eps (1-eps).\n    // E[d_i^2] = Var(d_i) + E[d_i]^2.\n    f.sum_sq_deg = 0;\n    f.sum_cube_deg = 0; // Harder to compute exact expectation for cube.\n    // Let's use E[d_i]^2 approximation for sum_sq_deg? No, use Var + Mean^2.\n    double var_deg = (n - 1) * eps * (1.0 - eps);\n    for (int i = 0; i < n; ++i) {\n        double mean_d = exp_deg[i];\n        f.sum_sq_deg += var_deg + mean_d * mean_d;\n        // For cube, approximation: E[X^3] approx E[X]^3 + 3 E[X] Var[X]\n        // This is for Gaussian. Bernoulli sum is close to Gaussian for large n.\n        f.sum_cube_deg += mean_d * mean_d * mean_d + 3.0 * mean_d * var_deg;\n    }\n\n    // Expected Triangle Count\n    // For each triplet, calculate prob of forming triangle.\n    // Let k be edges in G among triplet.\n    // Prob = (1-eps)^3 if k=3\n    //       eps*(1-eps)^2 if k=2\n    //       eps^2*(1-eps) if k=1\n    //       eps^3 if k=0\n    // We can iterate all triplets.\n    f.triangle_count = 0;\n    double p0 = pow(eps, 3);\n    double p1 = pow(eps, 2) * (1.0 - eps);\n    double p2 = eps * pow(1.0 - eps, 2);\n    double p3 = pow(1.0 - eps, 3);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            for (int k = j + 1; k < n; ++k) {\n                int edges = 0;\n                if (g.adj[i][j]) edges++;\n                if (g.adj[i][k]) edges++;\n                if (g.adj[j][k]) edges++;\n                if (edges == 0) f.triangle_count += p0;\n                else if (edges == 1) f.triangle_count += p1;\n                else if (edges == 2) f.triangle_count += p2;\n                else f.triangle_count += p3;\n            }\n        }\n    }\n\n    return f;\n}\n\ndouble feature_distance(const Features& f1, const Features& f2) {\n    double dist = 0.0;\n    // Weighted distance\n    // Normalize by expected variance?\n    // For simplicity, use Euclidean on normalized features.\n    // We assume features have different scales.\n    // Edge count ~ N^2/2. Triangles ~ N^3/6.\n    // Let's normalize by N^2 and N^3.\n    \n    // Actually, just raw distance might be dominated by high magnitude features.\n    // Let's use relative differences or standard normalization.\n    // For this heuristic, let's use simple Euclidean on scaled features.\n    \n    // Scale factors\n    double s_ec = 1.0; // Edge count\n    double s_tc = 1.0 / 100.0; // Triangle count usually larger\n    double s_sq = 1.0 / 1000.0; // Sum sq deg\n    double s_cb = 1.0 / 10000.0; // Sum cube deg\n    double s_deg = 1.0 / 10.0; // Degree (0 to N)\n\n    dist += s_ec * (f1.edge_count - f2.edge_count) * (f1.edge_count - f2.edge_count);\n    dist += s_tc * (f1.triangle_count - f2.triangle_count) * (f1.triangle_count - f2.triangle_count);\n    dist += s_sq * (f1.sum_sq_deg - f2.sum_sq_deg) * (f1.sum_sq_deg - f2.sum_sq_deg);\n    dist += s_cb * (f1.sum_cube_deg - f2.sum_cube_deg) * (f1.sum_cube_deg - f2.sum_cube_deg);\n    \n    for (size_t i = 0; i < f1.sorted_degrees.size(); ++i) {\n        dist += s_deg * (f1.sorted_degrees[i] - f2.sorted_degrees[i]) * (f1.sorted_degrees[i] - f2.sorted_degrees[i]);\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Optimization Phase\n    // We want to find N and M graphs that maximize score.\n    // Score = 0.9^E / N.\n    // We estimate E based on margin.\n    \n    int best_N = 40;\n    vector<Graph> best_Gs;\n    vector<Features> best_ExpectedFeatures;\n    double best_score = -1.0;\n\n    // Try different N\n    // Time limit 5s. Let's spend ~3s optimizing.\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 3.0; // seconds\n\n    // Search space for N\n    vector<int> N_candidates = {20, 30, 40, 50, 60, 70, 80, 90};\n    // If M is large, we might need larger N.\n    if (M > 50) N_candidates = {40, 50, 60, 70, 80, 90};\n    if (M > 80) N_candidates = {50, 60, 70, 80, 90};\n\n    for (int N : N_candidates) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        // Generate candidate graphs\n        // We need M graphs. Generate pool of size 5*M.\n        int pool_size = min(500, M * 5);\n        vector<Graph> candidates;\n        candidates.reserve(pool_size);\n        \n        // Density distribution\n        // Random graphs with varying densities are good.\n        for (int i = 0; i < pool_size; ++i) {\n            double p = (double)rand() / RAND_MAX; // Simple random density\n            // Better: uniform random edges\n            // Let's just use random edges with p=0.5 for variety\n            // Or p from 0.1 to 0.9\n            p = 0.1 + 0.8 * ((double)rand() / RAND_MAX);\n            candidates.push_back(Graph::random(N, p, gen));\n        }\n\n        // Compute expected features for candidates\n        vector<Features> cand_expected(pool_size);\n        for (int i = 0; i < pool_size; ++i) {\n            cand_expected[i] = compute_expected_features(candidates[i], eps);\n        }\n\n        // Greedy selection of M graphs to maximize min distance\n        vector<int> selected_indices;\n        selected_indices.reserve(M);\n        \n        // Pick first one arbitrarily\n        selected_indices.push_back(0);\n        \n        for (int i = 1; i < M; ++i) {\n            int best_idx = -1;\n            double max_min_dist = -1.0;\n            \n            for (int j = 0; j < pool_size; ++j) {\n                if (find(selected_indices.begin(), selected_indices.end(), j) != selected_indices.end()) continue;\n                \n                double min_d = 1e18;\n                for (int k : selected_indices) {\n                    double d = feature_distance(cand_expected[j], cand_expected[k]);\n                    if (d < min_d) min_d = d;\n                }\n                \n                if (min_d > max_min_dist) {\n                    max_min_dist = min_d;\n                    best_idx = j;\n                }\n            }\n            \n            if (best_idx != -1) {\n                selected_indices.push_back(best_idx);\n            } else {\n                // Fallback: pick random\n                int r = rand() % pool_size;\n                while (find(selected_indices.begin(), selected_indices.end(), r) != selected_indices.end()) r = rand() % pool_size;\n                selected_indices.push_back(r);\n            }\n        }\n\n        // Estimate Margin\n        double min_pair_dist = 1e18;\n        for (size_t i = 0; i < selected_indices.size(); ++i) {\n            for (size_t j = i + 1; j < selected_indices.size(); ++j) {\n                double d = feature_distance(cand_expected[selected_indices[i]], cand_expected[selected_indices[j]]);\n                if (d < min_pair_dist) min_pair_dist = d;\n            }\n        }\n\n        // Estimate Error E\n        // If min_pair_dist is large, E is small.\n        // Heuristic: E = max(0, 100 * exp(-min_pair_dist / 10.0))\n        // This is very rough.\n        // Let's assume if min_pair_dist > 5000, E=0.\n        // The scale of distance depends on N.\n        // Let's just use min_pair_dist as a proxy for quality.\n        // We want to maximize Quality / N.\n        // Quality = min_pair_dist.\n        // Score = 0.9^E / N.\n        // Let's assume E = 100 * exp(-min_pair_dist / 5000.0).\n        // If min_pair_dist is very small, E=100.\n        \n        double E_est = 0.0;\n        if (min_pair_dist < 1000.0) {\n             E_est = 100.0 * exp(-min_pair_dist / 500.0);\n        } else {\n             E_est = 100.0 * exp(-min_pair_dist / 5000.0);\n        }\n        if (E_est < 0.0) E_est = 0.0;\n        if (E_est > 100.0) E_est = 100.0;\n\n        double score = pow(0.9, E_est) / N;\n        \n        // We prefer smaller N if score is similar\n        if (score > best_score || (abs(score - best_score) < 1e-9 && N < best_N)) {\n            best_score = score;\n            best_N = N;\n            best_Gs.clear();\n            best_ExpectedFeatures.clear();\n            for (int idx : selected_indices) {\n                best_Gs.push_back(candidates[idx]);\n                best_ExpectedFeatures.push_back(cand_expected[idx]);\n            }\n        }\n    }\n\n    // Output N and Graphs\n    cout << best_N << endl;\n    for (const auto& g : best_Gs) {\n        cout << g.to_string() << endl;\n    }\n    cout.flush();\n\n    // Query Processing\n    // We have best_Gs and best_ExpectedFeatures.\n    // For each query, compute features of H, find closest.\n    \n    // Precompute expected features for best_Gs (already done in best_ExpectedFeatures)\n    \n    string H_str;\n    for (int q = 0; q < 100; ++q) {\n        cin >> H_str;\n        Graph H = Graph::from_string(best_N, H_str);\n        Features h_feat = compute_features(H);\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double d = feature_distance(h_feat, best_ExpectedFeatures[k]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint N, M, D, K;\nstruct Edge {\n    int u, v, w, id;\n};\nvector<Edge> edges;\nvector<int> edge_day;\nvector<vector<long long>> dist_original;\nmt19937 rng;\n\nvoid init_rng() {\n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n}\n\nvoid calc_original_distances() {\n    dist_original.assign(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int i = 1; i <= N; i++) {\n        dist_original[i][i] = 0;\n    }\n    \n    for (auto& e : edges) {\n        dist_original[e.u][e.v] = min(dist_original[e.u][e.v], (long long)e.w);\n        dist_original[e.v][e.u] = min(dist_original[e.v][e.u], (long long)e.w);\n    }\n    \n    for (int k = 1; k <= N; k++) {\n        for (int i = 1; i <= N; i++) {\n            if (dist_original[i][k] == 1e18) continue;\n            for (int j = 1; j <= N; j++) {\n                if (dist_original[k][j] == 1e18) continue;\n                dist_original[i][j] = min(dist_original[i][j], dist_original[i][k] + dist_original[k][j]);\n            }\n        }\n    }\n}\n\nlong long calc_frustration_day(int k) {\n    vector<vector<long long>> dist(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int i = 1; i <= N; i++) {\n        dist[i][i] = 0;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        if (edge_day[i] != k) {\n            dist[edges[i].u][edges[i].v] = min(dist[edges[i].u][edges[i].v], (long long)edges[i].w);\n            dist[edges[i].v][edges[i].u] = min(dist[edges[i].v][edges[i].u], (long long)edges[i].w);\n        }\n    }\n    \n    for (int k_iter = 1; k_iter <= N; k_iter++) {\n        for (int i = 1; i <= N; i++) {\n            if (dist[i][k_iter] == 1e18) continue;\n            for (int j = 1; j <= N; j++) {\n                if (dist[k_iter][j] == 1e18) continue;\n                dist[i][j] = min(dist[i][j], dist[i][k_iter] + dist[k_iter][j]);\n            }\n        }\n    }\n    \n    long long total_increase = 0;\n    for (int i = 1; i <= N; i++) {\n        for (int j = 1; j <= N; j++) {\n            if (i != j) {\n                if (dist[i][j] >= 1e9) {\n                    total_increase += 1e9;\n                } else {\n                    total_increase += max(0LL, dist[i][j] - dist_original[i][j]);\n                }\n            }\n        }\n    }\n    \n    return total_increase;\n}\n\nlong long calc_total_frustration() {\n    long long total = 0;\n    for (int k = 1; k <= D; k++) {\n        total += calc_frustration_day(k);\n    }\n    return total;\n}\n\nvoid init_solution() {\n    edge_day.assign(M, 0);\n    vector<int> day_count(D + 1, 0);\n    \n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    shuffle(edge_order.begin(), edge_order.end(), rng);\n    \n    for (int i : edge_order) {\n        int best_day = 1;\n        for (int d = 2; d <= D; d++) {\n            if (day_count[d] < day_count[best_day]) {\n                best_day = d;\n            }\n        }\n        edge_day[i] = best_day;\n        day_count[best_day]++;\n    }\n}\n\nvoid local_search() {\n    long long best_frustration = calc_total_frustration();\n    vector<int> best_day = edge_day;\n    \n    int no_improve = 0;\n    int max_no_improve = 300;\n    \n    while (no_improve < max_no_improve) {\n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) continue;\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        long long new_frustration = calc_total_frustration();\n        \n        if (new_frustration < best_frustration) {\n            best_frustration = new_frustration;\n            best_day = edge_day;\n            no_improve = 0;\n        } else {\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            no_improve++;\n        }\n    }\n    \n    edge_day = best_day;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> D >> K;\n    \n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i;\n    }\n    \n    vector<int> x(N + 1), y(N + 1);\n    for (int i = 1; i <= N; i++) {\n        cin >> x[i] >> y[i];\n    }\n    \n    init_rng();\n    calc_original_distances();\n    init_solution();\n    local_search();\n    \n    for (int i = 0; i < M; i++) {\n        cout << edge_day[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int MAXD = 15;\n\nint D;\nvector<string> f[2], r[2];\nint b[2][MAXD][MAXD][MAXD];\n\n// Block structure\nstruct Block {\n    int id;\n    vector<tuple<int,int,int>> cells;\n    int volume;\n    \n    Block() : id(0), volume(0) {}\n    Block(int i, const vector<tuple<int,int,int>>& c) : id(i), cells(c), volume(c.size()) {}\n};\n\n// Get all 24 rotations of a shape\nvector<vector<tuple<int,int,int>>> get_rotations(const vector<tuple<int,int,int>>& shape) {\n    vector<vector<tuple<int,int,int>>> rotations;\n    \n    auto normalize = [](vector<tuple<int,int,int>> s) {\n        int min_x = 0, min_y = 0, min_z = 0;\n        for (auto& [x, y, z] : s) {\n            min_x = min(min_x, x);\n            min_y = min(min_y, y);\n            min_z = min(min_z, z);\n        }\n        for (auto& [x, y, z] : s) {\n            x -= min_x;\n            y -= min_y;\n            z -= min_z;\n        }\n        sort(s.begin(), s.end());\n        return s;\n    };\n    \n    auto rotate_x = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(x, z, -y);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_y = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-z, y, x);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_z = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-y, x, z);\n        }\n        return normalize(s);\n    };\n    \n    vector<tuple<int,int,int>> current = shape;\n    set<vector<tuple<int,int,int>>> seen;\n    queue<vector<tuple<int,int,int>>> q;\n    \n    current = normalize(current);\n    seen.insert(current);\n    q.push(current);\n    rotations.push_back(current);\n    \n    while (!q.empty()) {\n        auto cur = q.front();\n        q.pop();\n        \n        for (auto& rot : {rotate_x, rotate_y, rotate_z}) {\n            auto next = rot(cur);\n            if (seen.find(next) == seen.end()) {\n                seen.insert(next);\n                q.push(next);\n                rotations.push_back(next);\n            }\n        }\n    }\n    \n    return rotations;\n}\n\n// Check if two shapes can match through rotation/translation\nbool can_match_shapes(const vector<tuple<int,int,int>>& shape1, const vector<tuple<int,int,int>>& shape2) {\n    if (shape1.size() != shape2.size()) return false;\n    \n    auto norm2 = normalize(shape2);\n    auto rotations = get_rotations(shape1);\n    \n    for (const auto& rot : rotations) {\n        if (rot == norm2) return true;\n    }\n    \n    return false;\n}\n\n// Normalize a shape for comparison\nvector<tuple<int,int,int>> normalize(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> s = shape;\n    if (s.empty()) return s;\n    \n    int min_x = 0, min_y = 0, min_z = 0;\n    for (auto& [x, y, z] : s) {\n        min_x = min(min_x, x);\n        min_y = min(min_y, y);\n        min_z = min(min_z, z);\n    }\n    for (auto& [x, y, z] : s) {\n        x -= min_x;\n        y -= min_y;\n        z -= min_z;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\n// Find connected components in a 3D grid\nvector<vector<tuple<int,int,int>>> find_connected_components(int id, const int (*grid)[MAXD][MAXD][MAXD]) {\n    vector<vector<tuple<int,int,int>>> components;\n    bool visited[MAXD][MAXD][MAXD] = {0};\n    \n    auto bfs = [&](int sx, int sy, int sz, int target_id) {\n        vector<tuple<int,int,int>> component;\n        queue<tuple<int,int,int>> q;\n        \n        visited[sx][sy][sz] = true;\n        q.push({sx, sy, sz});\n        component.push_back({sx, sy, sz});\n        \n        int dx[] = {1, -1, 0, 0, 0, 0};\n        int dy[] = {0, 0, 1, -1, 0, 0};\n        int dz[] = {0, 0, 0, 0, 1, -1};\n        \n        while (!q.empty()) {\n            auto [x, y, z] = q.front();\n            q.pop();\n            \n            for (int i = 0; i < 6; i++) {\n                int nx = x + dx[i];\n                int ny = y + dy[i];\n                int nz = z + dz[i];\n                \n                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                    !visited[nx][ny][nz] && (*grid)[nx][ny][nz] == target_id) {\n                    visited[nx][ny][nz] = true;\n                    q.push({nx, ny, nz});\n                    component.push_back({nx, ny, nz});\n                }\n            }\n        }\n        \n        return component;\n    };\n    \n    // Find all blocks with their IDs\n    map<int, vector<tuple<int,int,int>>> blocks;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if ((*grid)[x][y][z] > 0) {\n                    blocks[(*grid)[x][y][z]].push_back({x, y, z});\n                }\n            }\n        }\n    }\n    \n    for (auto& [id, cells] : blocks) {\n        components.push_back(cells);\n    }\n    \n    return components;\n}\n\n// Main optimization function\nvoid optimize() {\n    // Phase 1: Initial placement - place unit blocks at all valid positions\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent blocks with same ID to form larger blocks\n    // This is already done by the initial placement\n    \n    // Phase 3: Try to find common blocks between the two constructions\n    // Group blocks by their normalized shapes\n    map<vector<tuple<int,int,int>>, vector<pair<int,int>>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back({id, i});\n        }\n    }\n    \n    // Phase 4: Try to merge blocks that have matching shapes\n    // This is a heuristic - we prioritize larger blocks and shared blocks\n    \n    // For now, output the initial solution\n    // A more sophisticated solution would use simulated annealing or genetic algorithms\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        r[i].resize(D);\n        for (int z = 0; z < D; z++) {\n            cin >> f[i][z];\n        }\n        for (int z = 0; z < D; z++) {\n            cin >> r[i][z];\n        }\n    }\n    \n    // Initialize block arrays\n    memset(b, 0, sizeof(b));\n    \n    // Phase 1: Initial placement\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent cells into connected components\n    // This creates larger blocks from adjacent unit blocks\n    int new_block_counter = 0;\n    int temp_b[2][MAXD][MAXD][MAXD];\n    memset(temp_b, 0, sizeof(temp_b));\n    \n    for (int i = 0; i < 2; i++) {\n        // Find connected components\n        bool visited[MAXD][MAXD][MAXD] = {0};\n        \n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0 && !visited[x][y][z]) {\n                        // BFS to find connected component\n                        vector<tuple<int,int,int>> component;\n                        queue<tuple<int,int,int>> q;\n                        \n                        visited[x][y][z] = true;\n                        q.push({x, y, z});\n                        component.push_back({x, y, z});\n                        \n                        int dx[] = {1, -1, 0, 0, 0, 0};\n                        int dy[] = {0, 0, 1, -1, 0, 0};\n                        int dz[] = {0, 0, 0, 0, 1, -1};\n                        \n                        while (!q.empty()) {\n                            auto [cx, cy, cz] = q.front();\n                            q.pop();\n                            \n                            for (int d = 0; d < 6; d++) {\n                                int nx = cx + dx[d];\n                                int ny = cy + dy[d];\n                                int nz = cz + dz[d];\n                                \n                                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                    !visited[nx][ny][nz] && b[i][nx][ny][nz] > 0) {\n                                    visited[nx][ny][nz] = true;\n                                    q.push({nx, ny, nz});\n                                    component.push_back({nx, ny, nz});\n                                }\n                            }\n                        }\n                        \n                        // Assign new block ID to all cells in component\n                        new_block_counter++;\n                        for (auto& [cx, cy, cz] : component) {\n                            temp_b[i][cx][cy][cz] = new_block_counter;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Copy back\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    b[i][x][y][z] = temp_b[i][x][y][z];\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Try to match blocks between the two constructions\n    // Group blocks by normalized shape\n    map<vector<tuple<int,int,int>>, vector<int>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back(id);\n        }\n    }\n    \n    // Try to reuse blocks with matching shapes\n    int reused_blocks = 0;\n    for (auto& [norm, ids1] : shape_to_blocks[0]) {\n        if (shape_to_blocks[1].find(norm) != shape_to_blocks[1].end()) {\n            auto& ids2 = shape_to_blocks[1][norm];\n            // Reuse the first matching block\n            if (!ids1.empty() && !ids2.empty()) {\n                int reuse_id = ids1[0];\n                for (int x = 0; x < D; x++) {\n                    for (int y = 0; y < D; y++) {\n                        for (int z = 0; z < D; z++) {\n                            if (b[1][x][y][z] == ids2[0]) {\n                                b[1][x][y][z] = reuse_id;\n                            }\n                        }\n                    }\n                }\n                reused_blocks++;\n            }\n        }\n    }\n    \n    // Output\n    cout << new_block_counter << \"\\n\";\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    cout << b[i][x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \");\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst long long INF_COST = 1e18;\nconst int MAX_P = 5000;\n\n// Data structures\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int _x, int _y) : x(_x), y(_y) {}\n    \n    long long distSq(const Point& other) const {\n        return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y);\n    }\n    \n    double dist(const Point& other) const {\n        return sqrt(distSq(other));\n    }\n};\n\nstruct Edge {\n    int u, v, w;\n    int id;\n};\n\nstruct Resident {\n    int x, y, id;\n};\n\n// Global data\nint N, M, K;\nvector<Point> stations;\nvector<Edge> edges;\nvector<Resident> residents;\nvector<int> P;\nvector<int> B;\nvector<int> activeStations;\nvector<vector<int>> stationResidents;\nvector<vector<int>> adj;\nvector<long long> edgeCost;\n\n// Calculate total cost\nlong long calculateCost() {\n    long long cost = 0;\n    \n    // Edge costs\n    for (int j = 0; j < M; j++) {\n        if (B[j]) cost += edges[j].w;\n    }\n    \n    // Coverage costs\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    \n    return cost;\n}\n\n// Check if all residents are covered\nbool allCovered() {\n    for (int k = 0; k < K; k++) {\n        bool covered = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && stations[i].distSq(residents[k]) <= 1LL * P[i] * P[i]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\n// Check connectivity from vertex 1\nbool isConnected() {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    \n    q.push(0);\n    visited[0] = true;\n    \n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        \n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int edgeIdx = edge.second;\n            \n            if (B[edgeIdx] && !visited[v]) {\n                visited[v] = true;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Check if all stations with P > 0 are reachable\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && !visited[i]) {\n            return false;\n        }\n    }\n    \n    return true;\n}\n\n// Get minimum P needed to cover a resident\nint getPForResident(int stationIdx, int residentIdx) {\n    long long d2 = stations[stationIdx].distSq(residents[residentIdx]);\n    if (d2 > 1LL * MAX_P * MAX_P) return -1;\n    return (int)ceil(sqrt(d2));\n}\n\n// Assign residents to nearest active station\nvoid assignResidentsToStations() {\n    stationResidents.assign(N, vector<int>());\n    \n    for (int k = 0; k < K; k++) {\n        int bestStation = -1;\n        long long minDist = INF_COST;\n        \n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0) {\n                long long d = stations[i].distSq(residents[k]);\n                if (d < minDist) {\n                    minDist = d;\n                    bestStation = i;\n                }\n            }\n        }\n        \n        if (bestStation >= 0) {\n            stationResidents[bestStation].push_back(k);\n        }\n    }\n}\n\n// Calculate optimal P for each station based on assigned residents\nvoid optimizeP() {\n    for (int i = 0; i < N; i++) {\n        if (stationResidents[i].empty()) {\n            P[i] = 0;\n            continue;\n        }\n        \n        // Find maximum distance to any assigned resident\n        long long maxDist = 0;\n        for (int k : stationResidents[i]) {\n            maxDist = max(maxDist, stations[i].distSq(residents[k]));\n        }\n        \n        if (maxDist > 1LL * MAX_P * MAX_P) {\n            P[i] = MAX_P;\n        } else {\n            P[i] = (int)ceil(sqrt(maxDist));\n        }\n    }\n}\n\n// Build MST to connect active stations to vertex 1\nvoid buildNetwork() {\n    // Reset all edges\n    fill(B.begin(), B.end(), 0);\n    \n    // Collect active stations\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0) active.push_back(i);\n    }\n    \n    // If vertex 1 is not active, make it active\n    if (P[0] == 0 && !active.empty()) {\n        P[0] = 1;\n        active.push_back(0);\n    }\n    \n    // Use Kruskal's algorithm to connect all active stations\n    struct EdgeWithCost {\n        int u, v, w, id;\n    };\n    \n    vector<EdgeWithCost> edgeList;\n    for (int j = 0; j < M; j++) {\n        edgeList.push_back({edges[j].u - 1, edges[j].v - 1, edges[j].w, j});\n    }\n    \n    sort(edgeList.begin(), edgeList.end(), [](const EdgeWithCost& a, const EdgeWithCost& b) {\n        return a.w < b.w;\n    });\n    \n    // Union-Find\n    vector<int> parent(N);\n    iota(parent.begin(), parent.end(), 0);\n    \n    function<int(int)> find = [&](int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    };\n    \n    auto unite = [&](int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x != y) {\n            parent[x] = y;\n            return true;\n        }\n        return false;\n    };\n    \n    // Connect all active stations to vertex 1\n    for (auto& e : edgeList) {\n        if (find(e.u) != find(e.v)) {\n            unite(e.u, e.v);\n            B[e.id] = 1;\n        }\n    }\n}\n\n// Local search: try adding/removing stations\nvoid localSearch() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int iterations = 10000;\n    double temperature = 1000000.0;\n    double coolingRate = 0.9995;\n    \n    long long bestCost = calculateCost();\n    vector<int> bestP = P;\n    vector<int> bestB = B;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        // Try random modification\n        int action = rng() % 5;\n        \n        if (action == 0) {\n            // Try activating a new station\n            int station = rng() % N;\n            if (P[station] == 0) {\n                int oldP = P[station];\n                P[station] = 1;\n                \n                // Assign nearby residents\n                for (int k = 0; k < K; k++) {\n                    long long d = stations[station].distSq(residents[k]);\n                    if (d <= 1LL * MAX_P * MAX_P) {\n                        // Check if this is better than current assignment\n                        int currentBest = -1;\n                        long long currentDist = INF_COST;\n                        for (int i = 0; i < N; i++) {\n                            if (P[i] > 0) {\n                                long long d2 = stations[i].distSq(residents[k]);\n                                if (d2 < currentDist) {\n                                    currentDist = d2;\n                                    currentBest = i;\n                                }\n                            }\n                        }\n                        \n                        if (currentBest < 0 || d < currentDist) {\n                            // Reassign to this station\n                            optimizeP();\n                        }\n                    }\n                }\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 1) {\n            // Try deactivating a station\n            vector<int> activeStations;\n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) activeStations.push_back(i);\n            }\n            \n            if (activeStations.size() > 1) {\n                int idx = rng() % activeStations.size();\n                int station = activeStations[idx];\n                \n                // Skip vertex 1\n                if (station == 0) continue;\n                \n                int oldP = P[station];\n                P[station] = 0;\n                \n                // Reassign residents\n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 2) {\n            // Try increasing P\n            int station = rng() % N;\n            if (P[station] < MAX_P) {\n                int oldP = P[station];\n                P[station] = min(MAX_P, P[station] + rng() % 500 + 1);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 3) {\n            // Try decreasing P\n            int station = rng() % N;\n            if (P[station] > 0) {\n                int oldP = P[station];\n                P[station] = max(0, P[station] - rng() % 500);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else {\n            // Try reassigning a random resident\n            int resident = rng() % K;\n            int bestStation = -1;\n            long long minDist = INF_COST;\n            \n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) {\n                    long long d = stations[i].distSq(residents[resident]);\n                    if (d < minDist) {\n                        minDist = d;\n                        bestStation = i;\n                    }\n                }\n            }\n            \n            if (bestStation >= 0) {\n                int oldP = P[bestStation];\n                int newP = (int)ceil(sqrt(minDist));\n                P[bestStation] = newP;\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[bestStation] = oldP;\n                    buildNetwork();\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    P = bestP;\n    B = bestB;\n}\n\n// Initial solution\nvoid initSolution() {\n    P.assign(N, 0);\n    B.assign(M, 0);\n    \n    // Find nearest station for each resident\n    vector<int> residentStation(K, -1);\n    vector<long long> residentDist(K, INF_COST);\n    \n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d = stations[i].distSq(residents[k]);\n            if (d < residentDist[k]) {\n                residentDist[k] = d;\n                residentStation[k] = i;\n            }\n        }\n    }\n    \n    // Set P for each station based on assigned residents\n    for (int i = 0; i < N; i++) {\n        long long maxDist = 0;\n        for (int k = 0; k < K; k++) {\n            if (residentStation[k] == i) {\n                maxDist = max(maxDist, residentDist[k]);\n            }\n        }\n        \n        if (maxDist > 0) {\n            P[i] = (int)ceil(sqrt(maxDist));\n            if (P[i] > MAX_P) P[i] = MAX_P;\n        }\n    }\n    \n    // Ensure vertex 1 is active if needed\n    if (P[0] == 0) {\n        P[0] = 1;\n    }\n    \n    // Build network\n    buildNetwork();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N >> M >> K;\n    \n    stations.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    edgeCost.resize(M);\n    \n    for (int j = 0; j < M; j++) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n        edges[j].u--;\n        edges[j].v--;\n        edges[j].id = j;\n        adj[edges[j].u].push_back({edges[j].v, j});\n        adj[edges[j].v].push_back({edges[j].u, j});\n        edgeCost[j] = edges[j].w;\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n    \n    // Initial solution\n    initSolution();\n    \n    // Local search with simulated annealing\n    localSearch();\n    \n    // Final optimization\n    optimizeP();\n    buildNetwork();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\n\nint N = 30;\nvector<vector<int>> grid;\nvector<tuple<int, int, int, int>> operations;\n\n// Get all 6 adjacent positions\nvector<pair<int, int>> get_adj(int x, int y) {\n    vector<pair<int, int>> adj;\n    int dx[] = {-1, -1, 0, 0, 1, 1};\n    int dy[] = {-1, 0, -1, 1, 0, 1};\n    \n    for (int i = 0; i < 6; i++) {\n        int nx = x + dx[i];\n        int ny = y + dy[i];\n        if (nx >= 0 && nx < N && ny >= 0 && ny <= nx) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\n// BFS to find shortest path from (sx, sy) to (tx, ty)\nvector<pair<int, int>> bfs_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {};\n    \n    queue<pair<int, int>> q;\n    map<pair<int, int>, pair<int, int>> parent;\n    \n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == tx && y == ty) {\n            vector<pair<int, int>> path;\n            auto curr = make_pair(tx, ty);\n            while (curr.first != -1 && curr.second != -1) {\n                path.push_back(curr);\n                curr = parent[curr];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto [nx, ny] : get_adj(x, y)) {\n            if (parent.find({nx, ny}) == parent.end()) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    return {};\n}\n\n// Swap balls at two positions and record operation\nvoid swap_positions(int x1, int y1, int x2, int y2) {\n    int temp = grid[x1][y1];\n    grid[x1][y1] = grid[x2][y2];\n    grid[x2][y2] = temp;\n    operations.emplace_back(x1, y1, x2, y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    grid.resize(N);\n    for (int x = 0; x < N; x++) {\n        grid[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n        }\n    }\n    \n    // Track which positions are already filled\n    vector<vector<bool>> filled(N);\n    for (int x = 0; x < N; x++) {\n        filled[x].assign(x + 1, false);\n    }\n    \n    // Process positions from top to bottom\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (filled[x][y]) continue;\n            \n            // Find smallest ball among all unfilled positions\n            int best_val = 1e9;\n            int best_x = -1, best_y = -1;\n            \n            for (int px = x; px < N; px++) {\n                for (int py = 0; py <= px; py++) {\n                    if (!filled[px][py] && grid[px][py] < best_val) {\n                        best_val = grid[px][py];\n                        best_x = px;\n                        best_y = py;\n                    }\n                }\n            }\n            \n            // Move the best ball to current position\n            if (best_x != -1 && (best_x != x || best_y != y)) {\n                vector<pair<int, int>> path = bfs_path(best_x, best_y, x, y);\n                \n                // Perform swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); i++) {\n                    auto [x1, y1] = path[i];\n                    auto [x2, y2] = path[i + 1];\n                    swap_positions(x1, y1, x2, y2);\n                }\n            }\n            \n            filled[x][y] = true;\n        }\n    }\n    \n    // Output results\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <tuple>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\n// Grid dimensions\nconst int D = 9;\nint N;\nvector<pair<int, int>> obstacles;\nvector<vector<int>> grid; // 0: empty, 1: obstacle, 2: container\nvector<vector<int>> container_id; // ID of container at (i, j), -1 if empty\nvector<pair<int, int>> used_coords; // To track placed containers\n\n// Directions\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\n// BFS to find reachable empty squares and distances\n// Returns a map of (i, j) -> distance\nmap<pair<int, int>, int> get_distances(int start_i, int start_j) {\n    map<pair<int, int>, int> dist;\n    queue<pair<int, int>> q;\n    q.push({start_i, start_j});\n    dist[{start_i, start_j}] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n            if (nr >= 0 && nr < D && nc >= 0 && nc < D) {\n                if (grid[nr][nc] == 0 && dist.find({nr, nc}) == dist.end()) {\n                    dist[{nr, nc}] = dist[{r, c}] + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return dist;\n}\n\n// Check if a square is \"Safe\" to place a container\n// Safe means removing it (making it occupied) does not disconnect any other empty squares from entrance\nbool is_safe(int r, int c, int entrance_r, int entrance_c) {\n    // Temporarily mark as occupied\n    int original = grid[r][c];\n    grid[r][c] = 2; // Mark as occupied\n    \n    // Count reachable empty squares\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    int reachable_count = 0;\n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            reachable_count++;\n        }\n    }\n    \n    // Restore\n    grid[r][c] = original;\n    \n    // Calculate total empty squares\n    int total_empty = 0;\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (grid[i][j] == 0) total_empty++;\n        }\n    }\n    \n    // If we placed at (r, c), one less empty square.\n    // So we expect reachable_count == total_empty - 1\n    // Note: (r, c) is now occupied, so it's not counted in total_empty in the check above?\n    // Wait, total_empty is calculated with (r, c) as empty (restored).\n    // So if (r, c) is occupied, total empty is total_empty - 1.\n    // We need all other empty squares to be reachable.\n    // So reachable_count should be total_empty - 1.\n    \n    return reachable_count == total_empty - 1;\n}\n\n// Sort empty squares by accessibility for placement\n// We want to fill Leaves (Far) first, then Closer.\n// So sort by Distance Descending.\n// Safe squares are prioritized.\nvector<pair<int, int>> get_sorted_candidates(int entrance_r, int entrance_c) {\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    vector<pair<int, int>> candidates;\n    \n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            candidates.push_back(pos);\n        }\n    }\n    \n    // Sort by Distance Descending (Far first)\n    // Tie-breaker: Coordinate order for stability\n    sort(candidates.begin(), candidates.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {\n        if (dist[a] != dist[b]) return dist[a] > dist[b];\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    \n    // Filter Safe squares\n    vector<pair<int, int>> safe_candidates;\n    for (auto p : candidates) {\n        if (is_safe(p.first, p.second, entrance_r, entrance_c)) {\n            safe_candidates.push_back(p);\n        }\n    }\n    \n    // If no safe candidates (should not happen unless 1 square left), return all reachable\n    if (safe_candidates.empty() && !candidates.empty()) {\n        return candidates;\n    }\n    \n    return safe_candidates;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int entrance_r = 0;\n    int entrance_c = (D - 1) / 2;\n    \n    if (!(cin >> D >> N)) return 0;\n    \n    obstacles.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    // Initialize grid\n    grid.assign(D, vector<int>(D, 0));\n    container_id.assign(D, vector<int>(D, -1));\n    \n    for (auto obs : obstacles) {\n        grid[obs.first][obs.second] = 1;\n    }\n    // Entrance is (0, (D-1)/2)\n    // It is not an obstacle.\n    // We treat entrance as empty for placement logic, but we cannot place container there.\n    // Actually problem says \"It is neither the entrance nor an obstacle square\".\n    // So entrance is effectively blocked for placement.\n    grid[entrance_r][entrance_c] = 1; // Mark as obstacle for placement logic\n    \n    set<int> used_ids;\n    int total_containers = D * D - 1 - N;\n    \n    // Placement Phase\n    for (int d = 0; d < total_containers; ++d) {\n        int t;\n        cin >> t;\n        used_ids.insert(t);\n        \n        // Calculate rank r among remaining IDs\n        // r = number of unused IDs smaller than t\n        // Since used_ids contains all IDs placed so far,\n        // unused IDs are those not in used_ids.\n        // But we know t is the current ID.\n        // We can count how many IDs < t are already used.\n        int smaller_used = 0;\n        for (int u : used_ids) {\n            if (u < t) smaller_used++;\n        }\n        // Total IDs < t is t.\n        // So unused IDs < t is t - smaller_used.\n        int r = t - smaller_used;\n        \n        // Get sorted candidates\n        vector<pair<int, int>> candidates = get_sorted_candidates(entrance_r, entrance_c);\n        \n        int U = candidates.size();\n        // We want to place Large IDs at Far (Index 0), Small IDs at Close (Index U-1).\n        // Index k = U - 1 - r.\n        // Clamp k to [0, U-1]\n        int k = U - 1 - r;\n        if (k < 0) k = 0;\n        if (k >= U) k = U - 1;\n        \n        pair<int, int> chosen = candidates[k];\n        grid[chosen.first][chosen.second] = 2;\n        container_id[chosen.first][chosen.second] = t;\n        used_coords.push_back(chosen);\n        \n        cout << chosen.first << \" \" << chosen.second << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval Phase\n    // Greedy: Pick reachable container with min ID\n    vector<pair<int, int>> retrieval_order;\n    // Reset entrance to empty for retrieval logic?\n    // Entrance is (0, 4). It is marked as obstacle (1).\n    // For retrieval, we need to find reachable containers.\n    // Path must be through empty squares.\n    // Entrance is empty (conceptually).\n    // Let's mark entrance as 0 for BFS.\n    grid[entrance_r][entrance_c] = 0;\n    \n    int remaining = total_containers;\n    while (remaining > 0) {\n        // Find all reachable containers\n        // BFS from entrance\n        map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n        \n        int min_id = 1e9;\n        pair<int, int> best_pos = {-1, -1};\n        \n        for (auto const& [pos, d] : dist) {\n            if (grid[pos.first][pos.second] == 2) {\n                int id = container_id[pos.first][pos.second];\n                if (id < min_id) {\n                    min_id = id;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if (best_pos.first != -1) {\n            retrieval_order.push_back(best_pos);\n            grid[best_pos.first][best_pos.second] = 0; // Becomes empty\n            container_id[best_pos.first][best_pos.second] = -1;\n            remaining--;\n        } else {\n            // Should not happen\n            break;\n        }\n    }\n    \n    for (auto p : retrieval_order) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 101;\n\nint n, m;\nint grid[MAXN][MAXN];\nint adj_count[MAXM][MAXM];\nbool required_adj[MAXM][MAXM];\nint num_tiles[MAXM];\nvector<pair<int, int>> tiles[MAXM];\nint pos[MAXN][MAXN];\nvector<pair<int, int>> all_nonzero;\n\nint visited[MAXN][MAXN];\nint visited_cookie = 0;\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < n && c >= 0 && c < n;\n}\n\n// Check connectivity of a specific color\nbool check_connectivity(int color) {\n    if (num_tiles[color] <= 1) return true;\n    \n    visited_cookie++;\n    int start_r = tiles[color][0].first;\n    int start_c = tiles[color][0].second;\n    \n    int count = 0;\n    vector<pair<int, int>> q;\n    q.reserve(num_tiles[color]);\n    q.push_back({start_r, start_c});\n    visited[start_r][start_c] = visited_cookie;\n    count++;\n    \n    int head = 0;\n    while(head < q.size()){\n        auto [r, c] = q[head++];\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_cookie){\n                visited[nr][nc] = visited_cookie;\n                q.push_back({nr, nc});\n                count++;\n            }\n        }\n    }\n    return count == num_tiles[color];\n}\n\n// Try to remove tile at (r, c)\nbool try_remove(int r, int c) {\n    int color = grid[r][c];\n    if(color == 0) return false;\n    \n    // Check adjacency impact\n    bool adj_ok = true;\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != color){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                // If this is the last edge between c1 and c2, and they are required to be adjacent\n                if(adj_count[c1][c2] == 1 && required_adj[c1][c2]){\n                    adj_ok = false;\n                    break;\n                }\n            }\n        }\n    }\n    if(!adj_ok) return false;\n    \n    // Temporarily remove\n    int idx = pos[r][c];\n    tiles[color].erase(tiles[color].begin() + idx);\n    num_tiles[color]--;\n    grid[r][c] = 0;\n    \n    // Update adj_count\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != 0){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                adj_count[c1][c2]--;\n            }\n        }\n    }\n    \n    bool conn_ok = check_connectivity(color);\n    \n    if(!conn_ok){\n        // Revert\n        grid[r][c] = color;\n        num_tiles[color]++;\n        tiles[color].push_back({r, c});\n        pos[r][c] = tiles[color].size() - 1;\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc)){\n                int ncolor = grid[nr][nc];\n                if(ncolor != 0){\n                    int c1 = min(color, ncolor);\n                    int c2 = max(color, ncolor);\n                    adj_count[c1][c2]++;\n                }\n            }\n        }\n        return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> n >> m)) return 0;\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cin >> grid[i][j];\n            if(grid[i][j] != 0){\n                tiles[grid[i][j]].push_back({i, j});\n                pos[i][j] = tiles[grid[i][j]].size() - 1;\n                num_tiles[grid[i][j]]++;\n                all_nonzero.push_back({i, j});\n            }\n        }\n    }\n    \n    memset(required_adj, 0, sizeof(required_adj));\n    memset(adj_count, 0, sizeof(adj_count));\n    \n    // Compute required adjacencies and counts\n    // Count each edge once\n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            int c = grid[i][j];\n            for(int k=0; k<4; k++){\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if(is_valid(ni, nj)){\n                    int nc = grid[ni][nj];\n                    if(c != nc){\n                        int c1 = min(c, nc);\n                        int c2 = max(c, nc);\n                        // Count only once by checking coordinate order\n                        if((i < ni) || (i == ni && j < nj)){\n                             required_adj[c1][c2] = true;\n                             adj_count[c1][c2]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    mt19937 rng(1337);\n    uniform_int_distribution<int> dist_idx(0, (int)all_nonzero.size() - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int no_change = 0;\n    // Run greedy removal\n    while(true){\n        auto now = chrono::steady_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.9) break;\n        \n        if(all_nonzero.empty()) break;\n        \n        int idx = dist_idx((int)all_nonzero.size());\n        auto [r, c] = all_nonzero[idx];\n        \n        if(try_remove(r, c)){\n            // Remove from all_nonzero\n            int last_idx = all_nonzero.size() - 1;\n            all_nonzero[idx] = all_nonzero[last_idx];\n            all_nonzero.pop_back();\n            no_change = 0;\n        } else {\n            no_change++;\n            if(no_change > 5000) break;\n        }\n    }\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cout << grid[i][j] << (j == n-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for problem constraints\nint N, D, Q;\nvector<double> estimated_weights;\nvector<int> assignment;\nvector<vector<int>> sets;\nvector<double> set_sums;\n\n// Random number generator\nmt19937 rng(123456);\n\n// Function to output a query\nvoid output_query(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n}\n\n// Function to read query response\nstring read_response() {\n    string res;\n    cin >> res;\n    return res;\n}\n\n// Simulated Annealing for partitioning\nvoid simulate_annealing() {\n    // Initialize assignment using LPT (Largest Processing Time) heuristic\n    // Sort items by estimated weight descending\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({estimated_weights[i], i});\n    }\n    sort(items.begin(), items.end(), [](const pair<double, int>& a, const pair<double, int>& b) {\n        return a.first > b.first;\n    });\n\n    // Initialize sets and sums\n    sets.assign(D, vector<int>());\n    set_sums.assign(D, 0.0);\n    assignment.assign(N, 0);\n\n    for (int i = 0; i < N; ++i) {\n        int item_idx = items[i].second;\n        double weight = items[i].first;\n        \n        // Find set with minimum current sum\n        int min_set = 0;\n        for (int j = 1; j < D; ++j) {\n            if (set_sums[j] < set_sums[min_set]) {\n                min_set = j;\n            }\n        }\n        \n        sets[min_set].push_back(item_idx);\n        set_sums[min_set] += weight;\n        assignment[item_idx] = min_set;\n    }\n\n    // Calculate initial variance\n    double total_sum = 0.0;\n    for (double s : set_sums) total_sum += s;\n    double mean = total_sum / D;\n    double current_variance = 0.0;\n    for (double s : set_sums) {\n        current_variance += (s - mean) * (s - mean);\n    }\n    current_variance /= D;\n\n    double best_variance = current_variance;\n    vector<int> best_assignment = assignment;\n\n    // SA parameters\n    double temperature = 1.0;\n    double cooling_rate = 0.995;\n    int max_iterations = 20000;\n    int iterations = 0;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    auto end_time = chrono::high_resolution_clock::now() + chrono::seconds(1.5); // Leave margin for output\n\n    while (iterations < max_iterations && chrono::high_resolution_clock::now() < end_time) {\n        iterations++;\n        \n        // Select random move: swap or move\n        int move_type = uniform_int_distribution<int>(0, 1)(rng);\n        \n        if (move_type == 0) {\n            // Swap items between two different sets\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2 || sets[s1].empty() || sets[s2].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, sets[s1].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, sets[s2].size() - 1)(rng);\n            \n            int u = sets[s1][idx1];\n            int v = sets[s2][idx2];\n            \n            double w_u = estimated_weights[u];\n            double w_v = estimated_weights[v];\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u + w_v;\n            double new_sum_s2 = set_sums[s2] - w_v + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                assignment[v] = s1;\n                current_variance = new_variance;\n                \n                if (current_variance < best_variance) {\n                    best_variance = current_variance;\n                    best_assignment = assignment;\n                }\n            }\n        } else {\n            // Move item from one set to another\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (sets[s1].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, sets[s1].size() - 1)(rng);\n            int u = sets[s1][idx1];\n            double w_u = estimated_weights[u];\n            \n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u;\n            double new_sum_s2 = set_sums[s2] + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                current_variance = new_variance;\n                \n                if (current_variance < best_variance) {\n                    best_variance = current_variance;\n                    best_assignment = assignment;\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < 1e-9) break;\n    }\n\n    assignment = best_assignment;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    estimated_weights.assign(N, 1.0);\n\n    // Weight Estimation Phase\n    // We use Q queries to estimate weights\n    // We construct L and R such that sum(L) approx sum(R)\n    // This maximizes information gain\n    \n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    for (int q = 0; q < Q; ++q) {\n        // Shuffle items to ensure randomness in selection\n        shuffle(p.begin(), p.end(), rng);\n        \n        vector<int> L, R;\n        double sum_L = 0.0;\n        double sum_R = 0.0;\n        \n        // Greedy assignment to balance sums\n        // Ensure L and R are not empty\n        if (N >= 2) {\n            L.push_back(p[0]);\n            sum_L += estimated_weights[p[0]];\n            R.push_back(p[1]);\n            sum_R += estimated_weights[p[1]];\n        }\n        \n        for (int i = (N >= 2 ? 2 : 0); i < N; ++i) {\n            int item = p[i];\n            if (sum_L <= sum_R) {\n                L.push_back(item);\n                sum_L += estimated_weights[item];\n            } else {\n                R.push_back(item);\n                sum_R += estimated_weights[item];\n            }\n        }\n        \n        // Output query\n        output_query(L, R);\n        \n        // Read response\n        string res = read_response();\n        \n        // Update weights\n        double diff = sum_L - sum_R;\n        double eta = 0.5 * (1.0 - (double)q / Q); // Decaying learning rate\n        \n        if (res == \"<\") {\n            // L < R, but we estimated sum_L vs sum_R\n            // If sum_L >= sum_R, we are wrong\n            if (diff >= -1e-9) { // Allow small tolerance\n                // Decrease L weights, increase R weights\n                double adjustment = eta * max(0.0, diff + 1e-9);\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        } else if (res == \">\") {\n            // L > R\n            if (diff <= 1e-9) {\n                // Increase L weights, decrease R weights\n                double adjustment = eta * max(0.0, -diff + 1e-9);\n                for (int item : L) estimated_weights[item] += adjustment / L.size();\n                for (int item : R) estimated_weights[item] -= adjustment / R.size();\n            }\n        } else if (res == \"=\") {\n            // L = R\n            if (abs(diff) > 1e-9) {\n                // Adjust to reduce difference\n                double adjustment = eta * diff;\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        }\n        \n        // Ensure weights stay positive\n        for (double &w : estimated_weights) {\n            if (w < 0.1) w = 0.1;\n        }\n    }\n\n    // Partitioning Phase\n    simulate_annealing();\n\n    // Output final assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n\nusing namespace std;\n\n// Global variables to store state\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // pos[v] = {stack_idx, height} (0-indexed stack, 0-indexed height)\nvector<pair<int, int>> operations;\n\n// Function to calculate inversions between a block S and a stack Dest\n// S is a vector of box values in the block (from bottom to top)\n// Dest is the index of the destination stack\n// Returns the number of pairs (u, d) such that u in S, d in stacks[Dest], u > d\nint count_inversions(const vector<int>& S, int dest_idx) {\n    int count = 0;\n    const auto& dest_stack = stacks[dest_idx];\n    for (int u : S) {\n        for (int d : dest_stack) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to calculate inversions between a block S and boxes below v in Source stack\n// v is the box we want to expose (it is below S in the source stack)\n// S is the block above v\nint count_inversions_below(const vector<int>& S, int source_idx, int v) {\n    int count = 0;\n    const auto& source_stack = stacks[source_idx];\n    // Find position of v\n    int v_pos = -1;\n    for (int i = 0; i < source_stack.size(); ++i) {\n        if (source_stack[i] == v) {\n            v_pos = i;\n            break;\n        }\n    }\n    // Iterate boxes below v\n    for (int i = 0; i < v_pos; ++i) {\n        int d = source_stack[i];\n        for (int u : S) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to execute a move\n// Move block starting at box v (and all above it) to dest_stack_idx\n// Returns the number of boxes moved\nint move_block(int v, int dest_stack_idx) {\n    auto [src_idx, h] = pos[v];\n    if (src_idx == dest_stack_idx) return 0;\n    \n    const auto& src_stack = stacks[src_idx];\n    // Identify the block\n    // The block starts at h and goes to top\n    vector<int> block;\n    for (int i = h; i < src_stack.size(); ++i) {\n        block.push_back(src_stack[i]);\n    }\n    \n    // Move to dest\n    for (int u : block) {\n        stacks[dest_stack_idx].push_back(u);\n        pos[u] = {dest_stack_idx, (int)stacks[dest_stack_idx].size() - 1};\n    }\n    \n    // Remove from src\n    for (int i = 0; i < block.size(); ++i) {\n        stacks[src_idx].pop_back();\n    }\n    \n    operations.push_back({v, dest_stack_idx + 1}); // 1-indexed output\n    return block.size();\n}\n\n// Function to remove box v (Op 2)\nvoid remove_box(int v) {\n    auto [src_idx, h] = pos[v];\n    // It must be at the top\n    if (h != (int)stacks[src_idx].size() - 1) {\n        // Should not happen if logic is correct\n        return;\n    }\n    stacks[src_idx].pop_back();\n    operations.push_back({v, 0});\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    pos.resize(N + 1);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Main loop\n    for (int v = 1; v <= N; ++v) {\n        // Check if v is at the top\n        auto [src_idx, h] = pos[v];\n        while (h != (int)stacks[src_idx].size() - 1) {\n            // v is covered. Identify boxes above v.\n            const auto& src_stack = stacks[src_idx];\n            vector<int> boxes_above;\n            for (int i = h + 1; i < src_stack.size(); ++i) {\n                boxes_above.push_back(src_stack[i]);\n            }\n            \n            int k = boxes_above.size();\n            if (k == 0) break; // Should not happen\n\n            // Generate candidates\n            // We try moving suffixes of boxes_above\n            // Suffixes: top 1, top 2, ..., top k (whole block)\n            // To save time, if k is large, we limit suffixes.\n            \n            vector<int> suffix_lengths;\n            if (k <= 5) {\n                for (int len = 1; len <= k; ++len) suffix_lengths.push_back(len);\n            } else {\n                suffix_lengths.push_back(1);\n                suffix_lengths.push_back(2);\n                suffix_lengths.push_back(k);\n            }\n\n            int best_score = 1e9;\n            int best_move_v = -1;\n            int best_dest = -1;\n\n            // Random seed for tie-breaking\n            static mt19937 rng(1337);\n            vector<pair<int, int>> candidates;\n\n            for (int len : suffix_lengths) {\n                // The block to move is the top 'len' boxes of boxes_above\n                // boxes_above is from bottom to top.\n                // So top 'len' boxes are boxes_above[k-len ... k-1]\n                vector<int> S;\n                for (int i = k - len; i < k; ++i) {\n                    S.push_back(boxes_above[i]);\n                }\n                int v_to_move = S.back(); // The bottom-most box of the block being moved\n\n                for (int dest = 0; dest < M; ++dest) {\n                    if (dest == src_idx) continue;\n\n                    // Cost = len + 1\n                    int cost = len + 1;\n\n                    // Delta Potential = New Inversions - Removed Inversions\n                    // New Inversions: pairs (u, d) with u in S, d in stacks[dest], u > d\n                    int new_inv = count_inversions(S, dest);\n                    \n                    // Removed Inversions: pairs (u, d) with u in S, d in stacks[src_idx] below v, u > d\n                    int removed_inv = count_inversions_below(S, src_idx, v);\n\n                    int score = cost + (new_inv - removed_inv);\n\n                    if (score < best_score) {\n                        best_score = score;\n                        candidates.clear();\n                        candidates.push_back({v_to_move, dest});\n                    } else if (score == best_score) {\n                        candidates.push_back({v_to_move, dest});\n                    }\n                }\n            }\n\n            if (candidates.empty()) {\n                // Fallback: move top 1 box to random stack\n                int top_box = boxes_above.back();\n                int dest = src_idx;\n                while (dest == src_idx) dest = rng() % M;\n                move_block(top_box, dest);\n            } else {\n                int idx = rng() % candidates.size();\n                move_block(candidates[idx].first, candidates[idx].second);\n            }\n            \n            // Update pos[v] and h after move\n            // pos[v] is updated inside move_block\n            // But we need to re-check if v is at top\n            auto [new_src, new_h] = pos[v];\n            src_idx = new_src;\n            h = new_h;\n        }\n\n        // Now v should be at top\n        remove_box(v);\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring route;\nvector<pair<int, int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\nstring dir_chars = \"RDLU\";\n\nbool can_move(int i, int j, int di, int dj) {\n    int ni = i + di, nj = j + dj;\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    if (di == 1) return h[i][j] == '0';\n    if (di == -1) return h[ni][j] == '0';\n    if (dj == 1) return v[i][j] == '0';\n    if (dj == -1) return v[i][nj] == '0';\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N);\n    for (int i = 0; i < N; i++) cin >> h[i];\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    d.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    visited.assign(N, vector<bool>(N, false));\n    \n    // Sort neighbors by dirtiness (descending) for prioritization\n    auto get_neighbors = [&](int i, int j) {\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !visited[ni][nj]) {\n                if (can_move(i, j, di, dj)) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        return neighbors;\n    };\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        auto neighbors = get_neighbors(i, j);\n        for (auto& [dirt, dir] : neighbors) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (!visited[ni][nj] && can_move(i, j, di, dj)) {\n                route += dir_chars[dir];\n                dfs(ni, nj);\n                route += dir_chars[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Optimize: Add loops to high-dirtiness squares\n    // Find squares with high dirtiness and add revisit loops\n    vector<tuple<int, int, int>> high_dirtiness;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            high_dirtiness.push_back({d[i][j], i, j});\n        }\n    }\n    sort(high_dirtiness.rbegin(), high_dirtiness.end());\n    \n    // Try to add revisit loops to top high-dirtiness squares\n    int route_len = route.size();\n    int max_len = 100000;\n    \n    for (auto& [dirt, i, j] : high_dirtiness) {\n        if (route_len >= max_len - 20) break;\n        \n        // Try to add a small loop through this square\n        // Check if we can add a revisit from nearby visited squares\n        int best_dir = -1;\n        int best_score = 0;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                if (can_move(i, j, di, dj) && can_move(ni, nj, -di, -dj)) {\n                    best_dir = dir;\n                    best_score = dirt;\n                    break;\n                }\n            }\n        }\n        \n        if (best_dir >= 0 && route_len + 2 <= max_len) {\n            // Insert a revisit loop at a reasonable position\n            // For simplicity, we'll add it at the end before returning to (0,0)\n            route += dir_chars[best_dir];\n            route += dir_chars[(best_dir + 2) % 4];\n            route_len += 2;\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, M;\nint start_i, start_j;\nvector<string> grid(15);\nvector<string> targets;\nvector<pair<int, int>> char_pos[26];\nvector<pair<int, int>> path;\nint total_cost;\n\n// Precomputed costs\nint cost_from_start[200];  // Cost to complete each target from start position\nint cost_between[200][200]; // Cost to complete target[j] after target[i]\nint last_pos_i[200];  // Final position after completing each target\nint last_pos_j[200];\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nint move_cost(int i1, int j1, int i2, int j2) {\n    return manhattan(i1, j1, i2, j2) + 1;\n}\n\n// Find nearest position for character c from current position\npair<int, int> find_nearest(char c, int curr_i, int curr_j) {\n    int best_dist = 1e9;\n    pair<int, int> best_pos = {-1, -1};\n    for (auto& p : char_pos[c - 'A']) {\n        int d = manhattan(curr_i, curr_j, p.first, p.second);\n        if (d < best_dist) {\n            best_dist = d;\n            best_pos = p;\n        }\n    }\n    return best_pos;\n}\n\n// Precompute all costs\nvoid precompute_costs() {\n    for (int i = 0; i < M; i++) {\n        int ci = start_i, cj = start_j;\n        int cost = 0;\n        for (char c : targets[i]) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            cost += move_cost(ci, cj, pos.first, pos.second);\n            ci = pos.first;\n            cj = pos.second;\n        }\n        cost_from_start[i] = cost;\n        last_pos_i[i] = ci;\n        last_pos_j[i] = cj;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int ci = last_pos_i[i], cj = last_pos_j[i];\n            int cost = 0;\n            for (char c : targets[j]) {\n                pair<int, int> pos = find_nearest(c, ci, cj);\n                cost += move_cost(ci, cj, pos.first, pos.second);\n                ci = pos.first;\n                cj = pos.second;\n            }\n            cost_between[i][j] = cost;\n        }\n    }\n}\n\n// Calculate total cost for a given order using precomputed values\nint calculate_cost(const vector<int>& order) {\n    int cost = cost_from_start[order[0]];\n    for (int i = 1; i < M; i++) {\n        cost += cost_between[order[i-1]][order[i]];\n    }\n    return cost;\n}\n\n// Generate path for given order\nvector<pair<int, int>> generate_path(const vector<int>& order) {\n    vector<pair<int, int>> result;\n    int ci = start_i, cj = start_j;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            result.push_back(pos);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return result;\n}\n\n// 2-opt swap with incremental cost update\nint try_swap(vector<int>& order, int i, int j, int current_cost) {\n    if (i == j) return current_cost;\n    \n    // Calculate cost change from swapping positions i and j\n    int old_cost = current_cost;\n    \n    // Cost before swap: ... -> order[i-1] -> order[i] -> order[i+1] -> ... -> order[j-1] -> order[j] -> order[j+1] -> ...\n    // Cost after swap:  ... -> order[i-1] -> order[j] -> order[i+1] -> ... -> order[j-1] -> order[i] -> order[j+1] -> ...\n    \n    int cost_change = 0;\n    \n    // Handle boundary cases\n    if (i > 0) {\n        cost_change -= cost_between[order[i-1]][order[i]];\n        cost_change += cost_between[order[i-1]][order[j]];\n    }\n    if (j < M - 1) {\n        cost_change -= cost_between[order[j]][order[j+1]];\n        cost_change += cost_between[order[i]][order[j+1]];\n    }\n    if (i > 0 && j < M - 1) {\n        // Middle segment remains same\n    }\n    \n    // If i and j are adjacent, simpler calculation\n    if (j == i + 1) {\n        if (i > 0) {\n            cost_change = cost_between[order[i-1]][order[j]] + cost_between[order[j]][order[i]] \n                        - cost_between[order[i-1]][order[i]] - cost_between[order[i]][order[j]];\n        } else {\n            cost_change = cost_between[order[j]][order[i]] - cost_between[order[i]][order[j]];\n        }\n    } else {\n        // Non-adjacent swap\n        if (i > 0) cost_change -= cost_between[order[i-1]][order[i]];\n        if (j < M - 1) cost_change -= cost_between[order[j]][order[j+1]];\n        \n        if (i > 0) cost_change += cost_between[order[i-1]][order[j]];\n        if (j < M - 1) cost_change += cost_between[order[i]][order[j+1]];\n    }\n    \n    return old_cost + cost_change;\n}\n\nvoid optimize() {\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    \n    precompute_costs();\n    \n    int current_cost = calculate_cost(order);\n    \n    // Simple greedy improvement with limited iterations\n    int iterations = 5000;\n    int no_improve = 0;\n    \n    while (iterations-- > 0 && no_improve < 100) {\n        int best_i = -1, best_j = -1;\n        int best_cost = current_cost;\n        \n        // Try random swaps (faster than checking all pairs)\n        for (int iter = 0; iter < 100; iter++) {\n            int i = rand() % M;\n            int j = rand() % M;\n            if (i == j) continue;\n            \n            int new_cost = try_swap(order, i, j, current_cost);\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_i = i;\n                best_j = j;\n            }\n        }\n        \n        if (best_i != -1) {\n            swap(order[best_i], order[best_j]);\n            current_cost = best_cost;\n            no_improve = 0;\n        } else {\n            no_improve++;\n        }\n    }\n    \n    // Simulated annealing with fewer iterations\n    double temp = 100.0;\n    double decay = 0.9995;\n    int sa_iterations = 10000;\n    \n    for (int iter = 0; iter < sa_iterations; iter++) {\n        int i = rand() % M;\n        int j = rand() % M;\n        if (i == j) continue;\n        \n        int new_cost = try_swap(order, i, j, current_cost);\n        int delta = new_cost - current_cost;\n        \n        // Accept if better, or with probability if worse\n        if (delta <= 0 || (double)rand() / RAND_MAX < exp(-delta / temp)) {\n            swap(order[i], order[j]);\n            current_cost = new_cost;\n        }\n        \n        temp *= decay;\n    }\n    \n    // Generate final path\n    path = generate_path(order);\n    total_cost = calculate_cost(order);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> M >> start_i >> start_j;\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_pos[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    // Initialize cost arrays\n    memset(cost_from_start, 0, sizeof(cost_from_start));\n    memset(cost_between, 0, sizeof(cost_between));\n    memset(last_pos_i, 0, sizeof(last_pos_i));\n    memset(last_pos_j, 0, sizeof(last_pos_j));\n    \n    optimize();\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables\nint N, M;\ndouble epsilon;\nstruct Shape {\n    int id;\n    int area;\n    vector<pair<int, int>> cells;\n};\nvector<Shape> shapes;\nmap<pair<int, int>, int> drilled_values;\nbool solved = false;\n\n// Random number generator\nmt19937 rng(1337);\n\n// Function to query a single cell\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    int v;\n    cin >> v;\n    drilled_values[{r, c}] = v;\n    return v;\n}\n\n// Function to query a set of cells\nint divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Submit answer\nvoid submit(const vector<pair<int, int>>& cells) {\n    cout << \"a \" << cells.size();\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) {\n        solved = true;\n        exit(0);\n    }\n}\n\n// Check if a shape at position (r, c) covers (i, j)\nbool covers(const Shape& s, int r, int c, int i, int j) {\n    for (auto p : s.cells) {\n        if (r + p.first == i && c + p.second == j) return true;\n    }\n    return false;\n}\n\n// Calculate predicted v(i, j) for a configuration\nint predict_v(const vector<pair<int, int>>& config, int i, int j) {\n    int count = 0;\n    for (int k = 0; k < M; ++k) {\n        int r = config[k].first;\n        int c = config[k].second;\n        if (covers(shapes[k], r, c, i, j)) count++;\n    }\n    return count;\n}\n\n// Check if a configuration is consistent with drilled values\nbool is_consistent(const vector<pair<int, int>>& config) {\n    for (auto const& [pos, val] : drilled_values) {\n        int i = pos.first;\n        int j = pos.second;\n        int pred = predict_v(config, i, j);\n        if (pred != val) return false;\n    }\n    return true;\n}\n\n// Backtracking solver\n// candidates[k] is a list of possible positions for shape k\n// config[k] stores the chosen position for shape k\nbool solve(int k, vector<pair<int, int>>& config, vector<vector<pair<int, int>>>& candidates) {\n    if (k == M) {\n        return is_consistent(config);\n    }\n    \n    // Try all candidates for shape k\n    for (auto pos : candidates[k]) {\n        config[k] = pos;\n        // Pruning: Check consistency with drilled cells so far\n        bool possible = true;\n        for (auto const& [p, val] : drilled_values) {\n            int i = p.first;\n            int j = p.second;\n            // Calculate partial sum for this shape\n            int current_contribution = covers(shapes[k], pos.first, pos.second, i, j) ? 1 : 0;\n            // We need to check if it's possible to reach 'val' with remaining shapes\n            // This is a bit expensive to check fully, so let's just check exact match for drilled cells\n            // Actually, we can check if current config so far is consistent with drilled cells\n            // But we don't know other shapes yet.\n            // So we just check if the current shape doesn't violate any 0 constraints\n            if (val == 0 && current_contribution == 1) {\n                possible = false;\n                break;\n            }\n        }\n        if (!possible) continue;\n\n        if (solve(k + 1, config, candidates)) return true;\n    }\n    return false;\n}\n\n// Collect all possible positions for each shape\nvoid generate_candidates(vector<vector<pair<int, int>>>& candidates) {\n    candidates.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& s = shapes[k];\n        int max_r = N - 1;\n        int max_c = N - 1;\n        // Find bounding box of shape to determine max valid top-left\n        int s_max_r = 0, s_max_c = 0;\n        for (auto p : s.cells) {\n            s_max_r = max(s_max_r, p.first);\n            s_max_c = max(s_max_c, p.second);\n        }\n        for (int r = 0; r <= N - 1 - s_max_r; ++r) {\n            for (int c = 0; c <= N - 1 - s_max_c; ++c) {\n                // Check consistency with drilled cells\n                bool ok = true;\n                for (auto const& [pos, val] : drilled_values) {\n                    if (val == 0 && covers(s, r, c, pos.first, pos.second)) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) {\n                    candidates[k].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\n// Recursive region processing\nvoid process_region(int r1, int c1, int r2, int c2) {\n    int h = r2 - r1 + 1;\n    int w = c2 - c1 + 1;\n    int area = h * w;\n    \n    if (area <= 16) {\n        for (int r = r1; r <= r2; ++r) {\n            for (int c = c1; c <= c2; ++c) {\n                if (drilled_values.find({r, c}) == drilled_values.end()) {\n                    drill(r, c);\n                }\n            }\n        }\n        return;\n    }\n\n    // Query region\n    vector<pair<int, int>> cells;\n    for (int r = r1; r <= r2; ++r) {\n        for (int c = c1; c <= c2; ++c) {\n            cells.push_back({r, c});\n        }\n    }\n    \n    int k = cells.size();\n    int total_obs = 0;\n    int Q = 10; // Number of queries\n    for (int q = 0; q < Q; ++q) {\n        total_obs += divine(cells);\n    }\n    double avg_obs = (double)total_obs / Q;\n    \n    // Estimate true sum\n    // mu = k*eps + v*(1-2*eps)\n    // v_est = (avg_obs - k*eps) / (1-2*eps)\n    double v_est = (avg_obs - k * epsilon) / (1.0 - 2.0 * epsilon);\n    \n    // Threshold for \"empty\"\n    // If v_est is very small, assume empty.\n    // To be safe, we require v_est < 0.2 (since min non-zero is 1)\n    // But noise can make it negative.\n    // Let's say if v_est < 0.5, suspect empty.\n    if (v_est < 0.5) {\n        // Suspected empty. Verify with 1 drill.\n        int vr = r1 + (rng() % h);\n        int vc = c1 + (rng() % w);\n        int val = drill(vr, vc);\n        if (val > 0) {\n            // Not empty, recurse\n            int mr = (r1 + r2) / 2;\n            int mc = (c1 + c2) / 2;\n            process_region(r1, c1, mr, mc);\n            process_region(r1, c1, mr, c2); // Overlap? No, split properly\n            process_region(r1, c1, mr, mc); // Wait, standard quad split\n            // Correct split:\n            // Top-Left, Top-Right, Bottom-Left, Bottom-Right\n            // To avoid overlap, split at mid\n            int mid_r = (r1 + r2) / 2;\n            int mid_c = (c1 + c2) / 2;\n            process_region(r1, c1, mid_r, mid_c);\n            process_region(r1, mid_c + 1, mid_r, c2);\n            process_region(mid_r + 1, c1, r2, mid_c);\n            process_region(mid_r + 1, mid_c + 1, r2, c2);\n        } else {\n            // Assume empty, do nothing\n        }\n    } else {\n        // Definitely has oil, recurse\n        int mid_r = (r1 + r2) / 2;\n        int mid_c = (c1 + c2) / 2;\n        process_region(r1, c1, mid_r, mid_c);\n        process_region(r1, mid_c + 1, mid_r, c2);\n        process_region(mid_r + 1, c1, r2, mid_c);\n        process_region(mid_r + 1, mid_c + 1, r2, c2);\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> epsilon;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        shapes[k].id = k;\n        int d;\n        cin >> d;\n        shapes[k].area = d;\n        shapes[k].cells.resize(d);\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n        }\n    }\n\n    // Heuristic search for regions with oil\n    process_region(0, 0, N - 1, N - 1);\n\n    // Solve for configuration\n    vector<vector<pair<int, int>>> candidates;\n    generate_candidates(candidates);\n    \n    // Sort shapes by number of candidates (MRV)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return candidates[a].size() < candidates[b].size();\n    });\n\n    // We need to map back to original indices\n    // Let's just use the sorted order in recursion\n    // But the config vector needs to be indexed by original shape index\n    // Let's modify solve to take shape index from order\n    \n    vector<pair<int, int>> config(M);\n    // We need to re-implement solve to use the order\n    // Or just permute candidates\n    \n    // Let's create a permuted candidates list\n    vector<vector<pair<int, int>>> perm_candidates(M);\n    for(int i=0; i<M; ++i) perm_candidates[i] = candidates[order[i]];\n    \n    // We need a helper solve that takes the permuted candidates\n    // But predict_v uses original shape indices.\n    // So we need to keep track of which original shape we are placing.\n    \n    // Let's rewrite solve to accept a mapping\n    // Actually, simpler: just use the original candidates but pick the shape with fewest candidates first.\n    // We can do this by reordering the recursion.\n    \n    // Let's implement a custom solver\n    vector<int> shape_order = order;\n    vector<pair<int, int>> final_config(M);\n    \n    // We need to pass the current depth and the shape index we are deciding\n    // But since we reordered, we need to map back.\n    // Let's just use a lambda or a separate function with state\n    \n    // To keep it simple, let's just use the original candidates but sort them by size\n    // and pass the permutation to the solver.\n    \n    // Re-implementing solve with permutation\n    // We will fill final_config based on shape_order[k]\n    \n    auto solve_perm = [&](auto&& self, int k) -> bool {\n        if (k == M) {\n            return is_consistent(final_config);\n        }\n        int shape_idx = shape_order[k];\n        for (auto pos : candidates[shape_idx]) {\n            final_config[shape_idx] = pos;\n            // Pruning\n            bool possible = true;\n            for (auto const& [p, val] : drilled_values) {\n                if (val == 0 && covers(shapes[shape_idx], pos.first, pos.second, p.first, p.second)) {\n                    possible = false;\n                    break;\n                }\n            }\n            if (!possible) continue;\n            \n            if (self(self, k + 1)) return true;\n        }\n        return false;\n    };\n\n    if (solve_perm(solve_perm, 0)) {\n        // Found a configuration\n        // Collect all cells with v > 0\n        vector<pair<int, int>> result;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (predict_v(final_config, i, j) > 0) {\n                    result.push_back({i, j});\n                }\n            }\n        }\n        submit(result);\n    } else {\n        // Failed to find configuration.\n        // This might mean we missed some oil (false empty).\n        // We can try to drill more cells.\n        // But to keep it simple for the contest, we can just drill all remaining cells.\n        // Or submit an empty set? No, that's wrong.\n        // Let's drill all cells that are not drilled yet.\n        // This ensures we find the answer, but costs more.\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drilled_values.find({i, j}) == drilled_values.end()) {\n                    drill(i, j);\n                }\n            }\n        }\n        // Retry solving\n        generate_candidates(candidates);\n        if (solve_perm(solve_perm, 0)) {\n            vector<pair<int, int>> result;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (predict_v(final_config, i, j) > 0) {\n                        result.push_back({i, j});\n                    }\n                }\n            }\n            submit(result);\n        } else {\n            // Still failed? Fallback to all drilled cells with v>0\n            vector<pair<int, int>> result;\n            for (auto const& [pos, val] : drilled_values) {\n                if (val > 0) result.push_back(pos);\n            }\n            submit(result);\n        }\n    }\n\n    return 0;\n}","ahc031":"```cpp\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n#include <queue>\n\nusing namespace std;\n\n// Rectangle structure\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\n// Problem parameters\nint W, D, N;\nvector<vector<int>> a;  // desired areas\nvector<vector<Rect>> rects;  // assigned rectangles\n\n// Check if rectangles overlap\nbool checkOverlap(const vector<Rect>& day_rects) {\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!(day_rects[i].i1 <= day_rects[j].i0 ||\n                  day_rects[i].i0 >= day_rects[j].i1 ||\n                  day_rects[i].j1 <= day_rects[j].j0 ||\n                  day_rects[i].j0 >= day_rects[j].j1)) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\n// Calculate area cost for a day\nlong long calculateAreaCost(int d) {\n    long long cost = 0;\n    for (int k = 0; k < N; k++) {\n        int actual = rects[d][k].area();\n        if (actual < a[d][k]) {\n            cost += 100LL * (a[d][k] - actual);\n        }\n    }\n    return cost;\n}\n\n// Calculate partition segments for a day\nvector<vector<int>> getHorizontalSegments(int d) {\n    vector<vector<int>> H(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) H[i0][j] = 1;\n            if (i1 > 0 && i1 < W) H[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) H[i][j0] = 1;\n            if (j1 > 0 && j1 < W) H[i][j1] = 1;\n        }\n    }\n    return H;\n}\n\nvector<vector<int>> getVerticalSegments(int d) {\n    vector<vector<int>> V(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) V[i0][j] = 1;\n            if (i1 > 0 && i1 < W) V[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) V[i][j0] = 1;\n            if (j1 > 0 && j1 < W) V[i][j1] = 1;\n        }\n    }\n    return V;\n}\n\nlong long calculatePartitionCost(int d) {\n    if (d == 0) return 0;\n    long long cost = 0;\n    auto H_prev = getHorizontalSegments(d - 1);\n    auto H_curr = getHorizontalSegments(d);\n    auto V_prev = getVerticalSegments(d - 1);\n    auto V_curr = getVerticalSegments(d);\n    \n    for (int i = 1; i < W; i++) {\n        for (int j = 0; j < W; j++) {\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; i++) {\n        for (int j = 1; j < W; j++) {\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n        }\n    }\n    return cost;\n}\n\nlong long calculateTotalCost() {\n    long long total = 0;\n    for (int d = 0; d < D; d++) {\n        total += calculateAreaCost(d);\n        total += calculatePartitionCost(d);\n    }\n    return total;\n}\n\n// Initialize with better packing strategy\nvoid initializeSolution() {\n    rects.resize(D);\n    for (int d = 0; d < D; d++) {\n        rects[d].resize(N);\n        \n        // Sort reservations by area (descending) for better packing\n        vector<pair<int, int>> sorted_idx(N);\n        for (int k = 0; k < N; k++) sorted_idx[k] = {a[d][k], k};\n        sort(sorted_idx.rbegin(), sorted_idx.rend());\n        \n        // Use a simple row-based packing\n        int current_i = 0, current_j = 0;\n        for (int idx = 0; idx < N; idx++) {\n            int k = sorted_idx[idx].second;\n            int desired = a[d][k];\n            \n            // Calculate dimensions to minimize perimeter\n            int best_h = 1, best_w = desired;\n            int best_perimeter = 2 * (1 + desired);\n            for (int h = 1; h * h <= desired; h++) {\n                if (desired % h == 0) {\n                    int w = desired / h;\n                    int perimeter = 2 * (h + w);\n                    if (perimeter < best_perimeter) {\n                        best_perimeter = perimeter;\n                        best_h = h;\n                        best_w = w;\n                    }\n                }\n            }\n            \n            // Try to fit in current row\n            if (current_j + best_w <= W) {\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            } else {\n                // Move to next row\n                current_i += best_h;\n                current_j = 0;\n                if (current_i + best_h > W) {\n                    // Need to reorganize - use simpler approach\n                    current_i = 0;\n                    current_j = 0;\n                    for (int x = 0; x < idx; x++) {\n                        int pk = sorted_idx[x].second;\n                        int ph = rects[d][pk].i1 - rects[d][pk].i0;\n                        current_i += ph;\n                        if (current_i >= W) {\n                            current_i = 0;\n                            current_j = 0;\n                        }\n                    }\n                }\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            }\n        }\n    }\n}\n\n// Simulated Annealing optimization\nvoid optimizeSolution() {\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    uniform_int_distribution<int> int_dist(0, W - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double initial_temp = 5000.0;\n    const double cooling_rate = 0.998;\n    const double final_temp = 0.1;\n    \n    double temp = initial_temp;\n    long long current_cost = calculateTotalCost();\n    long long best_cost = current_cost;\n    \n    while (temp > final_temp) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > 2.8) break;  // Leave margin for output\n        \n        // Randomly select a day and rectangle\n        int d = dist(gen) * D;\n        int k = dist(gen) * N;\n        \n        Rect original = rects[d][k];\n        int attempts = 0;\n        bool valid = false;\n        Rect new_rect = original;\n        \n        while (attempts < 200 && !valid) {\n            int h = original.i1 - original.i0;\n            int w = original.j1 - original.j0;\n            \n            // Random perturbation with bias toward stability\n            int di = (dist(gen) * 15 - 7);\n            int dj = (dist(gen) * 15 - 7);\n            int dh = (dist(gen) * 8 - 4);\n            int dw = (dist(gen) * 8 - 4);\n            \n            int ni0 = max(0, min(W - 1, original.i0 + di));\n            int nj0 = max(0, min(W - 1, original.j0 + dj));\n            int ni1 = max(ni0 + 1, min(W, original.i1 + dh));\n            int nj1 = max(nj0 + 1, min(W, original.j1 + dw));\n            \n            new_rect = {ni0, nj0, ni1, nj1};\n            \n            if (!checkOverlap(rects[d])) {\n                valid = true;\n            } else {\n                attempts++;\n            }\n        }\n        \n        rects[d][k] = new_rect;\n        long long new_cost = calculateTotalCost();\n        double delta = new_cost - current_cost;\n        \n        if (delta < 0 || dist(gen) < exp(-delta / temp)) {\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n            }\n        } else {\n            rects[d][k] = original;\n        }\n        \n        temp *= cooling_rate;\n    }\n}\n\n// Local search for area satisfaction\nvoid improveAreaSatisfaction() {\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int current_area = rects[d][k].area();\n            if (current_area < a[d][k]) {\n                int needed = a[d][k] - current_area;\n                int h = rects[d][k].i1 - rects[d][k].i0;\n                int w = rects[d][k].j1 - rects[d][k].j0;\n                \n                // Try expanding in different directions\n                int[] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};\n                for (int dir = 0; dir < 4; dir++) {\n                    int di = dirs[dir][0];\n                    int dj = dirs[dir][1];\n                    \n                    int ni0 = rects[d][k].i0 + di * h;\n                    int nj0 = rects[d][k].j0 + dj * w;\n                    int ni1 = rects[d][k].i1 + di * h;\n                    int nj1 = rects[d][k].j1 + dj * w;\n                    \n                    if (ni0 >= 0 && ni1 <= W && nj0 >= 0 && nj1 <= W) {\n                        if (!checkOverlap(rects[d])) {\n                            rects[d][k] = {ni0, nj0, ni1, nj1};\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Try to reduce partition costs by aligning with previous day\nvoid improvePartitionStability() {\n    for (int d = 1; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            // Try to match previous day's partition pattern\n            if (d - 1 >= 0) {\n                int best_cost = 1e18;\n                Rect best_rect = rects[d][k];\n                \n                // Try small adjustments\n                for (int di = -3; di <= 3; di++) {\n                    for (int dj = -3; dj <= 3; dj++) {\n                        int ni0 = max(0, min(W - 1, rects[d][k].i0 + di));\n                        int nj0 = max(0, min(W - 1, rects[d][k].j0 + dj));\n                        int ni1 = max(ni0 + 1, min(W, rects[d][k].i1 + di));\n                        int nj1 = max(nj0 + 1, min(W, rects[d][k].j1 + dj));\n                        \n                        Rect test_rect = {ni0, nj0, ni1, nj1};\n                        if (!checkOverlap(rects[d])) {\n                            long long test_cost = calculateTotalCost();\n                            if (test_cost < best_cost) {\n                                best_cost = test_cost;\n                                best_rect = test_rect;\n                            }\n                        }\n                    }\n                }\n                rects[d][k] = best_rect;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n    \n    // Initialize solution\n    initializeSolution();\n    \n    // Optimize\n    optimizeSolution();\n    \n    // Final improvements\n    improveAreaSatisfaction();\n    improvePartitionStability();\n    \n    // Output\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[d][k].i0 << \" \" << rects[d][k].j0 << \" \"\n                 << rects[d][k].i1 << \" \" << rects[d][k].j1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst long long MOD = 998244353;\n\n// Structures\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\n// Global variables for solver state\nint board[N][N];\nint stamps[M][3][3];\nvector<Op> current_ops;\nlong long current_score;\nvector<Op> best_ops;\nlong long best_score;\n\n// Random number generator\nmt19937_64 rng;\n\n// Function to calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += (board[i][j] % MOD);\n        }\n    }\n    return score;\n}\n\n// Function to apply an operation\nvoid apply_op(const Op& op, int val) {\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            board[op.p + i][op.q + j] += val * stamps[op.m][i][j];\n        }\n    }\n}\n\n// Function to calculate delta score for an operation\nlong long get_delta_score(const Op& op, int val) {\n    long long delta = 0;\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            int r = op.p + i;\n            int c = op.q + j;\n            long long old_val = board[r][c] % MOD;\n            long long new_val = (board[r][c] + val * stamps[op.m][i][j]) % MOD;\n            delta += new_val - old_val;\n        }\n    }\n    return delta;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    // Read board\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> board[i][j];\n        }\n    }\n\n    // Read stamps\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            for (int l = 0; l < 3; ++l) {\n                cin >> stamps[i][j][l];\n            }\n        }\n    }\n\n    // Initialize current_ops with K random operations\n    // Actually, let's start with 0 and add K operations greedily or randomly.\n    // Random initialization is better for SA to avoid local optima early.\n    // But we can also do a greedy initialization.\n    // Let's try greedy initialization first to get a decent starting point.\n    \n    // Greedy initialization\n    current_ops.clear();\n    for (int i = 0; i < k; ++i) {\n        long long max_delta = -1e18;\n        Op best_op;\n        best_op.m = 0; best_op.p = 0; best_op.q = 0;\n        \n        // Find best operation to add\n        // We can iterate over all possible operations\n        // But 20 * 7 * 7 = 980 is small enough.\n        for (int sm = 0; sm < m; ++sm) {\n            for (int sp = 0; sp <= n - 3; ++sp) {\n                for (int sq = 0; sq <= n - 3; ++sq) {\n                    Op op = {sm, sp, sq};\n                    long long delta = get_delta_score(op, 1);\n                    if (delta > max_delta) {\n                        max_delta = delta;\n                        best_op = op;\n                    }\n                }\n            }\n        }\n        \n        // If max_delta is negative, we might still want to add to reach K?\n        // Or we can stop adding.\n        // Let's add if delta > 0. If all are negative, we can pick the least negative one\n        // or just stop.\n        // But we need to output at most K.\n        // If we stop early, we use fewer operations.\n        // Let's just add the best one regardless.\n        \n        current_ops.push_back(best_op);\n        apply_op(best_op, 1);\n    }\n    \n    current_score = calculate_score();\n    best_ops = current_ops;\n    best_score = current_score;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1900); // Leave 100ms for output\n    \n    double temperature = 1000000000.0; // High initial temperature\n    double cooling_rate = 0.9995;\n    double min_temp = 1e-9;\n\n    // Distributions\n    uniform_int_distribution<int> dist_m(0, m - 1);\n    uniform_int_distribution<int> dist_p(0, n - 3);\n    uniform_int_distribution<int> dist_q(0, n - 3);\n    uniform_int_distribution<int> dist_idx(0, k - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Select a random operation index to change\n        int idx = dist_idx(rng);\n        Op old_op = current_ops[idx];\n        \n        // Generate a new random operation\n        Op new_op;\n        new_op.m = dist_m(rng);\n        new_op.p = dist_p(rng);\n        new_op.q = dist_q(rng);\n        \n        // Calculate delta\n        long long delta = 0;\n        \n        // Remove old op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = old_op.p + i;\n                int c = old_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                if (new_val < 0) new_val += MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Add new op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = new_op.p + i;\n                int c = new_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Acceptance probability\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / temperature);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_ops[idx] = new_op;\n            // Apply the change to the board\n            // Remove old\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = old_op.p + i;\n                    int c = old_op.q + j;\n                    board[r][c] -= stamps[old_op.m][i][j];\n                }\n            }\n            // Add new\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = new_op.p + i;\n                    int c = new_op.q + j;\n                    board[r][c] += stamps[new_op.m][i][j];\n                }\n            }\n            current_score += delta;\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ops = current_ops;\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < min_temp) temperature = min_temp;\n    }\n\n    // Output best solution\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int INF = 1e9;\n\n// Container ID\nconst int EMPTY = -1;\n\nstruct Crane {\n    int id;\n    int x, y;\n    int holding; // Container ID or EMPTY\n    bool is_large;\n    bool active;\n};\n\nstruct State {\n    int grid[N][N]; // Container IDs\n    vector<Crane> cranes;\n    vector<vector<int>> input_queue; // input_queue[i] = list of containers for row i\n    vector<int> dispatch_expected; // dispatch_expected[i] = next expected container for row i\n    vector<vector<int>> dispatch_order; // To calculate M1 later if needed, but heuristic focuses on current state\n    int turn;\n    int dispatched_count;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = EMPTY;\n            input_queue.push_back({});\n            dispatch_expected.push_back(N * i);\n            dispatch_order.push_back({});\n        }\n        cranes.resize(N);\n        for(int i=0; i<N; ++i) {\n            cranes[i] = {i, i, 0, EMPTY, (i == 0), true};\n        }\n        turn = 0;\n        dispatched_count = 0;\n    }\n};\n\n// Check if a move is valid for a specific crane in isolation (ignoring other crane collisions)\nbool isMoveValidForCrane(const Crane& c, char action, const State& s) {\n    if (!c.active) return false;\n    int nx = c.x, ny = c.y;\n    int holding = c.holding;\n\n    if (action == 'P') {\n        if (holding != EMPTY) return false;\n        if (s.grid[c.x][c.y] == EMPTY) return false;\n        return true;\n    }\n    if (action == 'Q') {\n        if (holding == EMPTY) return false;\n        if (s.grid[c.x][c.y] != EMPTY) return false;\n        return true;\n    }\n    if (action == 'B') {\n        if (holding != EMPTY) return false;\n        return true;\n    }\n    if (action == 'U') ny--;\n    else if (action == 'D') ny++;\n    else if (action == 'L') nx--;\n    else if (action == 'R') nx++;\n    else if (action == '.') return true;\n    else return false;\n\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    \n    // Small crane carrying container cannot move to occupied square\n    if (!c.is_large && holding != EMPTY && s.grid[nx][ny] != EMPTY) return false;\n\n    return true;\n}\n\n// Check if a combination of actions is valid (collisions)\nbool isComboValid(const vector<char>& actions, const State& s, vector<Crane>& next_cranes) {\n    int N_cranes = s.cranes.size();\n    vector<pair<int, int>> start_pos(N_cranes);\n    vector<pair<int, int>> end_pos(N_cranes);\n    \n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        start_pos[i] = {s.cranes[i].x, s.cranes[i].y};\n        \n        int nx = s.cranes[i].x;\n        int ny = s.cranes[i].y;\n        char act = actions[i];\n        if (act == 'U') ny--;\n        else if (act == 'D') ny++;\n        else if (act == 'L') nx--;\n        else if (act == 'R') nx++;\n        \n        end_pos[i] = {nx, ny};\n    }\n\n    // Check overlap and swap\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        for(int j=i+1; j<N_cranes; ++j) {\n            if (!s.cranes[j].active) continue;\n            \n            // Overlap\n            if (end_pos[i] == end_pos[j]) return false;\n            \n            // Swap\n            if (start_pos[i] == end_pos[j] && start_pos[j] == end_pos[i]) return false;\n        }\n    }\n    \n    // Apply to next_cranes for simulation\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) {\n            next_cranes[i] = s.cranes[i];\n            continue;\n        }\n        next_cranes[i] = s.cranes[i];\n        char act = actions[i];\n        if (act == 'P') {\n            next_cranes[i].holding = s.grid[s.cranes[i].x][s.cranes[i].y];\n        } else if (act == 'Q') {\n            next_cranes[i].holding = EMPTY;\n        } else if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    return true;\n}\n\n// Calculate Heuristic Score\nint calculateScore(const State& s) {\n    int score = 0;\n    int undispatched = 0;\n    int wrong_gate = 0;\n    int inversions = 0;\n    int dist_sum = 0;\n    \n    // Check dispatched containers\n    // We simulate the dispatch step for the heuristic\n    // Actually, we can just check current state.\n    // If container at (i, 4) is correct, it counts as dispatched for next turn.\n    \n    vector<int> current_dispatched(N, 0); // Count of dispatched for each row\n    \n    for(int i=0; i<N; ++i) {\n        int cx = i;\n        int cy = N-1;\n        int container = s.grid[cx][cy];\n        if (container != EMPTY) {\n            int expected = N * i + s.dispatch_order[i].size(); // This is tricky, we need to know order\n            // Simplified: Check if container belongs to this row\n            if (container / N == i) {\n                // It belongs to this row.\n                // To check inversion, we need to know previous dispatched.\n                // For heuristic, we just count if it's at correct gate.\n                // We assume if it's at correct gate, it's good.\n                // Inversion penalty is small compared to M2, M3.\n                // We can estimate inversions by checking if container < last dispatched.\n                // But we don't store history in State efficiently here.\n                // Let's just count containers at wrong gates.\n            } else {\n                wrong_gate++;\n            }\n        }\n    }\n    \n    // Count undispatched\n    // Total containers = 25.\n    // Count how many are still on grid or in input queue.\n    int on_grid = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) on_grid++;\n        }\n    }\n    int in_queue = 0;\n    for(int i=0; i<N; ++i) in_queue += s.input_queue[i].size();\n    undispatched = on_grid + in_queue;\n    \n    // Distance\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) {\n                int c = s.grid[i][j];\n                int target_r = c / N;\n                int target_c = N - 1;\n                dist_sum += abs(i - target_r) + abs(j - target_c);\n            }\n        }\n    }\n    \n    // Input Blocking Penalty\n    // If a crane is at (i, 0), it blocks input.\n    // If a container is at (i, 0), it blocks input (until picked).\n    for(int i=0; i<N; ++i) {\n        bool blocked = false;\n        if (s.grid[i][0] != EMPTY) blocked = true;\n        for(const auto& c : s.cranes) {\n            if (c.active && c.x == i && c.y == 0) blocked = true;\n        }\n        if (blocked && !s.input_queue[i].empty()) {\n            // Huge penalty for blocking input\n            score += 100000; \n        }\n    }\n    \n    // Dispatch Gate Penalty\n    // If container at (i, 4) is not the expected one, it blocks dispatch.\n    // Expected for row i is N*i, N*i+1, ...\n    // We can track expected in State.\n    for(int i=0; i<N; ++i) {\n        int expected = N * i + s.dispatch_order[i].size();\n        int container = s.grid[i][4];\n        if (container != EMPTY && container != expected) {\n            // Wrong container at dispatch gate\n            score += 100000;\n        }\n    }\n    \n    score += 1000000 * undispatched;\n    score += 10000 * wrong_gate;\n    score += 100 * dist_sum;\n    score += s.turn; // Minimize turns\n    \n    return score;\n}\n\n// Simulate one turn and return new state\nState simulateTurn(const State& s, const vector<char>& actions) {\n    State next = s;\n    next.turn = s.turn + 1;\n    \n    // Step 1: Receiving Gates\n    for(int i=0; i<N; ++i) {\n        if (!next.input_queue[i].empty()) {\n            bool blocked = false;\n            if (next.grid[i][0] != EMPTY) blocked = true;\n            for(const auto& c : next.cranes) {\n                if (c.active && c.x == i && c.y == 0) blocked = true;\n            }\n            if (!blocked) {\n                next.grid[i][0] = next.input_queue[i].front();\n                next.input_queue[i].erase(next.input_queue[i].begin());\n            }\n        }\n    }\n    \n    // Step 2: Crane Actions\n    // We need to update grid and cranes based on actions\n    // Since we already validated actions in isComboValid, we can apply them.\n    // But we need to handle P/Q on grid correctly.\n    \n    vector<Crane> next_cranes = next.cranes;\n    vector<int> next_grid[N]; // Temporary to handle P/Q order? No, simultaneous.\n    // Actually, P/Q updates grid.\n    // We should apply moves first, then P/Q? No, P/Q happens at current square.\n    // Move happens to adjacent.\n    // The problem says \"Perform the actions of each crane\".\n    // It implies P/Q/Move are atomic per crane.\n    // So we update grid based on P/Q at current pos, then move cranes.\n    // Wait, if P happens, container leaves grid. If Q happens, container enters grid.\n    // If Move happens, crane changes pos.\n    // Order:\n    // 1. Check P/Q validity (already done).\n    // 2. Apply P: remove from grid, set crane holding.\n    // 3. Apply Q: set crane holding to EMPTY, put to grid.\n    // 4. Apply Move: update crane pos.\n    // Note: If a crane moves from A to B, and another Q at B?\n    // \"Cranes cannot overlap\". So if A moves to B, B must be empty of cranes.\n    // But can B have a container? Yes.\n    // If crane Q at B, it puts container at B.\n    // If crane A moves to B, it arrives at B.\n    // If A moves to B, and B was empty, now A is at B.\n    // If Q happens at B (by crane C), C must be at B.\n    // So A cannot move to B if C is at B.\n    // So Crane positions are updated simultaneously.\n    // Grid updates:\n    // - P removes from grid.\n    // - Q adds to grid.\n    // - Container at (i,0) added in Step 1.\n    // - Container at (i,4) removed in Step 3.\n    \n    // Apply P\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'P') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = EMPTY;\n            next_cranes[i].holding = s.grid[next_cranes[i].x][next_cranes[i].y];\n        }\n    }\n    // Apply Q\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'Q') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = next_cranes[i].holding;\n            next_cranes[i].holding = EMPTY;\n        }\n    }\n    // Apply Move / Bomb\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        char act = actions[i];\n        if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    next.cranes = next_cranes;\n    \n    // Step 3: Dispatch\n    for(int i=0; i<N; ++i) {\n        int container = next.grid[i][4];\n        if (container != EMPTY) {\n            // Check if correct\n            int expected = N * i + next.dispatch_order[i].size();\n            if (container == expected) {\n                next.dispatch_order[i].push_back(container);\n                next.grid[i][4] = EMPTY;\n                next.dispatched_count++;\n            }\n        }\n    }\n    \n    return next;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int N_in;\n    if (!(cin >> N_in)) return 0;\n    \n    State s;\n    // Read Input\n    // A_{i,j}\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int val;\n            cin >> val;\n            s.input_queue[i].push_back(val);\n        }\n    }\n    \n    vector<string> result(N, \"\");\n    \n    // Precompute valid actions for each crane to speed up\n    // But valid actions depend on state.\n    \n    // Loop\n    for(int t=0; t<MAX_TURNS; ++t) {\n        if (s.dispatched_count == N*N) break;\n        \n        // Generate candidate actions for each crane\n        vector<vector<pair<char, int>>> candidates(N);\n        \n        for(int i=0; i<N; ++i) {\n            if (!s.cranes[i].active) {\n                candidates[i].push_back({'.', 0});\n                continue;\n            }\n            const Crane& c = s.cranes[i];\n            vector<char> moves = {'P', 'Q', 'U', 'D', 'L', 'R', '.'};\n            for(char m : moves) {\n                if (isMoveValidForCrane(c, m, s)) {\n                    // Estimate score for this move alone (others do '.')\n                    // To save time, we can use a simpler heuristic or just add to list.\n                    // Let's just collect valid moves.\n                    candidates[i].push_back({m, 0});\n                }\n            }\n            // Sort candidates by some priority?\n            // Priority:\n            // 1. If at (i,0) and container exists: P\n            // 2. If holding: Q or Move towards target\n            // 3. If empty: Move towards (i,0) or container\n            // We can sort here to pick top K.\n            // For now, take all valid.\n            // Limit to top 5 to keep 5^5 small.\n            if (candidates[i].size() > 5) {\n                // Sort by heuristic improvement\n                // We can't compute full heuristic for each.\n                // Use simple priority.\n                // Just take first 5.\n                candidates[i].resize(5);\n            }\n        }\n        \n        // Iterate combinations\n        // We need to find the best valid combination.\n        // Since candidates are small (<=5), 5^5 = 3125.\n        // We can use a recursive search or nested loops.\n        // To find BEST, we can iterate all and track best.\n        \n        int best_score = INF;\n        vector<char> best_actions(N, '.');\n        bool found = false;\n        \n        // Use a simple iterative approach with indices\n        vector<int> idx(N, 0);\n        vector<int> sizes(N);\n        for(int i=0; i<N; ++i) sizes[i] = candidates[i].size();\n        \n        // We can use a priority queue to explore combinations in order of estimated utility?\n        // No, just iterate all valid ones and pick best.\n        // 3125 is small enough.\n        \n        // To optimize, we can prune invalid combos early.\n        // But 3125 is very small.\n        \n        // We need to generate all combinations.\n        // Recursive function\n        auto search = [&](auto&& self, int crane_idx, vector<char>& current_actions, State& temp_s, vector<Crane>& temp_cranes) -> void {\n            if (crane_idx == N) {\n                // Check validity of full combo\n                if (isComboValid(current_actions, s, temp_cranes)) {\n                    // Calculate score\n                    // We can simulate the turn to get exact score\n                    // But simulation is expensive.\n                    // Let's use calculateScore on the resulting state.\n                    // To avoid full simulation, we can approximate.\n                    // But for correctness, simulate.\n                    // Actually, we can just calculate score on 's' with modifications.\n                    // Let's just simulate.\n                    State next_s = simulateTurn(s, current_actions);\n                    int sc = calculateScore(next_s);\n                    if (sc < best_score) {\n                        best_score = sc;\n                        best_actions = current_actions;\n                        found = true;\n                    }\n                }\n                return;\n            }\n            \n            for(int i=0; i<sizes[crane_idx]; ++i) {\n                current_actions[crane_idx] = candidates[crane_idx][i].first;\n                self(self, crane_idx + 1, current_actions, temp_s, temp_cranes);\n            }\n        };\n        \n        vector<char> current_actions(N);\n        State temp_s = s;\n        vector<Crane> temp_cranes = s.cranes;\n        search(search, 0, current_actions, temp_s, temp_cranes);\n        \n        if (!found) {\n            // Fallback: all '.'\n            best_actions.assign(N, '.');\n        }\n        \n        // Apply best actions\n        for(int i=0; i<N; ++i) {\n            result[i] += best_actions[i];\n        }\n        \n        s = simulateTurn(s, best_actions);\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << result[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Point {\n    int x, y;\n    int id;\n};\n\nint dist(Point p1, Point p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<vector<int>> h(N, vector<int>(N));\n    vector<Point> sources, sinks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j, i * N + j});\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j, i * N + j});\n            }\n        }\n    }\n\n    int num_sources = sources.size();\n    int num_sinks = sinks.size();\n\n    // Build Min-Cost Flow Graph\n    // Nodes: 0..N*N-1 (Grid Cells), N*N (Source S), N*N+1 (Sink T)\n    // However, MCF works better with a bipartite structure for this problem.\n    // Let's map:\n    // S -> SourceCell (cap = h, cost = 0)\n    // SourceCell -> SinkCell (cap = inf, cost = dist)\n    // SinkCell -> T (cap = |h|, cost = 0)\n    \n    // To use AC Library MCF, we need to map grid cells to nodes.\n    // Let's use:\n    // 0..num_sources-1 : Source Cells\n    // num_sources..num_sources+num_sinks-1 : Sink Cells\n    // num_sources+num_sinks : S\n    // num_sources+num_sinks+1 : T\n    \n    int S = num_sources + num_sinks;\n    int T = num_sources + num_sinks + 1;\n    MCF mcf(T + 1);\n\n    long long total_supply = 0;\n    for (int i = 0; i < num_sources; ++i) {\n        int supply = h[sources[i].x][sources[i].y];\n        total_supply += supply;\n        mcf.add_edge(S, i, supply, 0);\n    }\n\n    for (int i = 0; i < num_sinks; ++i) {\n        int demand = abs(h[sinks[i].x][sinks[i].y]);\n        mcf.add_edge(num_sources + i, T, demand, 0);\n    }\n\n    for (int i = 0; i < num_sources; ++i) {\n        for (int j = 0; j < num_sinks; ++j) {\n            int d = dist(sources[i], sinks[j]);\n            mcf.add_edge(i, num_sources + j, 1e9, d);\n        }\n    }\n\n    auto result = mcf.min_cost_flow(S, T, total_supply);\n    // result.first is flow, result.second is cost\n\n    // Extract flow\n    // requests[u_idx] = vector of {v_idx, flow_amount}\n    vector<vector<pair<int, int>>> requests(num_sources);\n    \n    // Iterate over edges from SourceCells to SinkCells\n    // In MCF, edges are stored in a list. We need to find which ones are relevant.\n    // The edges from SourceCells (0..num_sources-1) to SinkCells (num_sources..) are the ones we care about.\n    // However, MCF adds edges in order.\n    // S->Source: 0..num_sources-1\n    // Sink->T: num_sources..num_sources+num_sinks-1\n    // Source->Sink: num_sources+num_sinks .. end\n    \n    // Let's iterate all edges and check indices\n    for (const auto &e : mcf.edges()) {\n        if (e.from >= 0 && e.from < num_sources && e.to >= num_sources && e.to < num_sources + num_sinks) {\n            if (e.flow > 0) {\n                int u_idx = e.from;\n                int v_idx = e.to - num_sources;\n                requests[u_idx].push_back({v_idx, (int)e.flow});\n            }\n        }\n    }\n\n    // Routing\n    // Current position\n    int cur_x = 0, cur_y = 0;\n    // Visited sources\n    vector<bool> source_done(num_sources, false);\n    // Remaining sources count\n    int remaining_sources = num_sources;\n    \n    // We will store operations\n    vector<string> ops;\n    \n    // Helper to move from (cx, cy) to (tx, ty)\n    auto move_to = [&](int tx, int ty) {\n        while (cur_x < tx) {\n            cur_x++;\n            ops.push_back(\"D\");\n        }\n        while (cur_x > tx) {\n            cur_x--;\n            ops.push_back(\"U\");\n        }\n        while (cur_y < ty) {\n            cur_y++;\n            ops.push_back(\"R\");\n        }\n        while (cur_y > ty) {\n            cur_y--;\n            ops.push_back(\"L\");\n        }\n    };\n\n    // Helper to load\n    auto load = [&](int amount) {\n        ops.push_back(\"+\" + to_string(amount));\n    };\n\n    // Helper to unload\n    auto unload = [&](int amount) {\n        ops.push_back(\"-\" + to_string(amount));\n    };\n\n    // Main Loop\n    while (remaining_sources > 0) {\n        // Find nearest source that is not done\n        int best_u = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < num_sources; ++i) {\n            if (!source_done[i]) {\n                int d = dist({cur_x, cur_y, -1}, sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_u = i;\n                }\n            }\n        }\n\n        if (best_u == -1) break; // Should not happen\n\n        // Move to source\n        move_to(sources[best_u].x, sources[best_u].y);\n\n        // Load soil\n        // We load all soil assigned to this source\n        // But we can load it in one go since capacity is effectively infinite\n        // However, we need to track how much we load to unload later.\n        // Actually, we can just load the total amount needed for this source's sinks.\n        int total_load = 0;\n        for (auto &p : requests[best_u]) {\n            total_load += p.second;\n        }\n        load(total_load);\n\n        // Plan Sink Tour\n        // We have a list of sinks to visit: requests[best_u]\n        // We want to visit them in an order that minimizes distance.\n        // Start at sources[best_u].\n        // End at some sink, then move to next source.\n        // Since we pick next source based on distance from current end, \n        // we just need to minimize the tour length from source to sinks.\n        // We use Nearest Neighbor for sinks.\n        \n        vector<int> sink_order;\n        vector<bool> sink_done_local(requests[best_u].size(), false);\n        int cur_sink_x = sources[best_u].x;\n        int cur_sink_y = sources[best_u].y;\n        \n        // Nearest Neighbor\n        for (int k = 0; k < requests[best_u].size(); ++k) {\n            int best_v = -1;\n            int min_d_sink = 1e9;\n            for (int i = 0; i < requests[best_u].size(); ++i) {\n                if (!sink_done_local[i]) {\n                    int d = dist({cur_sink_x, cur_sink_y, -1}, sinks[requests[best_u][i].first]);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                        best_v = i;\n                    }\n                }\n            }\n            if (best_v != -1) {\n                sink_done_local[best_v] = true;\n                sink_order.push_back(best_v);\n                int v_idx = requests[best_u][best_v].first;\n                cur_sink_x = sinks[v_idx].x;\n                cur_sink_y = sinks[v_idx].y;\n            }\n        }\n\n        // Execute Sink Tour\n        for (int idx : sink_order) {\n            int v_idx = requests[best_u][idx].first;\n            int amount = requests[best_u][idx].second;\n            int tx = sinks[v_idx].x;\n            int ty = sinks[v_idx].y;\n            \n            move_to(tx, ty);\n            unload(amount);\n        }\n\n        // Mark source as done\n        source_done[best_u] = true;\n        remaining_sources--;\n    }\n\n    // Output\n    for (const string &s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_int(0, 35);\nuniform_real_distribution<double> dist_real(0.0, 1.0);\n\nint N, M, T;\nint seed_count;\nvector<vector<int>> seeds;\nvector<int> seed_val;\nvector<vector<int>> adj;\nvector<int> pos_order;\nvector<int> grid;\nlong long current_score;\n\nlong long calc_edge_score(int u, int v) {\n    long long s = 0;\n    for (int l = 0; l < M; ++l) {\n        s += max(seeds[u][l], seeds[v][l]);\n    }\n    return s;\n}\n\nvoid init_adj() {\n    adj.assign(N * N, vector<int>());\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (i > 0) adj[u].push_back((i - 1) * N + j);\n            if (i < N - 1) adj[u].push_back((i + 1) * N + j);\n            if (j > 0) adj[u].push_back(i * N + (j - 1));\n            if (j < N - 1) adj[u].push_back(i * N + (j + 1));\n        }\n    }\n}\n\nvoid init_pos_order() {\n    pos_order.resize(N * N);\n    iota(pos_order.begin(), pos_order.end(), 0);\n    sort(pos_order.begin(), pos_order.end(), [&](int a, int b) {\n        return adj[a].size() > adj[b].size();\n    });\n}\n\nvoid init_grid() {\n    vector<int> p(seed_count);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        return seed_val[a] > seed_val[b];\n    });\n\n    for (int k = 0; k < N * N; ++k) {\n        grid[pos_order[k]] = p[k];\n    }\n\n    current_score = 0;\n    for (int i = 0; i < N * N; ++i) {\n        for (int n : adj[i]) {\n            if (i < n) {\n                current_score += calc_edge_score(grid[i], grid[n]);\n            }\n        }\n    }\n}\n\nvoid sa() {\n    double temp = 10000.0;\n    double cooling = 0.995;\n    int iterations = 50000;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int u = dist_int(gen);\n        int v = dist_int(gen);\n        if (u == v) continue;\n\n        long long delta = 0;\n        \n        // Remove contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta -= calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta -= calc_edge_score(grid[v], grid[n]);\n        }\n\n        swap(grid[u], grid[v]);\n\n        // Add contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta += calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta += calc_edge_score(grid[v], grid[n]);\n        }\n\n        if (delta >= 0 || dist_real(gen) < exp(delta / temp)) {\n            current_score += delta;\n        } else {\n            swap(grid[u], grid[v]);\n        }\n\n        temp *= cooling;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> T;\n    seed_count = 2 * N * (N - 1);\n    seeds.resize(seed_count, vector<int>(M));\n    seed_val.resize(seed_count);\n\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n            seed_val[i] += seeds[i][j];\n        }\n    }\n\n    init_adj();\n    init_pos_order();\n    grid.resize(N * N);\n\n    for (int t = 0; t < T; ++t) {\n        // Recalculate seed_val in case we need to re-sort (though we do it inside init_grid)\n        // Actually, seeds change every turn, so we must update seed_val\n        for (int i = 0; i < seed_count; ++i) {\n            seed_val[i] = 0;\n            for (int j = 0; j < M; ++j) {\n                seed_val[i] += seeds[i][j];\n            }\n        }\n\n        init_grid();\n        sa();\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << grid[i * N + j] << (j == N - 1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Takoyaki {\n    Point src, tgt;\n    int id;\n    bool done = false;\n};\n\nint N, M, V;\nvector<string> s_grid, t_grid;\nvector<Takoyaki> takoyakis;\nvector<int> edge_len;\nint root_x, root_y;\nint dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // R, D, L, U\nchar dir_char[4] = {'R', 'D', 'L', 'U'};\n\n// Current state\nint arm_dir[16]; // direction of each edge (0-3)\nbool holding[16]; // whether each fingertip is holding\nPoint fingertip_pos[16]; // current position of each fingertip\n\n// Calculate fingertip positions based on root and directions\nvoid update_fingertip_positions() {\n    for (int i = 1; i < edge_len.size() + 1; i++) {\n        int fx = root_x + dir[arm_dir[i]][0] * edge_len[i];\n        int fy = root_y + dir[arm_dir[i]][1] * edge_len[i];\n        fingertip_pos[i] = {fx, fy};\n    }\n}\n\n// Check if position is valid\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there's a takoyaki at position\nbool has_takoyaki(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1';\n}\n\n// Check if position is a target\nbool is_target(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return t_grid[x][y] == '1';\n}\n\n// Check if position has been filled (target completed)\nbool is_filled(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1' && t_grid[x][y] == '1';\n}\n\n// Find nearest available source for a fingertip\nPoint find_nearest_source(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].src.x) + abs(fp.y - takoyakis[i].src.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].src;\n        }\n    }\n    return best;\n}\n\n// Find nearest available target for a fingertip\nPoint find_nearest_target(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].tgt.x) + abs(fp.y - takoyakis[i].tgt.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].tgt;\n        }\n    }\n    return best;\n}\n\n// Get direction to move towards a target\nint get_direction(Point current, Point target) {\n    if (current.x < target.x) return 1; // D\n    if (current.x > target.x) return 3; // U\n    if (current.y < target.y) return 0; // R\n    if (current.y > target.y) return 2; // L\n    return 0; // Default\n}\n\n// Get rotation to achieve desired direction\nchar get_rotation(int current_dir, int target_dir) {\n    int diff = (target_dir - current_dir + 4) % 4;\n    if (diff == 0) return '.';\n    if (diff == 1 || diff == 3) return 'R'; // clockwise\n    return 'L'; // counterclockwise\n}\n\n// Check if all takoyaki are delivered\nbool all_delivered() {\n    for (int i = 0; i < M; i++) {\n        if (!takoyakis[i].done) return false;\n    }\n    return true;\n}\n\n// Check if a source still has takoyaki\nbool source_has_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return s_grid[p.x][p.y] == '1' && t_grid[p.x][p.y] == '0';\n}\n\n// Check if a target needs takoyaki\nbool target_needs_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return t_grid[p.x][p.y] == '1' && s_grid[p.x][p.y] == '0';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> V;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    \n    for (int i = 0; i < N; i++) cin >> s_grid[i];\n    for (int i = 0; i < N; i++) cin >> t_grid[i];\n    \n    // Parse takoyaki positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                takoyakis.push_back({{i, j}, {0, 0}, (int)takoyakis.size()});\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (t_grid[i][j] == '1' && s_grid[i][j] == '0') {\n                // Find matching source\n                for (auto& t : takoyakis) {\n                    if (t.tgt.x == 0 && t.tgt.y == 0) {\n                        t.tgt = {i, j};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Design star topology robot\n    int num_fingertips = min(V - 1, M); // Each fingertip handles one takoyaki\n    \n    // Output robot design\n    cout << num_fingertips + 1 << \"\\n\";\n    edge_len.resize(num_fingertips + 1);\n    \n    // Use different edge lengths for better coverage\n    for (int i = 1; i <= num_fingertips; i++) {\n        edge_len[i] = min(i * 2, N - 1);\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Initial position: center of grid\n    root_x = N / 2;\n    root_y = N / 2;\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Initialize directions (all pointing right initially)\n    for (int i = 0; i <= num_fingertips; i++) {\n        arm_dir[i] = 0;\n        holding[i] = false;\n    }\n    \n    update_fingertip_positions();\n    \n    // Main operation loop\n    int turn = 0;\n    int max_turns = 80000; // Leave margin for system test\n    \n    while (turn < max_turns && !all_delivered()) {\n        string cmd = \"\";\n        \n        // Step 1: Decide arm movement\n        // Find average direction to move towards pending sources/targets\n        int total_dx = 0, total_dy = 0;\n        int count = 0;\n        \n        for (int i = 0; i < M; i++) {\n            if (takoyakis[i].done) continue;\n            if (holding[i % (num_fingertips + 1)]) {\n                // Moving towards target\n                total_dx += takoyakis[i].tgt.x - root_x;\n                total_dy += takoyakis[i].tgt.y - root_y;\n            } else {\n                // Moving towards source\n                total_dx += takoyakis[i].src.x - root_x;\n                total_dy += takoyakis[i].src.y - root_y;\n                count++;\n            }\n        }\n        \n        // Determine movement direction\n        char move = '.';\n        if (count > 0) {\n            if (abs(total_dx) > abs(total_dy)) {\n                if (total_dx > 0) move = 'D';\n                else if (total_dx < 0) move = 'U';\n            } else {\n                if (total_dy > 0) move = 'R';\n                else if (total_dy < 0) move = 'L';\n            }\n        }\n        \n        // Check if movement is valid\n        int nx = root_x, ny = root_y;\n        if (move == 'D') nx++;\n        else if (move == 'U') nx--;\n        else if (move == 'R') ny++;\n        else if (move == 'L') ny--;\n        \n        if (!is_valid(nx, ny)) move = '.';\n        else { root_x = nx; root_y = ny; }\n        \n        cmd += move;\n        \n        // Step 2: Decide rotations for each fingertip\n        for (int i = 1; i <= num_fingertips; i++) {\n            char rot = '.';\n            \n            // Find what this fingertip should do\n            Point fp = fingertip_pos[i];\n            \n            if (holding[i]) {\n                // Try to drop at target\n                Point tgt = find_nearest_target(fp);\n                if (tgt.x >= 0 && target_needs_takoyaki(tgt)) {\n                    // Calculate direction to reach target\n                    int dx = tgt.x - root_x;\n                    int dy = tgt.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            } else {\n                // Try to pick from source\n                Point src = find_nearest_source(fp);\n                if (src.x >= 0 && source_has_takoyaki(src)) {\n                    // Calculate direction to reach source\n                    int dx = src.x - root_x;\n                    int dy = src.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            }\n            \n            cmd += rot;\n        }\n        \n        // Step 3: Decide pick/place actions\n        for (int i = 1; i <= num_fingertips; i++) {\n            update_fingertip_positions();\n            Point fp = fingertip_pos[i];\n            char action = '.';\n            \n            if (is_valid(fp.x, fp.y)) {\n                if (holding[i] && target_needs_takoyaki(fp.x, fp.y)) {\n                    // Drop takoyaki\n                    action = 'P';\n                    holding[i] = false;\n                    s_grid[fp.x][fp.y] = '1';\n                    \n                    // Mark as done\n                    for (int j = 0; j < M; j++) {\n                        if (!takoyakis[j].done && \n                            takoyakis[j].tgt.x == fp.x && \n                            takoyakis[j].tgt.y == fp.y) {\n                            takoyakis[j].done = true;\n                            break;\n                        }\n                    }\n                } else if (!holding[i] && source_has_takoyaki(fp.x, fp.y)) {\n                    // Pick takoyaki\n                    action = 'P';\n                    holding[i] = true;\n                    s_grid[fp.x][fp.y] = '0';\n                }\n            }\n            \n            cmd += action;\n        }\n        \n        // Add '.' for root (not a fingertip)\n        cmd += '.';\n        \n        cout << cmd << \"\\n\";\n        turn++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Distance squared\nlong long distSq(Point p1, Point p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Simple DSU for clustering\nstruct SimpleDSU {\n    vector<int> parent;\n    SimpleDSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx != ry) parent[rx] = ry;\n    }\n};\n\nstruct ClusterInfo {\n    int id;\n    vector<int> indices;\n    long long minX, maxX, minY, maxY;\n    int m_count, s_count;\n    long long score;\n};\n\n// Check if point is inside or on boundary of orthogonal polygon\nbool isInside(const vector<Point>& poly, Point p) {\n    int n = poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        bool cond1 = ((poly[i].y > p.y) != (poly[j].y > p.y));\n        if (poly[j].y != poly[i].y) {\n            bool cond2 = (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (double)(poly[j].y - poly[i].y) + poly[i].x);\n            if (cond1 && cond2) inside = !inside;\n        }\n    }\n    if (!inside) {\n        for (int i = 0; i < n; ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % n];\n            if (p1.x == p2.x) {\n                if (p.x == p1.x && min(p1.y, p2.y) <= p.y && p.y <= max(p1.y, p2.y)) return true;\n            } else {\n                if (p.y == p1.y && min(p1.x, p2.x) <= p.x && p.x <= max(p1.x, p2.x)) return true;\n            }\n        }\n    }\n    return inside;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // 1. Cluster Mackerels\n    const long long CLUSTER_DIST_SQ = 6000LL * 6000LL;\n    SimpleDSU dsu_m(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (distSq(mackerels[i], mackerels[j]) <= CLUSTER_DIST_SQ) {\n                dsu_m.unite(i, j);\n            }\n        }\n    }\n\n    vector<vector<int>> m_clusters(N);\n    for (int i = 0; i < N; ++i) {\n        m_clusters[dsu_m.find(i)].push_back(i);\n    }\n\n    // 2. Evaluate Clusters\n    vector<ClusterInfo> good_clusters;\n    for (int i = 0; i < N; ++i) {\n        if (m_clusters[i].empty()) continue;\n        \n        long long minX = 1e9, maxX = -1e9, minY = 1e9, maxY = -1e9;\n        for (int idx : m_clusters[i]) {\n            minX = min(minX, mackerels[idx].x);\n            maxX = max(maxX, mackerels[idx].x);\n            minY = min(minY, mackerels[idx].y);\n            maxY = max(maxY, mackerels[idx].y);\n        }\n\n        int m_cnt = m_clusters[i].size();\n        int s_cnt = 0;\n        for (const auto& s : sardines) {\n            if (s.x >= minX && s.x <= maxX && s.y >= minY && s.y <= maxY) {\n                s_cnt++;\n            }\n        }\n\n        long long sc = (long long)m_cnt - s_cnt;\n        if (sc > 0) {\n            good_clusters.push_back({i, m_clusters[i], minX, maxX, minY, maxY, m_cnt, s_cnt, sc});\n        }\n    }\n\n    // 3. Merge Good Clusters\n    sort(good_clusters.begin(), good_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n        return a.score > b.score;\n    });\n\n    vector<int> used(N, 0);\n    vector<ClusterInfo> final_clusters;\n    \n    auto distBox = [](const ClusterInfo& a, const ClusterInfo& b) {\n        long long dx = max(0LL, max(a.minX, b.minX) - min(a.maxX, b.maxX));\n        long long dy = max(0LL, max(a.minY, b.minY) - min(a.maxY, b.maxY));\n        return dx * dx + dy * dy;\n    };\n\n    for (int i = 0; i < (int)good_clusters.size(); ++i) {\n        if (used[i]) continue;\n        \n        ClusterInfo current = good_clusters[i];\n        used[i] = 1;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int j = 0; j < (int)good_clusters.size(); ++j) {\n                if (i == j || used[j]) continue;\n                \n                long long d2 = distBox(current, good_clusters[j]);\n                if (d2 <= 2000LL * 2000LL) { \n                    current.minX = min(current.minX, good_clusters[j].minX);\n                    current.maxX = max(current.maxX, good_clusters[j].maxX);\n                    current.minY = min(current.minY, good_clusters[j].minY);\n                    current.maxY = max(current.maxY, good_clusters[j].maxY);\n                    \n                    int m_cnt = 0;\n                    int s_cnt = 0;\n                    for (const auto& m : mackerels) {\n                        if (m.x >= current.minX && m.x <= current.maxX && m.y >= current.minY && m.y <= current.maxY) m_cnt++;\n                    }\n                    for (const auto& s : sardines) {\n                        if (s.x >= current.minX && s.x <= current.maxX && s.y >= current.minY && s.y <= current.maxY) s_cnt++;\n                    }\n                    current.m_count = m_cnt;\n                    current.s_count = s_cnt;\n                    current.score = (long long)m_cnt - s_cnt;\n                    \n                    used[j] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (current.score > 0) {\n            final_clusters.push_back(current);\n        }\n    }\n\n    if (final_clusters.empty()) {\n        cout << 4 << \"\\n\";\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Try to find the best valid polygon\n    ClusterInfo best_cluster = final_clusters[0];\n    vector<Point> best_poly;\n    long long best_score = -1e18;\n\n    for (const auto& cluster : final_clusters) {\n        long long cur_minX = cluster.minX;\n        long long cur_maxX = cluster.maxX;\n        long long cur_minY = cluster.minY;\n        long long cur_maxY = cluster.maxY;\n\n        // Shrink Phase: Iteratively remove sardines on boundary\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (const auto& s : sardines) {\n                if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_minX) {\n                    cur_minX = s.x + 1;\n                    changed = true;\n                }\n                if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_maxX) {\n                    cur_maxX = s.x - 1;\n                    changed = true;\n                }\n                if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_minY) {\n                    cur_minY = s.y + 1;\n                    changed = true;\n                }\n                if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_maxY) {\n                    cur_maxY = s.y - 1;\n                    changed = true;\n                }\n            }\n        }\n\n        if (cur_minX > cur_maxX || cur_minY > cur_maxY) continue;\n\n        // Calculate score for this box\n        int m_cnt = 0;\n        int s_cnt = 0;\n        for (const auto& m : mackerels) {\n            if (m.x >= cur_minX && m.x <= cur_maxX && m.y >= cur_minY && m.y <= cur_maxY) m_cnt++;\n        }\n        for (const auto& s : sardines) {\n            if (s.x >= cur_minX && s.x <= cur_maxX && s.y >= cur_minY && s.y <= cur_maxY) s_cnt++;\n        }\n        long long sc = (long long)m_cnt - s_cnt;\n\n        if (sc > best_score) {\n            best_score = sc;\n            best_cluster = cluster; // Not strictly needed, but for debugging\n            best_poly.clear();\n            best_poly.push_back({cur_minX, cur_minY});\n            best_poly.push_back({cur_maxX, cur_minY});\n            best_poly.push_back({cur_maxX, cur_maxY});\n            best_poly.push_back({cur_minX, cur_maxY});\n        }\n    }\n\n    if (best_poly.empty()) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Notch Phase: Add notches to remove sardines on the boundary of the best_poly\n    // We only add notches on the 4 original sides to avoid intersection.\n    // We track intervals on each side to prevent overlapping notches.\n    \n    // Identify sardines on the 4 sides\n    struct SideSardine {\n        long long pos; // x for horizontal, y for vertical\n        int side; // 0: Bottom, 1: Top, 2: Left, 3: Right\n        Point p;\n    };\n    vector<SideSardine> sardines_on_sides;\n\n    long long minX = best_poly[0].x;\n    long long maxX = best_poly[1].x;\n    long long minY = best_poly[0].y;\n    long long maxY = best_poly[2].y;\n\n    for (const auto& s : sardines) {\n        // Check Bottom (y = minY)\n        if (s.y == minY && s.x > minX && s.x < maxX) {\n            sardines_on_sides.push_back({s.x, 0, s});\n        }\n        // Check Top (y = maxY)\n        if (s.y == maxY && s.x > minX && s.x < maxX) {\n            sardines_on_sides.push_back({s.x, 1, s});\n        }\n        // Check Left (x = minX)\n        if (s.x == minX && s.y > minY && s.y < maxY) {\n            sardines_on_sides.push_back({s.y, 2, s});\n        }\n        // Check Right (x = maxX)\n        if (s.x == maxX && s.y > minY && s.y < maxY) {\n            sardines_on_sides.push_back({s.y, 3, s});\n        }\n    }\n\n    // Sort by side and position\n    sort(sardines_on_sides.begin(), sardines_on_sides.end(), [](const SideSardine& a, const SideSardine& b) {\n        if (a.side != b.side) return a.side < b.side;\n        return a.pos < b.pos;\n    });\n\n    // Track used intervals\n    // For each side, store a list of [start, end] intervals that are notched\n    vector<vector<pair<long long, long long>>> used_intervals(4);\n\n    for (const auto& ss : sardines_on_sides) {\n        int side = ss.side;\n        long long pos = ss.pos;\n        \n        // Check overlap\n        bool overlap = false;\n        for (auto& interval : used_intervals[side]) {\n            // Notch at pos occupies [pos, pos+1] (since notch depth is 1 and width is 1)\n            // Actually, notch at x=pos on bottom edge creates vertices at pos and pos+1.\n            // So it occupies [pos, pos+1].\n            if (pos < interval.second && pos + 1 > interval.first) {\n                overlap = true;\n                break;\n            }\n        }\n        if (overlap) continue;\n\n        // Check if notch removes a mackerel\n        // Notch location:\n        // Bottom: (pos, minY+1)\n        // Top: (pos, maxY-1)\n        // Left: (minX+1, pos)\n        // Right: (maxX-1, pos)\n        Point notch_loc;\n        if (side == 0) notch_loc = {pos, minY + 1};\n        else if (side == 1) notch_loc = {pos, maxY - 1};\n        else if (side == 2) notch_loc = {minX + 1, pos};\n        else notch_loc = {maxX - 1, pos};\n\n        bool has_mackerel = false;\n        for (const auto& m : mackerels) {\n            if (m.x == notch_loc.x && m.y == notch_loc.y) {\n                has_mackerel = true;\n                break;\n            }\n        }\n        if (has_mackerel) continue; // Don't notch if it removes a mackerel\n\n        // Add notch\n        used_intervals[side].push_back({pos, pos + 1});\n        \n        // Insert vertices into best_poly\n        // We need to reconstruct the polygon with notches\n        // To keep it simple, we will rebuild the polygon from the intervals at the end\n    }\n\n    // Reconstruct polygon\n    vector<Point> final_poly;\n    \n    // Bottom edge (minY)\n    long long curr_x = minX;\n    for (auto& interval : used_intervals[0]) {\n        // Move to start of notch\n        final_poly.push_back({curr_x, minY});\n        // Notch\n        final_poly.push_back({interval.first, minY + 1});\n        final_poly.push_back({interval.second, minY + 1});\n        final_poly.push_back({interval.second, minY});\n        curr_x = interval.second;\n    }\n    final_poly.push_back({curr_x, minY}); // End of bottom edge (maxX)\n\n    // Right edge (maxX)\n    long long curr_y = minY;\n    for (auto& interval : used_intervals[3]) {\n        final_poly.push_back({maxX, curr_y});\n        final_poly.push_back({maxX - 1, interval.first});\n        final_poly.push_back({maxX - 1, interval.second});\n        final_poly.push_back({maxX, interval.second});\n        curr_y = interval.second;\n    }\n    final_poly.push_back({maxX, curr_y}); // End of right edge (maxY)\n\n    // Top edge (maxY)\n    curr_x = maxX;\n    for (auto& interval : used_intervals[1]) {\n        final_poly.push_back({curr_x, maxY});\n        final_poly.push_back({interval.second, maxY - 1}); // Note: Top edge goes right to left\n        final_poly.push_back({interval.first, maxY - 1});\n        final_poly.push_back({interval.first, maxY});\n        curr_x = interval.first;\n    }\n    final_poly.push_back({curr_x, maxY}); // End of top edge (minX)\n\n    // Left edge (minX)\n    curr_y = maxY;\n    for (auto& interval : used_intervals[2]) {\n        final_poly.push_back({minX, curr_y});\n        final_poly.push_back({minX + 1, interval.second}); // Left edge goes top to bottom\n        final_poly.push_back({minX + 1, interval.first});\n        final_poly.push_back({minX, interval.first});\n        curr_y = interval.first;\n    }\n    final_poly.push_back({minX, curr_y}); // End of left edge (minY)\n\n    // Remove duplicates\n    vector<Point> unique_poly;\n    for (int i = 0; i < final_poly.size(); ++i) {\n        if (i > 0 && final_poly[i].x == final_poly[i-1].x && final_poly[i].y == final_poly[i-1].y) continue;\n        unique_poly.push_back(final_poly[i]);\n    }\n    if (unique_poly.size() > 1 && unique_poly.front().x == unique_poly.back().x && unique_poly.front().y == unique_poly.back().y) {\n        unique_poly.pop_back();\n    }\n    final_poly = unique_poly;\n\n    if (final_poly.size() < 4) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << final_poly.size() << \"\\n\";\n    for (const auto& p : final_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Placement {\n    int p;  // rectangle index\n    int r;  // rotation (0 or 1)\n    char d; // direction ('U' or 'L')\n    int b;  // reference rectangle index (-1 or index)\n};\n\nstruct Rect {\n    int id;\n    int w, h;\n    int x, y;\n};\n\nclass Solver {\nprivate:\n    int N, T;\n    double sigma;\n    vector<pair<int, int>> wh;\n    mt19937 rng;\n    int best_W = 2e9, best_H = 2e9;\n    vector<Placement> best_placements;\n    \n    // Calculate actual placement position\n    pair<int, int> calculatePosition(const vector<Rect>& placed, int rw, int rh, \n                                     char dir, int ref) {\n        int x = 0, y = 0;\n        \n        if (dir == 'U') {\n            // Place upward - align left edge with reference's right edge (or x=0)\n            x = (ref == -1) ? 0 : placed[ref].x + placed[ref].w;\n            y = 0;\n            // Move up until hitting something\n            for (const auto& r : placed) {\n                if (x < r.x + r.w && x + rw > r.x) {\n                    y = max(y, r.y + r.h);\n                }\n            }\n        } else {\n            // Place leftward - align top edge with reference's bottom edge (or y=0)\n            y = (ref == -1) ? 0 : placed[ref].y + placed[ref].h;\n            x = 0;\n            // Move left until hitting something\n            for (const auto& r : placed) {\n                if (y < r.y + r.h && y + rh > r.y) {\n                    x = max(x, r.x + r.w);\n                }\n            }\n        }\n        \n        return {x, y};\n    }\n    \n    // Calculate bounding box\n    pair<int, int> getBoundingBox(const vector<Rect>& placed) {\n        if (placed.empty()) return {0, 0};\n        int W = 0, H = 0;\n        for (const auto& r : placed) {\n            W = max(W, r.x + r.w);\n            H = max(H, r.y + r.h);\n        }\n        return {W, H};\n    }\n    \n    // Try greedy placement with given strategy\n    vector<Placement> greedyPlacement(int strategy, bool trySkip = false) {\n        vector<Placement> placements;\n        vector<Rect> placed;\n        \n        for (int i = 0; i < N; i++) {\n            // Decide whether to skip this rectangle\n            bool skip = false;\n            if (trySkip && strategy == 2 && rng() % 5 == 0) {\n                skip = true;\n            }\n            \n            if (skip) continue;\n            \n            int best_score = 2e9;\n            Placement best_p = {i, 0, 'U', -1};\n            \n            for (int rot = 0; rot < 2; rot++) {\n                int rw = rot ? wh[i].second : wh[i].first;\n                int rh = rot ? wh[i].first : wh[i].second;\n                \n                for (char dir : {'U', 'L'}) {\n                    // Try different reference rectangles\n                    int max_ref = (int)placed.size() - 1;\n                    for (int ref = -1; ref <= max_ref; ref++) {\n                        auto [x, y] = calculatePosition(placed, rw, rh, dir, ref);\n                        \n                        // Calculate bounding box with this placement\n                        int W = 0, H = 0;\n                        for (const auto& r : placed) {\n                            W = max(W, r.x + r.w);\n                            H = max(H, r.y + r.h);\n                        }\n                        W = max(W, x + rw);\n                        H = max(H, y + rh);\n                        \n                        int score = W + H;\n                        if (score < best_score) {\n                            best_score = score;\n                            best_p = {i, rot, dir, ref};\n                        }\n                    }\n                }\n            }\n            \n            placements.push_back(best_p);\n            int rw = best_p.r ? wh[i].second : wh[i].first;\n            int rh = best_p.r ? wh[i].first : wh[i].second;\n            auto [x, y] = calculatePosition(placed, rw, rh, best_p.d, best_p.b);\n            placed.push_back({i, rw, rh, x, y});\n        }\n        \n        return placements;\n    }\n    \n    // Try multiple strategies and return best\n    vector<Placement> findBestPlacement() {\n        vector<Placement> best = greedyPlacement(0);\n        int best_score = 2e9;\n        \n        // Calculate score for initial best\n        vector<Rect> placed;\n        for (const auto& p : best) {\n            int rw = p.r ? wh[p.p].second : wh[p.p].first;\n            int rh = p.r ? wh[p.p].first : wh[p.p].second;\n            auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n            placed.push_back({p.p, rw, rh, x, y});\n        }\n        auto [W, H] = getBoundingBox(placed);\n        best_score = W + H;\n        \n        // Try different strategies\n        for (int s = 1; s <= 3; s++) {\n            vector<Placement> cur = greedyPlacement(s, s == 2);\n            placed.clear();\n            for (const auto& p : cur) {\n                int rw = p.r ? wh[p.p].second : wh[p.p].first;\n                int rh = p.r ? wh[p.p].first : wh[p.p].second;\n                auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n                placed.push_back({p.p, rw, rh, x, y});\n            }\n            auto [W, H] = getBoundingBox(placed);\n            int score = W + H;\n            \n            if (score < best_score) {\n                best_score = score;\n                best = cur;\n            }\n        }\n        \n        // Try with some random variations\n        for (int iter = 0; iter < 5; iter++) {\n            vector<Placement> cur = greedyPlacement(0);\n            // Randomly modify some placements\n            for (int i = 0; i < (int)cur.size(); i++) {\n                if (rng() % 3 == 0) {\n                    cur[i].r ^= 1;\n                }\n            }\n            \n            placed.clear();\n            for (const auto& p : cur) {\n                int rw = p.r ? wh[p.p].second : wh[p.p].first;\n                int rh = p.r ? wh[p.p].first : wh[p.p].second;\n                auto [x, y] = calculatePosition(placed, rw, rh, p.d, p.b);\n                placed.push_back({p.p, rw, rh, x, y});\n            }\n            auto [W, H] = getBoundingBox(placed);\n            int score = W + H;\n            \n            if (score < best_score) {\n                best_score = score;\n                best = cur;\n            }\n        }\n        \n        return best;\n    }\n    \npublic:\n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void solve() {\n        cin >> N >> T >> sigma;\n        wh.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> wh[i].first >> wh[i].second;\n        }\n        \n        // Track time to avoid TLE\n        auto startTime = chrono::steady_clock::now();\n        const double MAX_TIME = 2.8; // Leave margin for system test\n        \n        for (int t = 0; t < T; t++) {\n            // Check time limit\n            auto currentTime = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed > MAX_TIME) break;\n            \n            // Find best placement\n            vector<Placement> placements = findBestPlacement();\n            \n            // Output placements\n            cout << placements.size() << \"\\n\";\n            for (const auto& p : placements) {\n                cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n            }\n            cout.flush();\n            \n            // Read feedback\n            int W, H;\n            cin >> W >> H;\n            \n            // Track best solution\n            if (W + H < best_W + best_H) {\n                best_W = W;\n                best_H = H;\n                best_placements = placements;\n            }\n            \n            // Optional: Output debug info\n            // cout << \"# Turn \" << t+1 << \" W=\" << W << \" H=\" << H << \" Score=\" << W+H << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.solve();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Global buffers to avoid reallocation overhead\nconst int MAXN = 1005;\nvector<int> adj[MAXN];\nint A[MAXN];\nint L[MAXN];\nint pc[MAXN]; // parent count: number of neighbors u with L[u] == L[v] - 1\nint p[MAXN];  // output parent array\nint x[MAXN], y[MAXN];\n\nvoid solve() {\n    int N, M, H;\n    // Read until EOF\n    while (cin >> N >> M >> H) {\n        // Read Beauty values\n        for (int i = 0; i < N; ++i) {\n            cin >> A[i];\n        }\n        // Read Edges\n        for (int i = 0; i < M; ++i) {\n            int u, v;\n            cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // Read Coordinates (ignored but must be read)\n        for (int i = 0; i < N; ++i) {\n            cin >> x[i] >> y[i];\n        }\n\n        // Initialize State\n        for (int i = 0; i < N; ++i) {\n            L[i] = 0;\n            pc[i] = 0;\n        }\n\n        // Random number generator\n        static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_int_distribution<int> dist_idx(0, N - 1);\n        uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n        // Simulated Annealing\n        // Increased iterations to 20,000 to allow better exploration within 2.0s\n        // T and decay tuned for longer run\n        int iterations = 20000;\n        double T = 1000.0;\n        double decay = 0.9995;\n\n        long long current_score = 0;\n        // current_score tracks sum L[v] * A[v]\n\n        // Pre-allocate candidate array to avoid vector allocation in loop\n        int candidates[2];\n        int c_count;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            // Pick random vertex\n            int v = dist_idx(rng);\n            \n            int old_L = L[v];\n            \n            // Candidate moves\n            c_count = 0;\n            if (old_L < H) candidates[c_count++] = old_L + 1;\n            if (old_L > 0) candidates[c_count++] = old_L - 1;\n            \n            // Shuffle candidates to avoid bias\n            shuffle(candidates, candidates + c_count, rng);\n            \n            bool move_accepted = false;\n            \n            for (int k = 0; k < c_count; ++k) {\n                int new_L = candidates[k];\n                if (new_L == old_L) continue;\n                \n                // Check validity\n                bool valid = true;\n                \n                // 1. Check v's own parent requirement\n                if (new_L > 0) {\n                    bool has_parent = false;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L - 1) {\n                            has_parent = true;\n                            break;\n                        }\n                    }\n                    if (!has_parent) valid = false;\n                }\n                \n                // 2. Check neighbors' parent count requirement\n                if (valid) {\n                    for (int u : adj[v]) {\n                        if (L[u] == old_L + 1) {\n                            // v was a parent, now not\n                            if (pc[u] == 1) {\n                                valid = false;\n                                break;\n                            }\n                        }\n                    }\n                }\n                \n                if (valid) {\n                    long long delta = (long long)(new_L - old_L) * A[v];\n                    // Calculate acceptance probability\n                    double prob = 1.0;\n                    if (delta < 0) {\n                        prob = exp((double)delta / T);\n                    }\n                    \n                    if (dist_prob(rng) < prob) {\n                        // Accept move\n                        L[v] = new_L;\n                        current_score += delta;\n                        \n                        // Update pc for neighbors\n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                pc[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                pc[u]++;\n                            }\n                        }\n                        move_accepted = true;\n                        break; // Accept first valid move\n                    }\n                }\n            }\n            \n            // Cool down\n            T *= decay;\n        }\n\n        // Construct parent array\n        for (int i = 0; i < N; ++i) {\n            if (L[i] == 0) {\n                p[i] = -1;\n            } else {\n                // Find a neighbor with L[u] == L[i] - 1\n                int parent = -1;\n                for (int u : adj[i]) {\n                    if (L[u] == L[i] - 1) {\n                        parent = u;\n                        break;\n                    }\n                }\n                p[i] = parent;\n            }\n        }\n\n        // Output\n        for (int i = 0; i < N; ++i) {\n            cout << p[i] << (i == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\n// Structure to represent a move\nstruct Move {\n    char d;\n    int p;\n};\n\n// Structure to represent a candidate move\nstruct Candidate {\n    int cost;\n    int oni_removed;\n    char d;\n    int p;\n    int shift_amount;\n};\n\nint N;\nvector<string> board;\nvector<Move> moves;\n\n// Count total Oni on the board\nint count_oni() {\n    int c = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\n// Get position of the first Fuku in a specific direction\n// Returns N if no Fuku found (for left/up), -1 if no Fuku found (for right/down)\nint get_first_fuku_row_left(int r) {\n    for (int j = 0; j < N; ++j) {\n        if (board[r][j] == 'o') return j;\n    }\n    return N;\n}\n\nint get_first_fuku_row_right(int r) {\n    for (int j = N - 1; j >= 0; --j) {\n        if (board[r][j] == 'o') return j;\n    }\n    return -1;\n}\n\nint get_first_fuku_col_up(int c) {\n    for (int i = 0; i < N; ++i) {\n        if (board[i][c] == 'o') return i;\n    }\n    return N;\n}\n\nint get_first_fuku_col_down(int c) {\n    for (int i = N - 1; i >= 0; --i) {\n        if (board[i][c] == 'o') return i;\n    }\n    return -1;\n}\n\n// Apply a shift operation k times\nvoid apply_move(char d, int p, int k) {\n    for (int step = 0; step < k; ++step) {\n        if (d == 'L') {\n            moves.push_back({'L', p});\n            for (int j = 0; j < N - 1; ++j) {\n                board[p][j] = board[p][j + 1];\n            }\n            board[p][N - 1] = '.';\n        } else if (d == 'R') {\n            moves.push_back({'R', p});\n            for (int j = N - 1; j > 0; --j) {\n                board[p][j] = board[p][j - 1];\n            }\n            board[p][0] = '.';\n        } else if (d == 'U') {\n            moves.push_back({'U', p});\n            for (int i = 0; i < N - 1; ++i) {\n                board[i][p] = board[i + 1][p];\n            }\n            board[N - 1][p] = '.';\n        } else if (d == 'D') {\n            moves.push_back({'D', p});\n            for (int i = N - 1; i > 0; --i) {\n                board[i][p] = board[i - 1][p];\n            }\n            board[0][p] = '.';\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n    board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> board[i];\n    }\n\n    // Greedy strategy to remove Oni\n    while (count_oni() > 0) {\n        Candidate best;\n        best.cost = 1e9;\n        best.oni_removed = 0;\n        best.shift_amount = 0;\n        bool found = false;\n\n        // Check Rows\n        for (int r = 0; r < N; ++r) {\n            // Left direction\n            int fuku_pos = get_first_fuku_row_left(r);\n            vector<int> oni_pos;\n            for (int j = 0; j < N; ++j) {\n                if (board[r][j] == 'x') oni_pos.push_back(j);\n            }\n            for (int p : oni_pos) {\n                if (p < fuku_pos) {\n                    int k = p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op < k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'L', r, k};\n                        found = true;\n                    }\n                } else {\n                    break; \n                }\n            }\n\n            // Right direction\n            fuku_pos = get_first_fuku_row_right(r);\n            oni_pos.clear();\n            for (int j = N - 1; j >= 0; --j) {\n                if (board[r][j] == 'x') oni_pos.push_back(j);\n            }\n            // oni_pos is sorted descending\n            for (int p : oni_pos) {\n                if (p > fuku_pos) {\n                    int k = (N - 1) - p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op > (N - 1) - k) benefit++; // op >= N - k\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'R', r, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n        }\n\n        // Check Cols\n        for (int c = 0; c < N; ++c) {\n            // Up direction\n            int fuku_pos = get_first_fuku_col_up(c);\n            vector<int> oni_pos;\n            for (int i = 0; i < N; ++i) {\n                if (board[i][c] == 'x') oni_pos.push_back(i);\n            }\n            for (int p : oni_pos) {\n                if (p < fuku_pos) {\n                    int k = p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op < k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'U', c, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n\n            // Down direction\n            fuku_pos = get_first_fuku_col_down(c);\n            oni_pos.clear();\n            for (int i = N - 1; i >= 0; --i) {\n                if (board[i][c] == 'x') oni_pos.push_back(i);\n            }\n            for (int p : oni_pos) {\n                if (p > fuku_pos) {\n                    int k = (N - 1) - p + 1;\n                    int benefit = 0;\n                    for (int op : oni_pos) {\n                        if (op > (N - 1) - k) benefit++;\n                    }\n                    if (!found || k < best.cost || (k == best.cost && benefit > best.oni_removed)) {\n                        best = {k, benefit, 'D', c, k};\n                        found = true;\n                    }\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (!found) {\n            // If no valid move is found, we cannot proceed safely.\n            // This should theoretically not happen given the problem constraints.\n            break;\n        }\n\n        apply_move(best.d, best.p, best.shift_amount);\n    }\n\n    for (const auto& m : moves) {\n        cout << m.d << \" \" << m.p << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables to store problem data and state\nint N, L;\nint T[105];\nint A[105], B[105];\nint current_cnt[105];\n\n// Function to simulate the cleaning process and calculate error\nlong long evaluate() {\n    // Reset counts\n    memset(current_cnt, 0, sizeof(current_cnt));\n    int cur = 0;\n    for(int w=0; w<L; ++w) {\n        current_cnt[cur]++;\n        // If count is odd, go to A[cur], else B[cur]\n        if (current_cnt[cur] & 1) cur = A[cur];\n        else cur = B[cur];\n    }\n    // Calculate total absolute error\n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(current_cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // Initialize RNG\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_node(0, N-1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Initialization based on target frequencies T[i]\n    // We want to distribute 2*N edges such that in-degree of i is proportional to T[i]\n    vector<int> targets;\n    targets.reserve(2 * N);\n    vector<int> base_counts(N, 0);\n    long long distributed = 0;\n    for(int i=0; i<N; ++i) {\n        long long k = (2LL * N * T[i]) / L;\n        base_counts[i] = k;\n        distributed += k;\n    }\n    long long remainder = 2 * N - distributed;\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    // Sort indices by T[i] descending to distribute remainder\n    sort(p.begin(), p.end(), [&](int i, int j){\n        return T[i] > T[j];\n    });\n    for(int i=0; i<remainder && i<N; ++i) {\n        base_counts[p[i]]++;\n    }\n    for(int i=0; i<N; ++i) {\n        for(int k=0; k<base_counts[i]; ++k) {\n            targets.push_back(i);\n        }\n    }\n    // Shuffle to avoid deterministic structure\n    shuffle(targets.begin(), targets.end(), rng);\n    // Assign A and B\n    for(int i=0; i<N; ++i) {\n        A[i] = targets[2*i];\n        B[i] = targets[2*i+1];\n    }\n\n    // Initial evaluation\n    long long current_err = evaluate();\n    long long best_err = current_err;\n    vector<int> best_A(N), best_B(N);\n    for(int i=0; i<N; ++i) {\n        best_A[i] = A[i];\n        best_B[i] = B[i];\n    }\n\n    // Simulated Annealing parameters\n    double temp = 1e7;\n    double cooling = 0.999;\n    \n    // Time limit handling\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Save current counts for potential revert\n        vector<int> saved_cnt(N);\n        for(int i=0; i<N; ++i) saved_cnt[i] = current_cnt[i];\n        \n        // Pick node u to modify (biased by error)\n        int u = dist_node(rng);\n        long long total_err = 0;\n        for(int i=0; i<N; ++i) total_err += abs(current_cnt[i] - T[i]);\n        if (total_err > 0) {\n            long long r = rng() % total_err;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = abs(current_cnt[i] - T[i]);\n                sum += w;\n                if (sum > r) {\n                    u = i;\n                    break;\n                }\n            }\n        }\n\n        // Pick target node v (biased by need)\n        int v = dist_node(rng);\n        long long total_need = 0;\n        for(int i=0; i<N; ++i) {\n            if (T[i] > current_cnt[i]) total_need += (T[i] - current_cnt[i]);\n        }\n        if (total_need > 0) {\n            long long r = rng() % total_need;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = max(0, T[i] - current_cnt[i]);\n                sum += w;\n                if (sum > r) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n\n        // Propose change: modify A[u] or B[u]\n        int edge_type = dist_node(rng) % 2;\n        int old_target = (edge_type == 0) ? A[u] : B[u];\n        \n        if (edge_type == 0) A[u] = v;\n        else B[u] = v;\n\n        // Evaluate new state\n        long long new_err = evaluate();\n        \n        // Acceptance probability\n        double delta = new_err - current_err;\n        double prob = exp(-delta / temp);\n        \n        if (delta < 0 || dist_prob(rng) < prob) {\n            current_err = new_err;\n            if (current_err < best_err) {\n                best_err = current_err;\n                for(int i=0; i<N; ++i) {\n                    best_A[i] = A[i];\n                    best_B[i] = B[i];\n                }\n            }\n        } else {\n            // Revert change\n            if (edge_type == 0) A[u] = old_target;\n            else B[u] = old_target;\n            // Restore counts\n            for(int i=0; i<N; ++i) current_cnt[i] = saved_cnt[i];\n        }\n        \n        // Cool down\n        temp *= cooling;\n        if (temp < 1e-3) temp = 1e-3;\n    }\n\n    // Output best solution\n    for(int i=0; i<N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\n// Structure to represent a city\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    double cx, cy; // Estimated center coordinates\n};\n\n// Structure to represent an edge\nstruct Edge {\n    int u, v;\n    int dist;\n    bool operator<(const Edge& other) const {\n        if (dist != other.dist) return dist < other.dist;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\n// Union-Find data structure\nclass DSU {\npublic:\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) {\n            parent[rootX] = rootY;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<City> cities;\nvector<vector<int>> groups; // groups[i] contains list of city IDs for group i\nint query_cnt = 0;\n\n// Calculate estimated distance between two cities\nint calc_dist(int i, int j) {\n    double dx = cities[i].cx - cities[j].cx;\n    double dy = cities[i].cy - cities[j].cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Function to perform a query\nvoid perform_query(const vector<int>& subset) {\n    if (query_cnt >= Q) return;\n    cout << \"? \" << subset.size();\n    for (int id : subset) {\n        cout << \" \" << id;\n    }\n    cout << endl;\n    query_cnt++;\n}\n\n// Function to read query response\nvector<pair<int, int>> read_query_response(int size) {\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < size - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.push_back({u, v});\n    }\n    return edges;\n}\n\n// Function to build MST for a group using estimated distances\nvector<pair<int, int>> build_estimated_mst(const vector<int>& group) {\n    vector<Edge> all_edges;\n    int sz = (int)group.size();\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = calc_dist(u, v);\n            all_edges.push_back({u, v, d});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n\n    DSU dsu(sz);\n    vector<pair<int, int>> mst_edges;\n    \n    // Map global IDs to local indices\n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        if (u_idx != -1 && v_idx != -1) {\n            if (dsu.unite(u_idx, v_idx)) {\n                mst_edges.push_back({e.u, e.v});\n                if ((int)mst_edges.size() == sz - 1) break;\n            }\n        }\n    }\n    return mst_edges;\n}\n\n// Function to calculate estimated MST cost for a group\nint calc_estimated_cost(const vector<int>& group) {\n    int sz = (int)group.size();\n    if (sz <= 1) return 0;\n    \n    vector<Edge> all_edges;\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = calc_dist(u, v);\n            all_edges.push_back({u, v, d});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n    \n    DSU dsu(sz);\n    int cost = 0;\n    int edges_count = 0;\n    \n    for (const auto& e : all_edges) {\n        // Find local indices\n        int u_idx = -1, v_idx = -1;\n        for (int k = 0; k < sz; ++k) {\n            if (group[k] == e.u) u_idx = k;\n            if (group[k] == e.v) v_idx = k;\n        }\n        \n        if (u_idx != -1 && v_idx != -1 && dsu.unite(u_idx, v_idx)) {\n            cost += e.dist;\n            edges_count++;\n        }\n    }\n    return cost;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2.0;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2.0;\n    }\n\n    // Sort cities by X then Y to form spatially contiguous groups\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (cities[a].cx != cities[b].cx) return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n\n    // Assign cities to groups\n    groups.resize(M);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(p[current_idx++]);\n        }\n    }\n\n    // Local Search Optimization: Swap boundary cities between adjacent groups\n    auto start_time = chrono::high_resolution_clock::now();\n    auto time_limit = chrono::high_resolution_clock::now() + chrono::milliseconds(1500);\n\n    for (int iter = 0; iter < 10; ++iter) {\n        bool improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            if (groups[i].empty() || groups[i+1].empty()) continue;\n            \n            int u = groups[i].back();\n            int v = groups[i+1].front();\n            \n            int cost_before = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            swap(groups[i].back(), groups[i+1].front());\n            \n            int cost_after = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            if (cost_after < cost_before) {\n                improved = true;\n            } else {\n                swap(groups[i].back(), groups[i+1].front());\n            }\n        }\n        if (!improved) break;\n        \n        auto now = chrono::high_resolution_clock::now();\n        if (now > time_limit) break;\n    }\n\n    // Query Phase\n    vector<vector<pair<int, int>>> group_queried_edges(M);\n\n    // 1. Query small groups (3 <= size <= L)\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] >= 3 && G[i] <= L) {\n            perform_query(groups[i]);\n            group_queried_edges[i] = read_query_response(G[i]);\n        }\n    }\n\n    // 2. Query subsets of large groups\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] > L) {\n            // Query overlapping subsets of size L to get more edges\n            int step = max(2, L / 2);\n            for (int start = 0; start < G[i]; start += step) {\n                if (query_cnt >= Q) break;\n                int end = min(start + L, G[i]);\n                if (end - start < 2) continue;\n                \n                vector<int> subset;\n                for (int k = start; k < end; ++k) {\n                    subset.push_back(groups[i][k]);\n                }\n                \n                perform_query(subset);\n                vector<pair<int, int>> sub_edges = read_query_response(end - start);\n                \n                for (auto& e : sub_edges) {\n                    group_queried_edges[i].push_back(e);\n                }\n            }\n        }\n    }\n\n    // Final Output\n    cout << \"!\" << endl;\n\n    for (int i = 0; i < M; ++i) {\n        // Output cities\n        for (int j = 0; j < G[i]; ++j) {\n            cout << groups[i][j] << (j == G[i] - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n\n        // Output edges\n        if (G[i] <= 1) continue;\n\n        vector<pair<int, int>> final_edges;\n        int sz = G[i];\n\n        if (!group_queried_edges[i].empty()) {\n            // Combine queried edges (priority) with estimated edges\n            vector<Edge> all_edges;\n            \n            // Add queried edges with weight 0 (highest priority)\n            for (auto& e : group_queried_edges[i]) {\n                all_edges.push_back({e.first, e.second, 0});\n            }\n            \n            // Add estimated edges\n            for (int u_idx = 0; u_idx < sz; ++u_idx) {\n                for (int v_idx = u_idx + 1; v_idx < sz; ++v_idx) {\n                    int u = groups[i][u_idx];\n                    int v = groups[i][v_idx];\n                    int d = calc_dist(u, v);\n                    all_edges.push_back({u, v, d});\n                }\n            }\n            \n            sort(all_edges.begin(), all_edges.end());\n            \n            // Map global IDs to local indices\n            vector<int> id_to_idx(N, -1);\n            for (int k = 0; k < sz; ++k) {\n                id_to_idx[groups[i][k]] = k;\n            }\n            \n            DSU dsu(sz);\n            int edges_count = 0;\n            \n            for (const auto& e : all_edges) {\n                int u_idx = id_to_idx[e.u];\n                int v_idx = id_to_idx[e.v];\n                \n                if (u_idx != -1 && v_idx != -1) {\n                    if (dsu.unite(u_idx, v_idx)) {\n                        final_edges.push_back({e.u, e.v});\n                        edges_count++;\n                        if (edges_count == sz - 1) break;\n                    }\n                }\n            }\n        } else {\n            // No queried edges, use estimated MST\n            final_edges = build_estimated_mst(groups[i]);\n        }\n        \n        for (const auto& e : final_edges) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\n// Directions: U, D, L, R\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dirChar[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nclass SkatingSolver {\nprivate:\n    int n;\n    vector<Point> targets;\n    Point currentPos;\n    vector<vector<bool>> blocks;\n    vector<pair<char, char>> actions;\n    int actionCount = 0;\n    \n    bool isValid(int x, int y) const {\n        return x >= 0 && x < n && y >= 0 && y < n;\n    }\n    \n    bool hasBlock(int x, int y) const {\n        return isValid(x, y) && blocks[x][y];\n    }\n    \n    // Check if we can slide from currentPos in direction d and reach target\n    bool canSlideToPoint(Point target, int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny)) return false;\n            if (nx == target.x && ny == target.y) return true;\n            if (hasBlock(nx, ny)) return false;\n            \n            x = nx;\n            y = ny;\n        }\n    }\n    \n    // Find where we would stop if we slide in direction d\n    Point slideDestination(int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                break;\n            }\n            x = nx;\n            y = ny;\n        }\n        \n        return {x, y};\n    }\n    \n    // Safe action execution with validation\n    bool executeAction(char action, char dir) {\n        if (actionCount >= 2 * N * M) return false;\n        \n        int d = 0;\n        if (dir == 'U') d = 0;\n        else if (dir == 'D') d = 1;\n        else if (dir == 'L') d = 2;\n        else if (dir == 'R') d = 3;\n        \n        if (action == 'M') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                return false;  // Invalid move\n            }\n            currentPos = {nx, ny};\n        } else if (action == 'S') {\n            Point dest = slideDestination(d);\n            if (dest == currentPos) {\n                return false;  // No movement possible\n            }\n            currentPos = dest;\n        } else if (action == 'A') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny)) {\n                return false;  // Can't alter outside grid\n            }\n            blocks[nx][ny] = !blocks[nx][ny];\n        }\n        \n        actions.push_back({action, dir});\n        actionCount++;\n        return true;\n    }\n    \n    // BFS to find path using Move actions\n    vector<pair<char, char>> bfsPath(Point target) {\n        vector<pair<char, char>> path;\n        \n        using State = tuple<int, int, int>;\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<int>> parentDir(n, vector<int>(n, -1));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                // Reconstruct path\n                int cx = x, cy = y;\n                vector<int> dirs;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    dirs.push_back(parentDir[cx][cy]);\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                // Execute moves in correct order\n                for (int i = dirs.size() - 1; i >= 0; i--) {\n                    executeAction('M', dirChar[dirs[i]]);\n                }\n                \n                return path;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parentDir[nx][ny] = dir;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return path;\n    }\n    \n    // Try to reach target using sliding with block placement\n    bool trySlideToTarget(Point target) {\n        for (int d = 0; d < 4; d++) {\n            if (canSlideToPoint(target, d)) {\n                // Check if we need to place a block after target\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                // If there's already a block or we're at boundary, we can slide directly\n                if (!isValid(stopX, stopY) || hasBlock(stopX, stopY)) {\n                    executeAction('S', dirChar[d]);\n                    return true;\n                }\n                \n                // Need to place block after target to stop the slide\n                executeAction('A', dirChar[d]);\n                executeAction('S', dirChar[d]);\n                executeAction('A', dirChar[d]);  // Remove block\n                \n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // Find optimal path to target\n    void findPathToTarget(Point target) {\n        // First try sliding (most efficient)\n        if (trySlideToTarget(target)) {\n            return;\n        }\n        \n        // Fall back to BFS with Move actions\n        bfsPath(target);\n    }\n\npublic:\n    SkatingSolver(int n) : n(n) {\n        blocks.assign(n, vector<bool>(n, false));\n    }\n    \n    void setInitialPosition(int x, int y) {\n        currentPos = {x, y};\n    }\n    \n    void addTarget(int x, int y) {\n        targets.push_back({x, y});\n    }\n    \n    void solve() {\n        for (const auto& target : targets) {\n            if (actionCount >= 2 * N * M) break;\n            \n            findPathToTarget(target);\n        }\n    }\n    \n    void output() const {\n        for (const auto& action : actions) {\n            cout << action.first << \" \" << action.second << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    SkatingSolver solver(n);\n    \n    int x, y;\n    cin >> x >> y;\n    solver.setInitialPosition(x, y);\n    \n    for (int i = 0; i < m; i++) {\n        cin >> x >> y;\n        solver.addTarget(x, y);\n    }\n    \n    solver.solve();\n    solver.output();\n    \n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\ndouble calculate_p(int r, int s) {\n    if (s == 0) return 0.0;\n    double ratio = (double)min(r, s) / max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble calculate_total_p(const vector<Company>& companies) {\n    double total = 0;\n    for (auto& c : companies) {\n        int s = (c.c - c.a) * (c.d - c.b);\n        total += calculate_p(c.r, s);\n    }\n    return total;\n}\n\nbool can_place(const vector<tuple<int, int, int, int>>& placed, int a, int b, int c, int d) {\n    for (auto& [pa, pb, pc, pd] : placed) {\n        if (!(c <= pa || a >= pc || d <= pb || b >= pd)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid place_rectangles(vector<Company>& companies, const vector<int>& order) {\n    vector<tuple<int, int, int, int>> placed;\n    \n    for (int idx : order) {\n        int x = companies[idx].x;\n        int y = companies[idx].y;\n        int r = companies[idx].r;\n        \n        // Find all dimension pairs (w, h) such that w * h = r\n        vector<pair<int, int>> dims;\n        for (int w = 1; w * w <= r; w++) {\n            if (r % w == 0) {\n                dims.push_back({w, r / w});\n                if (w * w != r) {\n                    dims.push_back({r / w, w});\n                }\n            }\n        }\n        \n        // Prefer more square-like rectangles (better packing)\n        sort(dims.begin(), dims.end(), [](auto& p1, auto& p2) {\n            return abs(p1.first - p1.second) < abs(p2.first - p2.second);\n        });\n        \n        bool placed_rect = false;\n        for (auto [w, h] : dims) {\n            // Try all positions that contain (x, y)\n            for (int offset_x = 0; offset_x < w && !placed_rect; offset_x++) {\n                for (int offset_y = 0; offset_y < h && !placed_rect; offset_y++) {\n                    int a = x - offset_x;\n                    int b = y - offset_y;\n                    int c = a + w;\n                    int d = b + h;\n                    \n                    if (a >= 0 && c <= 10000 && b >= 0 && d <= 10000) {\n                        if (can_place(placed, a, b, c, d)) {\n                            companies[idx].a = a;\n                            companies[idx].b = b;\n                            companies[idx].c = c;\n                            companies[idx].d = d;\n                            placed.emplace_back(a, b, c, d);\n                            placed_rect = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        companies[i].a = 0;\n        companies[i].b = 0;\n        companies[i].c = 0;\n        companies[i].d = 0;\n    }\n    \n    vector<Company> best_companies = companies;\n    double best_p = -1;\n    \n    // Strategy 1: Sort by r (largest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r > current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 2: Sort by position (x then y)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].x != current[j].x) return current[i].x < current[j].x;\n            return current[i].y < current[j].y;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 3: Sort by position (y then x)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].y != current[j].y) return current[i].y < current[j].y;\n            return current[i].x < current[j].x;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 4: Random order (multiple times)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 100; trial++) {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 5: Sort by r (smallest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r < current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 6: Sort by distance from center\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 7: Sort by r * distance from center (combined heuristic)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            if (current[i].r != current[j].r) return current[i].r > current[j].r;\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Output best solution\n    for (int i = 0; i < n; i++) {\n        cout << best_companies[i].a << \" \" << best_companies[i].b << \" \" \n             << best_companies[i].c << \" \" << best_companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\n// Global problem data\nint si, sj;\nint t[50][50];\nint p[50][50];\nint adj[50][50][4];\nint adj_count[50][50];\nchar move_char[4] = {'U', 'D', 'L', 'R'};\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\n// Global path state (no copying)\nint path_r[2505];\nint path_c[2505];\nchar path_moves[2505];\nbool visited_tile[2505];\nint path_len;\nlong long current_score;\n\n// Best path\nlong long best_score;\nstring best_moves;\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < 50 && c >= 0 && c < 50;\n}\n\nvoid precompute_adj() {\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            adj_count[i][j] = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (is_valid(ni, nj)) {\n                    adj[i][j][adj_count[i][j]++] = k;\n                }\n            }\n        }\n    }\n}\n\nvoid save_best() {\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_moves.clear();\n        best_moves.reserve(path_len - 1);\n        for (int i = 0; i < path_len - 1; ++i) {\n            best_moves += path_moves[i];\n        }\n    }\n}\n\n// Simple lookahead: count available neighbors\nint count_available_neighbors(int r, int c) {\n    int count = 0;\n    for (int k = 0; k < adj_count[r][c]; ++k) {\n        int dir = adj[r][c][k];\n        int nr = r + di[dir];\n        int nc = c + dj[dir];\n        int tile = t[nr][nc];\n        if (!visited_tile[tile]) {\n            count++;\n        }\n    }\n    return count;\n}\n\n// Calculate move score: value + connectivity bonus\nint move_score(int r, int c, int nr, int nc) {\n    int score = p[nr][nc];\n    int neighbors = count_available_neighbors(nr, nc);\n    // Bonus for moves that keep us connected\n    if (neighbors >= 2) score += 20;\n    else if (neighbors == 1) score += 10;\n    // Penalty for dead ends\n    if (neighbors == 0) score -= 100;\n    return score;\n}\n\nvoid run_single_path(mt19937& rng, uniform_real_distribution<double>& prob_dist) {\n    // Reset path\n    memset(visited_tile, 0, sizeof(visited_tile));\n    path_len = 0;\n    current_score = 0;\n\n    // Start from initial position\n    path_r[0] = si;\n    path_c[0] = sj;\n    visited_tile[t[si][sj]] = true;\n    path_len = 1;\n    current_score = p[si][sj];\n\n    save_best();\n\n    int stuck_steps = 0;\n    int backtrack_count = 0;\n\n    while (path_len > 0 && stuck_steps < 100) {\n        int r = path_r[path_len - 1];\n        int c = path_c[path_len - 1];\n        \n        // Find valid neighbors with scores\n        struct Candidate {\n            int dir;\n            int nr, nc;\n            int tile;\n            int score;\n        };\n        \n        vector<Candidate> candidates;\n        for (int k = 0; k < adj_count[r][c]; ++k) {\n            int dir = adj[r][c][k];\n            int nr = r + di[dir];\n            int nc = c + dj[dir];\n            int tile = t[nr][nc];\n            \n            if (!visited_tile[tile]) {\n                Candidate cand;\n                cand.dir = dir;\n                cand.nr = nr;\n                cand.nc = nc;\n                cand.tile = tile;\n                cand.score = move_score(r, c, nr, nc);\n                candidates.push_back(cand);\n            }\n        }\n\n        if (!candidates.empty()) {\n            // Sort by score\n            sort(candidates.begin(), candidates.end(), \n                [](const Candidate& a, const Candidate& b) {\n                    return a.score > b.score;\n                });\n\n            // Adaptive exploration rate\n            double exploration_rate = 0.2 + (stuck_steps * 0.01);\n            exploration_rate = min(0.6, exploration_rate);\n            \n            int chosen_idx = 0;\n            if (candidates.size() > 1 && prob_dist(rng) < exploration_rate) {\n                // Weighted random selection\n                double total_weight = 0;\n                vector<double> weights;\n                for (size_t i = 0; i < candidates.size(); ++i) {\n                    double weight = max(1, candidates[i].score + 50);\n                    total_weight += weight;\n                    weights.push_back(total_weight);\n                }\n                \n                double r_val = prob_dist(rng) * total_weight;\n                for (size_t i = 0; i < weights.size(); ++i) {\n                    if (r_val <= weights[i]) {\n                        chosen_idx = i;\n                        break;\n                    }\n                }\n            }\n\n            // Extend path\n            Candidate& chosen = candidates[chosen_idx];\n            path_r[path_len] = chosen.nr;\n            path_c[path_len] = chosen.nc;\n            path_moves[path_len - 1] = move_char[chosen.dir];\n            visited_tile[chosen.tile] = true;\n            path_len++;\n            current_score += p[chosen.nr][chosen.nc];\n            \n            stuck_steps = 0;\n            save_best();\n        } else {\n            // No valid moves - backtrack\n            stuck_steps++;\n            \n            if (path_len <= 1) break;\n            \n            // Backtrack one step\n            int last_r = path_r[path_len - 1];\n            int last_c = path_c[path_len - 1];\n            int last_tile = t[last_r][last_c];\n            \n            path_len--;\n            current_score -= p[last_r][last_c];\n            visited_tile[last_tile] = false;\n            \n            backtrack_count++;\n            \n            // If we've backtracked too much, restart\n            if (backtrack_count > 50) {\n                break;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> t[i][j];\n        }\n    }\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    precompute_adj();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1980);\n\n    best_score = -1;\n    best_moves.clear();\n\n    // Multiple restarts with different random seeds\n    int restart = 0;\n    while (chrono::steady_clock::now() < end_time && restart < 1000) {\n        restart++;\n        run_single_path(rng, prob_dist);\n    }\n\n    cout << best_moves << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <string>\n#include <tuple>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst double INIT_W = 5000.0;\nconst double K = 5.0; // Blending factor for row/col average\n\n// Edge weight estimates\n// h[i][j] stores stats for horizontal edge between (i, j) and (i, j+1)\n// v[i][j] stores stats for vertical edge between (i, j) and (i+1, j)\nstruct Stats {\n    double log_sum = 0.0;\n    int cnt = 0;\n};\n\nStats h_stats[N][N]; // 30x30, though j only goes to 28\nStats v_stats[N][N]; // 30x30, though i only goes to 28\nStats h_avg_stats[N]; // Row averages\nStats v_avg_stats[N]; // Col averages\n\n// Helper to get weight from stats\ndouble get_weight(const Stats& s) {\n    if (s.cnt == 0) return INIT_W;\n    return INIT_W * exp(s.log_sum / s.cnt);\n}\n\n// Helper to get effective weight blending edge and average\ndouble get_h_weight(int i, int j) {\n    double w_edge = get_weight(h_stats[i][j]);\n    double w_avg = get_weight(h_avg_stats[i]);\n    return (h_stats[i][j].cnt * w_edge + K * w_avg) / (h_stats[i][j].cnt + K);\n}\n\ndouble get_v_weight(int i, int j) {\n    double w_edge = get_weight(v_stats[i][j]);\n    double w_avg = get_weight(v_avg_stats[j]);\n    return (v_stats[i][j].cnt * w_edge + K * w_avg) / (v_stats[i][j].cnt + K);\n}\n\n// Update stats with ratio\nvoid update_h(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    h_stats[i][j].log_sum += log(ratio);\n    h_stats[i][j].cnt++;\n    h_avg_stats[i].log_sum += log(ratio);\n    h_avg_stats[i].cnt++;\n}\n\nvoid update_v(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    v_stats[i][j].log_sum += log(ratio);\n    v_stats[i][j].cnt++;\n    v_avg_stats[j].log_sum += log(ratio);\n    v_avg_stats[j].cnt++;\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int queries = 1000;\n    for (int k = 0; k < queries; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // Dijkstra\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n        vector<vector<char>> move_dir(N, vector<char>(N, 0));\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[si][sj] = 0.0;\n        pq.push({0.0, si, sj});\n\n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        char dirs[] = {'U', 'D', 'L', 'R'};\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n\n            if (current.dist > dist[r][c]) continue;\n            if (r == ti && c == tj) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    double w = 0.0;\n                    if (d == 0) { // U: from (r, c) to (r-1, c). Edge is v[r-1][c]\n                        w = get_v_weight(nr, nc);\n                    } else if (d == 1) { // D: from (r, c) to (r+1, c). Edge is v[r][c]\n                        w = get_v_weight(r, c);\n                    } else if (d == 2) { // L: from (r, c) to (r, c-1). Edge is h[r][c-1]\n                        w = get_h_weight(r, nc);\n                    } else if (d == 3) { // R: from (r, c) to (r, c+1). Edge is h[r][c]\n                        w = get_h_weight(r, c);\n                    }\n\n                    if (dist[r][c] + w < dist[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + w;\n                        parent[nr][nc] = {r, c};\n                        move_dir[nr][nc] = dirs[d];\n                        pq.push({dist[nr][nc], nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path\n        string path = \"\";\n        int curr_r = ti, curr_c = tj;\n        double path_est = 0.0;\n        vector<pair<int, int>> path_edges_h; // Store (i, j) for h edges\n        vector<pair<int, int>> path_edges_v; // Store (i, j) for v edges\n\n        while (curr_r != si || curr_c != sj) {\n            int pr = parent[curr_r][curr_c].first;\n            int pc = parent[curr_r][curr_c].second;\n            char d = move_dir[curr_r][curr_c];\n            path += d;\n\n            // Identify edge and update estimate\n            if (d == 'U') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r + 1.\n                // Edge is v[curr_r][curr_c]\n                path_edges_v.push_back({curr_r, curr_c});\n                path_est += get_v_weight(curr_r, curr_c);\n            } else if (d == 'D') { // From (pr, pc) to (curr_r, curr_c). pr = curr_r - 1.\n                // Edge is v[pr][pc] = v[curr_r-1][curr_c]\n                path_edges_v.push_back({pr, pc});\n                path_est += get_v_weight(pr, pc);\n            } else if (d == 'L') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c + 1.\n                // Edge is h[pr][curr_c]\n                path_edges_h.push_back({pr, curr_c});\n                path_est += get_h_weight(pr, curr_c);\n            } else if (d == 'R') { // From (pr, pc) to (curr_r, curr_c). pc = curr_c - 1.\n                // Edge is h[pr][pc]\n                path_edges_h.push_back({pr, pc});\n                path_est += get_h_weight(pr, pc);\n            }\n\n            curr_r = pr;\n            curr_c = pc;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << endl;\n\n        // Read feedback\n        int result;\n        cin >> result;\n\n        // Update weights\n        if (path_est > 0) {\n            double ratio = (double)result / path_est;\n            if (ratio <= 0) ratio = 1.0; \n\n            for (auto& e : path_edges_h) {\n                update_h(e.first, e.second, ratio);\n            }\n            for (auto& e : path_edges_v) {\n                update_v(e.first, e.second, ratio);\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n\nusing namespace std;\n\n// Problem Constants - N is fixed to 20\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\nconst int NUM_CHARS = 8; // A-H\n\n// State\nint matrix[N][N]; // 0-7 for A-H\nint string_counts[MAX_M]; // Number of valid placements for each string\nint total_matched = 0;\nint M;\n\n// Valid placements tracking\nbitset<10000> valid_placements[MAX_M];\n\n// cell_active[r*N+c] stores list of placements that cover this cell\nstruct PlacementInfo {\n    int s;\n    int id;\n};\nvector<PlacementInfo> cell_active[N * N];\n\n// potential_lists[char][cell] stores list of {s, id} that could match at this cell with this char\nvector<PlacementInfo> potential_lists[NUM_CHARS][N * N];\n\n// Helper to encode placement ID\ninline int encode_id(int r, int c, int dir, int offset) {\n    return dir * N * N * MAX_LEN + r * N * MAX_LEN + c * MAX_LEN + offset;\n}\n\n// Helper to decode placement ID\ninline void decode_id(int id, int &r, int &c, int &dir, int &offset) {\n    offset = id % MAX_LEN;\n    id /= MAX_LEN;\n    c = id % N;\n    id /= N;\n    r = id % N;\n    dir = id / N;\n}\n\n// Strings data\nvector<string> strings;\nvector<int> string_lens;\n\n// Random number generator\nmt19937 rng(1337);\nuniform_int_distribution<int> dist_char(0, NUM_CHARS - 1);\nuniform_int_distribution<int> dist_cell(0, N * N - 1);\n\n// Check if a placement is valid\nbool is_placement_valid(int s, int r, int c, int dir) {\n    int len = string_lens[s];\n    const string &str = strings[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) { // Horizontal\n            cr = r;\n            cc = (c + k) % N;\n        } else { // Vertical\n            cr = (r + k) % N;\n            cc = c;\n        }\n        if (matrix[cr][cc] != (str[k] - 'A')) return false;\n    }\n    return true;\n}\n\n// Add a valid placement\nvoid add_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (valid_placements[s].test(id)) return;\n\n    valid_placements[s].set(id);\n    string_counts[s]++;\n    if (string_counts[s] == 1) total_matched++;\n\n    int len = string_lens[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        cell_active[cr * N + cc].push_back({s, id});\n    }\n}\n\n// Remove a valid placement\nvoid remove_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (!valid_placements[s].test(id)) return;\n\n    valid_placements[s].reset(id);\n    string_counts[s]--;\n    if (string_counts[s] == 0) total_matched--;\n}\n\n// Initialize potential lists\nvoid init_potential_lists() {\n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        const string &str = strings[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal placements covering (r, c)\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_c = (c - k);\n                    if (start_c < 0) start_c += N;\n                    int id = encode_id(r, start_c, 0, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n                // Vertical placements covering (r, c)\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_r = (r - k);\n                    if (start_r < 0) start_r += N;\n                    int id = encode_id(start_r, c, 1, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n            }\n        }\n    }\n}\n\n// Initialize matrix and state\nvoid init_state() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            matrix[i][j] = dist_char(rng);\n        }\n    }\n\n    for (int s = 0; s < M; ++s) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (is_placement_valid(s, r, c, 0)) {\n                    add_placement(s, r, c, 0);\n                }\n                if (is_placement_valid(s, r, c, 1)) {\n                    add_placement(s, r, c, 1);\n                }\n            }\n        }\n    }\n}\n\n// Update cell (r, c) from old_char to new_char\nbool update_cell(int r, int c, int new_char) {\n    int old_char = matrix[r][c];\n    if (old_char == new_char) return true;\n\n    int cell_idx = r * N + c;\n\n    // Invalidate existing placements covering this cell\n    for (auto &p : cell_active[cell_idx]) {\n        if (valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            \n            int k = -1;\n            if (tdir == 0) {\n                k = (c - tc);\n                if (k < 0) k += N;\n            } else {\n                k = (r - tr);\n                if (k < 0) k += N;\n            }\n            \n            if (k >= string_lens[p.s]) continue;\n\n            int required_char = strings[p.s][k] - 'A';\n            if (required_char != new_char) {\n                remove_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    // Find new valid placements\n    for (auto &p : potential_lists[new_char][cell_idx]) {\n        if (!valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            if (is_placement_valid(p.s, tr, tc, tdir)) {\n                add_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    matrix[r][c] = new_char;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_input;\n    cin >> N_input >> M;\n    \n    strings.resize(M);\n    string_lens.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        string_lens[i] = strings[i].length();\n    }\n\n    init_potential_lists();\n    init_state();\n\n    // Simulated Annealing with more iterations\n    double temperature = 100.0;\n    double cooling_rate = 0.996;\n    int max_iter = 80000;\n    int iter = 0;\n\n    while (iter < max_iter && temperature > 0.01) {\n        int cell = dist_cell(rng);\n        int r = cell / N;\n        int c = cell % N;\n        \n        int old_char = matrix[r][c];\n        int new_char = dist_char(rng);\n        \n        int old_total_matched = total_matched;\n        \n        update_cell(r, c, new_char);\n        \n        double delta_score = total_matched - old_total_matched;\n        \n        double prob = 1.0;\n        if (delta_score < 0) {\n            prob = exp(delta_score / temperature);\n        }\n        \n        double rand_val = (double)dist_char(rng) / (double)NUM_CHARS;\n        if (rand_val >= prob) {\n            update_cell(r, c, old_char);\n        }\n\n        temperature *= cooling_rate;\n        iter++;\n    }\n\n    // Output exactly N lines with N characters each\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << (char)('A' + matrix[i][j]);\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> roads;\nint total_roads = 0;\n\n// Direction arrays: U, D, L, R\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\nconst char dc[] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && grid[i][j] != '#';\n}\n\nbool isVisible(int ci, int cj, int ti, int tj) {\n    if (ci == ti) {\n        for (int j = min(cj, tj); j <= max(cj, tj); j++) {\n            if (grid[ci][j] == '#') return false;\n        }\n        return true;\n    }\n    if (cj == tj) {\n        for (int i = min(ci, ti); i <= max(ci, ti); i++) {\n            if (grid[i][cj] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\nint getCost(int i, int j) {\n    return grid[i][j] - '0';\n}\n\n// BFS to find shortest path between two points\nvector<pair<int,int>> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {{si, sj}};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    queue<pair<int,int>> q;\n    \n    dist[si][sj] = 0;\n    q.push({si, sj});\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) {\n            vector<pair<int,int>> path;\n            int i = ti, j = tj;\n            while (!(i == si && j == sj)) {\n                path.push_back({i, j});\n                auto [pi, pj] = parent[i][j];\n                i = pi; j = pj;\n            }\n            path.push_back({si, sj});\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (isValid(ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                parent[ni][nj] = {ci, cj};\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Should not happen in valid inputs, but return direct path as fallback\n    return {{si, sj}, {ti, tj}};\n}\n\n// Count newly visible squares from a position\nint countNewVisible(int ci, int cj, const set<pair<int,int>>& covered) {\n    int count = 0;\n    for (const auto& [ri, rj] : roads) {\n        if (covered.find({ri, rj}) == covered.end()) {\n            if (isVisible(ci, cj, ri, rj)) {\n                count++;\n            }\n        }\n    }\n    return count;\n}\n\n// Get all newly visible squares from a position\nvoid addNewVisible(int ci, int cj, set<pair<int,int>>& covered) {\n    for (const auto& [ri, rj] : roads) {\n        if (covered.find({ri, rj}) == covered.end()) {\n            if (isVisible(ci, cj, ri, rj)) {\n                covered.insert({ri, rj});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n    }\n    \n    // Collect all road squares\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                roads.push_back({i, j});\n            }\n        }\n    }\n    total_roads = roads.size();\n    \n    // Track covered squares\n    set<pair<int,int>> covered;\n    \n    // Mark initially visible squares from start\n    addNewVisible(si, sj, covered);\n    \n    // Path storage\n    vector<pair<int,int>> path;\n    path.push_back({si, sj});\n    int ci = si, cj = sj;\n    \n    // Phase 1: Greedy coverage with limited iterations\n    int max_iter = 30000;\n    int iter = 0;\n    \n    while ((int)covered.size() < total_roads && iter < max_iter) {\n        iter++;\n        \n        int best_d = -1;\n        int max_new = -1;\n        \n        // Check all 4 directions\n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (!isValid(ni, nj)) continue;\n            \n            int new_covered = countNewVisible(ni, nj, covered);\n            \n            if (new_covered > max_new) {\n                max_new = new_covered;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1 || max_new == 0) {\n            // No new coverage from adjacent, try BFS to find best position\n            int best_target_i = -1, best_target_j = -1;\n            int best_new = -1;\n            \n            // Check all road squares as potential targets\n            for (const auto& [ti, tj] : roads) {\n                if (covered.find({ti, tj}) == covered.end()) {\n                    int new_vis = countNewVisible(ti, tj, covered);\n                    if (new_vis > best_new) {\n                        best_new = new_vis;\n                        best_target_i = ti;\n                        best_target_j = tj;\n                    }\n                }\n            }\n            \n            if (best_target_i != -1) {\n                auto subPath = bfsPath(ci, cj, best_target_i, best_target_j);\n                for (size_t k = 1; k < subPath.size(); k++) {\n                    path.push_back(subPath[k]);\n                    ci = subPath[k].first;\n                    cj = subPath[k].second;\n                    addNewVisible(ci, cj, covered);\n                }\n                continue;\n            } else {\n                // Random move\n                best_d = rand() % 4;\n                while (!isValid(ci + di[best_d], cj + dj[best_d])) {\n                    best_d = (best_d + 1) % 4;\n                }\n            }\n        }\n        \n        // Move in best direction\n        ci += di[best_d];\n        cj += dj[best_d];\n        path.push_back({ci, cj});\n        addNewVisible(ci, cj, covered);\n    }\n    \n    // Phase 2: Return to start using BFS\n    auto returnPath = bfsPath(ci, cj, si, sj);\n    for (size_t i = 1; i < returnPath.size(); i++) {\n        path.push_back(returnPath[i]);\n    }\n    \n    // Phase 3: Ensure path ends at start (critical fix)\n    if (path.back().first != si || path.back().second != sj) {\n        // Force return to start\n        auto forceReturn = bfsPath(path.back().first, path.back().second, si, sj);\n        for (size_t i = 1; i < forceReturn.size(); i++) {\n            path.push_back(forceReturn[i]);\n        }\n    }\n    \n    // Phase 4: Remove consecutive duplicates\n    vector<pair<int,int>> cleanedPath;\n    for (size_t i = 0; i < path.size(); i++) {\n        if (i == 0 || path[i] != path[i-1]) {\n            cleanedPath.push_back(path[i]);\n        }\n    }\n    \n    // Verify final position again\n    if (cleanedPath.back().first != si || cleanedPath.back().second != sj) {\n        cleanedPath.push_back({si, sj});\n    }\n    \n    // Phase 5: Convert path to movement string\n    string result;\n    for (size_t i = 1; i < cleanedPath.size(); i++) {\n        int di_val = cleanedPath[i].first - cleanedPath[i-1].first;\n        int dj_val = cleanedPath[i].second - cleanedPath[i-1].second;\n        \n        if (di_val == -1) result += 'U';\n        else if (di_val == 1) result += 'D';\n        else if (dj_val == -1) result += 'L';\n        else if (dj_val == 1) result += 'R';\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    vector<int> dependents;\n    int indegree;\n    int status; // 0: available, 1: assigned, 2: done\n    int start_day;\n};\n\nstruct Member {\n    int id;\n    vector<double> estimate;\n    vector<int> lower_bound;\n    int current_task; // -1 if free\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<vector<int>> adj;\nint day = 0;\n\ndouble calculate_cost(int task_idx, int member_idx) {\n    double cost = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            cost += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n        }\n    }\n    return max(1.0, cost);\n}\n\nvoid update_costs_for_member(int member_idx) {\n    // Re-calculate costs for all tasks for this member\n    // This is O(N * K)\n    // We don't store costs explicitly to save memory and update time, \n    // we calculate on demand or update a cache if needed.\n    // Given N=1000, M=20, calculating on demand is O(N*K) = 20000 ops.\n    // Doing this for all members is 400000 ops.\n    // Doing this every day is 2000 * 400000 = 8e8 ops. Too slow.\n    // We need to cache costs.\n    // But costs only change when skills change.\n    // Skills change when a task completes.\n    // So we update costs only when skills update.\n    // This is O(N*K) per completion. Total N completions.\n    // Total O(N^2 * K) = 1000^2 * 20 = 2e7 ops. Acceptable.\n    // So we maintain a cost matrix.\n}\n\nvector<vector<double>> cost_matrix;\n\nvoid update_cost_matrix(int member_idx) {\n    for (int i = 0; i < N; ++i) {\n        cost_matrix[i][member_idx] = calculate_cost(i, member_idx);\n    }\n}\n\nvoid update_skills(int member_idx, int task_idx, int t) {\n    // Update lower bounds and estimates\n    // t is the actual time taken\n    \n    // If t=1, we know w=0, so s >= d for all k\n    if (t == 1) {\n        for (int k = 0; k < K; ++k) {\n            if (tasks[task_idx].d[k] > members[member_idx].lower_bound[k]) {\n                members[member_idx].lower_bound[k] = tasks[task_idx].d[k];\n                // Update estimate to be at least lower bound\n                if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                    members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n                }\n            }\n        }\n    }\n    \n    // Update estimate based on observed time\n    // w_obs approx t (if t > 1)\n    // w_pred = sum(max(0, d - estimate))\n    \n    double w_pred = 0;\n    int count_non_zero = 0;\n    vector<int> contributing_skills;\n    \n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            w_pred += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n            count_non_zero++;\n            contributing_skills.push_back(k);\n        }\n    }\n    \n    double w_obs = 0;\n    if (t > 1) {\n        // w = t - r, r in [-3, 3]. So w in [t-3, t+3].\n        // Expectation is t.\n        // But if t=1, w=0.\n        w_obs = t; \n        // Conservative: if t is small, w might be 0.\n        // But if t=1, handled above.\n        // If t=2, w could be 0 (if r=2) or 5 (if r=-3).\n        // But if w=0, t=1 always. So if t>1, w>0.\n        // So w_obs = t is reasonable.\n    } else {\n        w_obs = 0;\n    }\n    \n    if (count_non_zero > 0) {\n        double diff = w_pred - w_obs;\n        // If diff > 0, we overestimated skills (predicted less work than observed). Decrease estimate.\n        // If diff < 0, we underestimated skills. Increase estimate.\n        // Adjustment per skill\n        double adjust = diff / count_non_zero;\n        \n        for (int k : contributing_skills) {\n            members[member_idx].estimate[k] -= adjust;\n            // Clamp to lower bound\n            if (members[member_idx].estimate[k] < members[member_idx].lower_bound[k]) {\n                members[member_idx].estimate[k] = members[member_idx].lower_bound[k];\n            }\n            // Also ensure non-negative\n            if (members[member_idx].estimate[k] < 0) {\n                members[member_idx].estimate[k] = 0;\n            }\n        }\n    }\n    \n    // Update cost matrix for this member\n    update_cost_matrix(member_idx);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n        }\n        tasks[i].indegree = 0;\n        tasks[i].status = 0;\n        tasks[i].start_day = 0;\n    }\n\n    adj.resize(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        tasks[v].indegree++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].estimate.assign(K, 0.0);\n        members[i].lower_bound.assign(K, 0);\n        members[i].current_task = -1;\n    }\n\n    cost_matrix.assign(N, vector<double>(M, 0.0));\n    // Initialize cost matrix\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cost_matrix[i][j] = calculate_cost(i, j);\n        }\n    }\n\n    // Count dependents for priority\n    vector<int> outdegree(N, 0);\n    for (int i = 0; i < N; ++i) {\n        outdegree[i] = adj[i].size();\n    }\n\n    while (true) {\n        day++;\n        if (day > 2000) break;\n\n        // Identify free members\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (members[j].current_task == -1) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Identify available tasks\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (tasks[i].status == 0 && tasks[i].indegree == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Assign tasks\n        // We want to match free_members to available_tasks to minimize cost\n        // Priority: cost first, then outdegree (tasks that unlock more)\n        \n        struct Assignment {\n            double cost;\n            int task_idx;\n            int member_idx;\n            int priority; // outdegree\n            bool operator<(const Assignment& other) const {\n                if (abs(cost - other.cost) > 1e-9) return cost < other.cost;\n                return priority > other.priority; // Higher outdegree first\n            }\n        };\n\n        vector<Assignment> candidates;\n        candidates.reserve(free_members.size() * available_tasks.size());\n\n        for (int j : free_members) {\n            for (int i : available_tasks) {\n                candidates.push_back({cost_matrix[i][j], i, j, outdegree[i]});\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n\n        vector<int> assigned_tasks(N, -1); // -1 if not assigned in this round\n        vector<int> assigned_members(M, -1); // -1 if not assigned in this round\n        vector<pair<int, int>> output_assignments;\n\n        for (const auto& cand : candidates) {\n            if (assigned_tasks[cand.task_idx] == -1 && assigned_members[cand.member_idx] == -1) {\n                assigned_tasks[cand.task_idx] = cand.task_idx;\n                assigned_members[cand.member_idx] = cand.member_idx;\n                output_assignments.push_back({cand.member_idx, cand.task_idx});\n                \n                // Update status\n                tasks[cand.task_idx].status = 1;\n                tasks[cand.task_idx].start_day = day;\n                members[cand.member_idx].current_task = cand.task_idx;\n            }\n        }\n\n        // Output\n        cout << output_assignments.size();\n        for (const auto& p : output_assignments) {\n            cout << \" \" << (p.first + 1) << \" \" << (p.second + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completions\n        int n_completions;\n        cin >> n_completions;\n        if (n_completions == -1) break;\n\n        vector<int> completed_members(n_completions);\n        for (int i = 0; i < n_completions; ++i) {\n            cin >> completed_members[i];\n            --completed_members[i]; // 0-indexed\n        }\n\n        for (int j : completed_members) {\n            int task_idx = members[j].current_task;\n            if (task_idx != -1) {\n                int t = day - tasks[task_idx].start_day + 1;\n                \n                // Update skills\n                update_skills(j, task_idx, t);\n                \n                // Update task status\n                tasks[task_idx].status = 2;\n                members[j].current_task = -1;\n                \n                // Update dependencies\n                for (int v : adj[task_idx]) {\n                    tasks[v].indegree--;\n                    if (tasks[v].indegree == 0) {\n                        // Task v becomes available\n                        // No need to do anything, it will be picked up next day\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n    int orderId; // -1 for office\n    int type; // 0 for pickup, 1 for dropoff, 2 for office\n};\n\nint dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    vector<Order> orders(1000);\n    for (int i = 0; i < 1000; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n    \n    int ox = 400, oy = 400;\n    \n    // Selected orders\n    vector<int> selected;\n    vector<bool> isSelected(1000, false);\n    vector<int> notSelected;\n    \n    // Initial selection: pick orders with short pickup-dropoff distance\n    vector<pair<int, int>> orderDist;\n    for (int i = 0; i < 1000; i++) {\n        int d = dist(orders[i].a, orders[i].b, orders[i].c, orders[i].d);\n        orderDist.push_back({d, i});\n    }\n    sort(orderDist.begin(), orderDist.end());\n    for (int i = 0; i < 50; i++) {\n        selected.push_back(orderDist[i].second);\n        isSelected[orderDist[i].second] = true;\n    }\n    for (int i = 50; i < 1000; i++) {\n        notSelected.push_back(orderDist[i].second);\n    }\n    \n    // Build initial route: office -> all pickups -> all dropoffs -> office\n    auto buildRoute = [&](const vector<int>& sel) {\n        vector<Point> route;\n        route.reserve(2 * sel.size() + 2);\n        route.push_back({ox, oy, -1, 2});\n        for (int idx : sel) {\n            route.push_back({orders[idx].a, orders[idx].b, idx, 0});\n        }\n        for (int idx : sel) {\n            route.push_back({orders[idx].c, orders[idx].d, idx, 1});\n        }\n        route.push_back({ox, oy, -1, 2});\n        return route;\n    };\n    \n    vector<Point> route = buildRoute(selected);\n    \n    // Calculate route cost\n    auto calcCost = [&]() {\n        int cost = 0;\n        for (size_t i = 0; i + 1 < route.size(); i++) {\n            cost += dist(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n        }\n        return cost;\n    };\n    \n    int currentCost = calcCost();\n    int bestCost = currentCost;\n    vector<Point> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // Simulated annealing parameters\n    random_device rd;\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> randDist(0.0, 1.0);\n    \n    double temperature = 3000.0;\n    double coolingRate = 0.99992;\n    \n    auto startTime = chrono::high_resolution_clock::now();\n    double timeLimit = 1.95;\n    \n    // Check if route is valid (pickup before dropoff for each order)\n    auto isValidRoute = [&](const vector<Point>& r, const vector<int>& sel) {\n        vector<int> pickupPos(1000, -1), dropoffPos(1000, -1);\n        for (size_t k = 0; k < r.size(); k++) {\n            if (r[k].orderId >= 0) {\n                if (r[k].type == 0) pickupPos[r[k].orderId] = k;\n                else dropoffPos[r[k].orderId] = k;\n            }\n        }\n        for (int idx : sel) {\n            if (pickupPos[idx] >= dropoffPos[idx]) return false;\n        }\n        return true;\n    };\n    \n    // Incremental cost calculation for 2-opt\n    auto calc2optDelta = [&](const vector<Point>& r, int i, int j) {\n        int delta = 0;\n        if (i > 0) {\n            delta -= dist(r[i-1].x, r[i-1].y, r[i].x, r[i].y);\n        }\n        if (j + 1 < (int)r.size()) {\n            delta -= dist(r[j].x, r[j].y, r[j+1].x, r[j+1].y);\n        }\n        if (i > 0) {\n            delta += dist(r[i-1].x, r[i-1].y, r[j].x, r[j].y);\n        }\n        if (j + 1 < (int)r.size()) {\n            delta += dist(r[i].x, r[i].y, r[j+1].x, r[j+1].y);\n        }\n        return delta;\n    };\n    \n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed >= timeLimit) break;\n        \n        // Try different moves\n        int moveType = randDist(gen) < 0.4 ? 0 : (randDist(gen) < 0.75 ? 1 : 2);\n        \n        if (moveType == 0) {\n            // Swap: exchange an order in/out of selected set\n            int inIdx = (int)(randDist(gen) * selected.size());\n            int outIdx = (int)(randDist(gen) * notSelected.size());\n            \n            int inOrder = selected[inIdx];\n            int outOrder = notSelected[outIdx];\n            \n            // Try swap\n            auto oldSelected = selected;\n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            selected[inIdx] = outOrder;\n            isSelected[inOrder] = false;\n            isSelected[outOrder] = true;\n            notSelected[outIdx] = inOrder;\n            \n            route = buildRoute(selected);\n            \n            if (!isValidRoute(route, selected)) {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n                isSelected[inOrder] = true;\n                isSelected[outOrder] = false;\n                notSelected[outIdx] = outOrder;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                selected = oldSelected;\n                route = oldRoute;\n                currentCost = oldCost;\n                isSelected[inOrder] = true;\n                isSelected[outOrder] = false;\n                notSelected[outIdx] = outOrder;\n            }\n        } else if (moveType == 1) {\n            // 2-opt: reverse a segment of the route (excluding first and last)\n            int i = 1 + (int)(randDist(gen) * (route.size() - 4));\n            int j = i + 1 + (int)(randDist(gen) * (route.size() - i - 3));\n            \n            // Ensure we don't include first or last point\n            i = max(1, i);\n            j = min((int)route.size() - 2, j);\n            \n            if (i >= j) continue;\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            reverse(route.begin() + i, route.begin() + j + 1);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        } else {\n            // Insert: move a non-office point to different position\n            int pos1 = 1 + (int)(randDist(gen) * (route.size() - 3));\n            int pos2 = 1 + (int)(randDist(gen) * (route.size() - 3));\n            \n            if (pos1 == pos2) continue;\n            \n            auto oldRoute = route;\n            auto oldCost = currentCost;\n            \n            Point p = route[pos1];\n            route.erase(route.begin() + pos1);\n            route.insert(route.begin() + pos2, p);\n            \n            if (!isValidRoute(route, selected)) {\n                route = oldRoute;\n                currentCost = oldCost;\n                continue;\n            }\n            \n            int newCost = calcCost();\n            int delta = newCost - currentCost;\n            \n            if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                currentCost = newCost;\n                if (currentCost < bestCost) {\n                    bestCost = currentCost;\n                    bestRoute = route;\n                    bestSelected = selected;\n                }\n            } else {\n                route = oldRoute;\n                currentCost = oldCost;\n            }\n        }\n        \n        temperature *= coolingRate;\n        \n        // Periodically output for visualization (optional)\n        if (elapsed > 0.5 && elapsed < 0.6) {\n            cout << bestSelected.size();\n            for (int idx : bestSelected) {\n                cout << \" \" << orders[idx].id;\n            }\n            cout << \"\\n\";\n            cout << bestRoute.size();\n            for (auto& p : bestRoute) {\n                cout << \" \" << p.x << \" \" << p.y;\n            }\n            cout << \"\\n\";\n        }\n    }\n    \n    // Output final best solution\n    cout << bestSelected.size();\n    for (int idx : bestSelected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (auto& p : bestRoute) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<pair<int, int>> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        long long dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = (int)round(sqrt(dx * dx + dy * dy));\n    }\n\n    DSU dsu(N);\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int root_u = dsu.find(u);\n        int root_v = dsu.find(v);\n\n        if (root_u == root_v) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Count remaining edges for each component\n        vector<int> edge_count(N, 0);\n        long long min_d_direct = 1e18;\n        long long min_d_any = 1e18;\n        int remaining_edges = 0;\n        bool has_direct = false;\n\n        for (int j = i + 1; j < M; ++j) {\n            int u_j = edges[j].u;\n            int v_j = edges[j].v;\n            int ru = dsu.find(u_j);\n            int rv = dsu.find(v_j);\n\n            if (ru != rv) {\n                remaining_edges++;\n                edge_count[ru]++;\n                edge_count[rv]++;\n                min_d_any = min(min_d_any, (long long)edges[j].d);\n                \n                if ((ru == root_u && rv == root_v) || (ru == root_v && rv == root_u)) {\n                    min_d_direct = min(min_d_direct, (long long)edges[j].d);\n                    has_direct = true;\n                }\n            }\n        }\n\n        bool accept = true;  // Default to accepting\n\n        // Only reject if BOTH components have MANY remaining edges\n        // AND the current edge is significantly more expensive\n        if (edge_count[root_u] >= 5 && edge_count[root_v] >= 5) {\n            if (has_direct) {\n                // Expected cost of future direct edge is 2 * min_d_direct\n                // Only reject if current edge is much more expensive\n                if (l_i > 4.0 * min_d_direct) {\n                    accept = false;\n                }\n            }\n            else if (min_d_any != 1e18) {\n                // For indirect path, be even more conservative\n                if (l_i > 5.0 * min_d_any) {\n                    accept = false;\n                }\n            }\n        }\n        // If either component has few remaining edges, always accept\n        else {\n            accept = true;\n        }\n\n        cout << (accept ? \"1\" : \"0\") << \"\\n\";\n        cout.flush();\n\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Pet {\n    int x, y, type;\n    bool operator<(const Pet& other) const {\n        return type < other.type;\n    }\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct State {\n    int turn;\n    vector<Pet> pets;\n    vector<Human> humans;\n    vector<vector<bool>> wall;\n    vector<vector<bool>> passable;\n};\n\nState state;\nmt19937 rng;\n\n// Directions: up, down, left, right\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char moveChars[] = {'U', 'D', 'L', 'R'};\nconst char wallChars[] = {'u', 'd', 'l', 'r'};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;\n}\n\nbool isPassable(int x, int y) {\n    if (!isValid(x, y)) return false;\n    return !state.wall[x][y];\n}\n\nbool hasPetAt(int x, int y) {\n    for (const auto& pet : state.pets) {\n        if (pet.x == x && pet.y == y) return true;\n    }\n    return false;\n}\n\nbool hasHumanAt(int x, int y) {\n    for (const auto& human : state.humans) {\n        if (human.x == x && human.y == y) return true;\n    }\n    return false;\n}\n\nbool hasPetAdjacent(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (hasPetAt(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canPlaceWall(int x, int y) {\n    if (!isValid(x, y)) return false;\n    if (state.wall[x][y]) return false;\n    if (hasPetAt(x, y)) return false;\n    if (hasHumanAt(x, y)) return false;\n    if (hasPetAdjacent(x, y)) return false;\n    return true;\n}\n\nint bfsReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint countPetsInReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (hasPetAt(x, y)) count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint getDistance(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint bfsDistance(int x1, int y1, int x2, int y2) {\n    if (!isValid(x1, y1) || !isValid(x2, y2)) return 1e9;\n    if (x1 == x2 && y1 == y2) return 0;\n    \n    vector<vector<int>> dist(GRID_SIZE, vector<int>(GRID_SIZE, 1e9));\n    queue<pair<int, int>> q;\n    \n    dist[x1][y1] = 0;\n    q.push({x1, y1});\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == x2 && y == y2) return dist[x][y];\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny] && dist[nx][ny] == 1e9) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return 1e9;\n}\n\ndouble evaluateAction(int humanIdx, char action) {\n    // Simulate the action and evaluate the result\n    State simState = state;\n    \n    // Apply human action\n    if (action == '.') {\n        // Stay\n    } else if (action >= 'A' && action <= 'Z') {\n        // Move\n        int d = 0;\n        if (action == 'U') d = 0;\n        else if (action == 'D') d = 1;\n        else if (action == 'L') d = 2;\n        else if (action == 'R') d = 3;\n        \n        int nx = simState.humans[humanIdx].x + dx[d];\n        int ny = simState.humans[humanIdx].y + dy[d];\n        \n        if (isValid(nx, ny) && !simState.wall[nx][ny]) {\n            simState.humans[humanIdx].x = nx;\n            simState.humans[humanIdx].y = ny;\n        }\n    } else if (action >= 'a' && action <= 'z') {\n        // Place wall\n        int d = 0;\n        if (action == 'u') d = 0;\n        else if (action == 'd') d = 1;\n        else if (action == 'l') d = 2;\n        else if (action == 'r') d = 3;\n        \n        int wx = simState.humans[humanIdx].x + dx[d];\n        int wy = simState.humans[humanIdx].y + dy[d];\n        \n        if (canPlaceWall(wx, wy)) {\n            simState.wall[wx][wy] = true;\n        }\n    }\n    \n    // Calculate score\n    int reachable = bfsReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    int petsInArea = countPetsInReachable(simState.humans[humanIdx].x, simState.humans[humanIdx].y);\n    \n    double score = (double)reachable / 900.0 * pow(0.5, petsInArea);\n    \n    // Penalty for being close to dogs\n    for (const auto& pet : simState.pets) {\n        if (pet.type == 4) { // Dog\n            int dist = bfsDistance(simState.humans[humanIdx].x, simState.humans[humanIdx].y, pet.x, pet.y);\n            if (dist < 10) {\n                score -= 0.1 * (10 - dist);\n            }\n        }\n    }\n    \n    return score;\n}\n\nchar decideAction(int humanIdx) {\n    vector<char> possibleActions = {'.', 'U', 'D', 'L', 'R', 'u', 'd', 'l', 'r'};\n    char bestAction = '.';\n    double bestScore = -1e9;\n    \n    for (char action : possibleActions) {\n        // Check if action is valid\n        if (action >= 'A' && action <= 'Z') {\n            int d = 0;\n            if (action == 'U') d = 0;\n            else if (action == 'D') d = 1;\n            else if (action == 'L') d = 2;\n            else if (action == 'R') d = 3;\n            \n            int nx = state.humans[humanIdx].x + dx[d];\n            int ny = state.humans[humanIdx].y + dy[d];\n            \n            if (!isValid(nx, ny) || state.wall[nx][ny]) continue;\n        } else if (action >= 'a' && action <= 'z') {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n        }\n        \n        double score = evaluateAction(humanIdx, action);\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestAction = action;\n        }\n    }\n    \n    return bestAction;\n}\n\nchar decideActionStrategic(int humanIdx) {\n    // Strategic decision based on turn phase\n    int turn = state.turn;\n    \n    // Early phase: Build walls around humans\n    if (turn < 50) {\n        // Prioritize wall placement\n        vector<char> wallActions = {'u', 'd', 'l', 'r'};\n        char bestWall = '.';\n        double bestScore = -1e9;\n        \n        for (char action : wallActions) {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[humanIdx].x + dx[d];\n            int wy = state.humans[humanIdx].y + dy[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateAction(humanIdx, action);\n            \n            // Bonus for blocking dogs\n            for (const auto& pet : state.pets) {\n                if (pet.type == 4) { // Dog\n                    int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                    if (dist < 15) {\n                        score += 0.5;\n                    }\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestWall = action;\n            }\n        }\n        \n        if (bestWall != '.') return bestWall;\n        \n        // If no good wall placement, stay\n        return '.';\n    }\n    \n    // Middle phase: Expand and defend\n    if (turn < 200) {\n        // Mix of wall placement and movement\n        char action = decideAction(humanIdx);\n        \n        // Bias towards walls if close to pets\n        for (const auto& pet : state.pets) {\n            if (pet.type == 4) { // Dog\n                int dist = bfsDistance(state.humans[humanIdx].x, state.humans[humanIdx].y, pet.x, pet.y);\n                if (dist < 10) {\n                    // Prefer wall placement\n                    vector<char> wallActions = {'u', 'd', 'l', 'r'};\n                    for (char wall : wallActions) {\n                        int d = 0;\n                        if (wall == 'u') d = 0;\n                        else if (wall == 'd') d = 1;\n                        else if (wall == 'l') d = 2;\n                        else if (wall == 'r') d = 3;\n                        \n                        int wx = state.humans[humanIdx].x + dx[d];\n                        int wy = state.humans[humanIdx].y + dy[d];\n                        \n                        if (canPlaceWall(wx, wy)) {\n                            return wall;\n                        }\n                    }\n                }\n            }\n        }\n        \n        return action;\n    }\n    \n    // Late phase: Fine-tune\n    return decideAction(humanIdx);\n}\n\nvoid updateState(const vector<string>& petMoves) {\n    // Update pet positions based on their moves\n    for (int i = 0; i < state.pets.size(); i++) {\n        const string& move = petMoves[i];\n        int x = state.pets[i].x;\n        int y = state.pets[i].y;\n        \n        for (char c : move) {\n            int d = 0;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            \n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                x = nx;\n                y = ny;\n            }\n        }\n        \n        state.pets[i].x = x;\n        state.pets[i].y = y;\n    }\n    \n    state.turn++;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    // Read input\n    int N;\n    cin >> N;\n    \n    state.pets.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> state.pets[i].x >> state.pets[i].y >> state.pets[i].type;\n        state.pets[i].x--; // Convert to 0-indexed\n        state.pets[i].y--;\n    }\n    \n    int M;\n    cin >> M;\n    \n    state.humans.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> state.humans[i].x >> state.humans[i].y;\n        state.humans[i].x--; // Convert to 0-indexed\n        state.humans[i].y--;\n    }\n    \n    // Initialize state\n    state.turn = 0;\n    state.wall.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    state.passable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Main game loop\n    for (int turn = 0; turn < MAX_TURNS; turn++) {\n        // Check time limit\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2800) {\n            // Output stay for all humans to avoid TLE\n            for (int i = 0; i < M; i++) {\n                cout << '.';\n            }\n            cout << endl;\n            flush(cout);\n            \n            // Read pet moves\n            vector<string> petMoves(M);\n            for (int i = 0; i < N; i++) {\n                cin >> petMoves[i];\n            }\n            continue;\n        }\n        \n        // Decide actions for each human\n        string actions = \"\";\n        for (int i = 0; i < M; i++) {\n            char action = decideActionStrategic(i);\n            actions += action;\n        }\n        \n        cout << actions << endl;\n        flush(cout);\n        \n        // Read pet moves\n        vector<string> petMoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petMoves[i];\n        }\n        \n        // Update state\n        updateState(petMoves);\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int INF = 1e9;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    if (!(cin >> si >> sj >> ti >> tj >> p)) return 0;\n\n    vector<string> h(MAX_N);\n    for (int i = 0; i < MAX_N; ++i) {\n        cin >> h[i];\n    }\n\n    vector<string> v(MAX_N - 1);\n    for (int i = 0; i < MAX_N - 1; ++i) {\n        cin >> v[i];\n    }\n\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    char moves[] = {'R', 'L', 'D', 'U'};\n\n    // BFS from target to compute distances\n    vector<vector<int>> dist(MAX_N, vector<int>(MAX_N, INF));\n    queue<pair<int, int>> q;\n\n    dist[ti][tj] = 0;\n    q.push({ti, tj});\n\n    auto can_move = [&](int i, int j, int k) -> bool {\n        int ni = i + di[k];\n        int nj = j + dj[k];\n        if (ni < 0 || ni >= MAX_N || nj < 0 || nj >= MAX_N) return false;\n        if (k == 0) { if (h[i][j] == '1') return false; }\n        else if (k == 1) { if (h[i][j-1] == '1') return false; }\n        else if (k == 2) { if (v[i][j] == '1') return false; }\n        else if (k == 3) { if (v[i-1][j] == '1') return false; }\n        return true;\n    };\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k];\n            int nj = j + dj[k];\n\n            if (can_move(i, j, k) && dist[ni][nj] == INF) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n\n    // Probability distribution\n    vector<vector<double>> prob(MAX_N, vector<double>(MAX_N, 0.0));\n    prob[si][sj] = 1.0;\n    double move_prob = 1.0 - p;\n\n    // Helper function to simulate one move\n    auto simulate_move = [&](const vector<vector<double>>& current_prob, int k) {\n        vector<vector<double>> next_prob(MAX_N, vector<double>(MAX_N, 0.0));\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (current_prob[i][j] < 1e-15) continue;\n                if (i == ti && j == tj) {\n                    next_prob[i][j] += current_prob[i][j];\n                    continue;\n                }\n                if (can_move(i, j, k)) {\n                    int ni = i + di[k];\n                    int nj = j + dj[k];\n                    next_prob[ni][nj] += current_prob[i][j] * move_prob;\n                    next_prob[i][j] += current_prob[i][j] * p;\n                } else {\n                    next_prob[i][j] += current_prob[i][j];\n                }\n            }\n        }\n        return next_prob;\n    };\n\n    // Helper function to calculate score\n    auto calculate_score = [&](const vector<vector<double>>& current_prob) {\n        double expected_dist = 0.0;\n        double reach_prob = 0.0;\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (i == ti && j == tj) {\n                    reach_prob += current_prob[i][j];\n                } else if (dist[i][j] != INF) {\n                    expected_dist += current_prob[i][j] * dist[i][j];\n                }\n            }\n        }\n        return make_pair(expected_dist, reach_prob);\n    };\n\n    string result = \"\";\n\n    for (int step = 0; step < 200; ++step) {\n        int best_move = 0;\n        double best_score = -1e18;\n        vector<vector<double>> best_next_prob;\n\n        // 2-step lookahead\n        for (int k1 = 0; k1 < 4; ++k1) {\n            auto prob_after_1 = simulate_move(prob, k1);\n            \n            // Calculate score after 1 step\n            auto score1 = calculate_score(prob_after_1);\n            double score1_val = -score1.first + 150.0 * score1.second;\n\n            // Look ahead one more step\n            double max_score2 = -1e18;\n            for (int k2 = 0; k2 < 4; ++k2) {\n                auto prob_after_2 = simulate_move(prob_after_1, k2);\n                auto score2 = calculate_score(prob_after_2);\n                double score2_val = -score2.first + 150.0 * score2.second;\n                max_score2 = max(max_score2, score2_val);\n            }\n\n            // Combined score: weighted average of 1-step and 2-step lookahead\n            double combined_score = 0.7 * score1_val + 0.3 * max_score2;\n\n            // Bonus for moves that reduce distance from high-probability cells\n            double distance_bonus = 0.0;\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (prob[i][j] > 0.1 && dist[i][j] != INF) {\n                        if (can_move(i, j, k1)) {\n                            int ni = i + di[k1];\n                            int nj = j + dj[k1];\n                            if (dist[ni][nj] < dist[i][j]) {\n                                distance_bonus += prob[i][j] * (dist[i][j] - dist[ni][nj]);\n                            }\n                        }\n                    }\n                }\n            }\n            combined_score += 5.0 * distance_bonus;\n\n            if (combined_score > best_score + 1e-9) {\n                best_score = combined_score;\n                best_move = k1;\n                best_next_prob = prob_after_1;\n            }\n        }\n\n        result += moves[best_move];\n        prob = best_next_prob;\n    }\n\n    cout << result << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to table from problem statement\nconst int to[8][4] = {\n    {1, 0, -1, -1}, // 0\n    {3, -1, -1, 0}, // 1\n    {-1, -1, 3, 2}, // 2\n    {-1, 2, 1, -1}, // 3\n    {1, 0, 3, 2},   // 4\n    {3, 2, 1, 0},   // 5\n    {2, -1, 0, -1}, // 6\n    {-1, 3, -1, 1}  // 7\n};\n\nint grid_type[30][30];\nint rot[30][30];\nint best_rot[30][30];\n\n// Visited generation array to avoid memset every time\nint vis_gen[30][30][4];\nint dist[30][30][4];\nint trace_id = 0;\n\nint get_effective_type(int base, int r) {\n    if (base < 4) return (base + r) % 4;\n    if (base == 4) return 4 + (r % 2);\n    if (base == 5) return 5 - (r % 2);\n    if (base == 6) return 6 + (r % 2);\n    if (base == 7) return 7 - (r % 2);\n    return 0;\n}\n\nlong long calc_score(vector<int>& lengths) {\n    lengths.clear();\n    lengths.reserve(900);\n\n    trace_id++;\n    if (trace_id == 0) {\n        memset(vis_gen, 0, sizeof(vis_gen));\n        trace_id = 1;\n    }\n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (vis_gen[i][j][d] == trace_id) continue;\n\n                int cur_i = i, cur_j = j, cur_d = d;\n                int steps = 0;\n                bool cycle_found = false;\n                int cycle_len = 0;\n\n                while (true) {\n                    if (vis_gen[cur_i][cur_j][cur_d] == trace_id) {\n                        cycle_len = steps - dist[cur_i][cur_j][cur_d];\n                        cycle_found = true;\n                        break;\n                    }\n                    if (vis_gen[cur_i][cur_j][cur_d] != 0) {\n                        break;\n                    }\n\n                    vis_gen[cur_i][cur_j][cur_d] = trace_id;\n                    dist[cur_i][cur_j][cur_d] = steps;\n\n                    int t = get_effective_type(grid_type[cur_i][cur_j], rot[cur_i][cur_j]);\n                    int next_d = to[t][cur_d];\n                    if (next_d == -1) break;\n\n                    int next_i = cur_i + di[next_d];\n                    int next_j = cur_j + dj[next_d];\n\n                    if (next_i < 0 || next_i >= 30 || next_j < 0 || next_j >= 30) break;\n\n                    cur_i = next_i;\n                    cur_j = next_j;\n                    cur_d = (next_d + 2) % 4;\n                    steps++;\n                }\n\n                if (cycle_found) {\n                    lengths.push_back(cycle_len);\n                }\n            }\n        }\n    }\n\n    if (lengths.size() < 2) return 0;\n    sort(lengths.rbegin(), lengths.rend());\n    return (long long)lengths[0] * lengths[1];\n}\n\nvoid copy_rot(int src[30][30], int dst[30][30]) {\n    for (int i = 0; i < 30; ++i)\n        for (int j = 0; j < 30; ++j)\n            dst[i][j] = src[i][j];\n}\n\nvoid randomize_rot(mt19937& rng, int rot[30][30]) {\n    uniform_int_distribution<int> dist_rot(0, 3);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            rot[i][j] = dist_rot(rng);\n        }\n    }\n}\n\nvoid solve() {\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            grid_type[i][j] = s[j] - '0';\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_rot(0, 3);\n    uniform_int_distribution<int> dist_idx(0, 29);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    long long best_score = 0;\n    vector<int> lengths;\n\n    auto start_time = chrono::steady_clock::now();\n    auto limit_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    // Multi-start with different strategies\n    int num_starts = 0;\n    int max_starts = 20;\n\n    while (chrono::steady_clock::now() < limit_time && num_starts < max_starts) {\n        num_starts++;\n\n        // Randomize rotations\n        randomize_rot(rng, rot);\n\n        // Initial score\n        long long current_score = calc_score(lengths);\n\n        // Local search with simulated annealing\n        double T = 5000.0;\n        int no_improve_count = 0;\n        int max_no_improve = 100000;\n\n        while (chrono::steady_clock::now() < limit_time && no_improve_count < max_no_improve) {\n            // Try single tile flip\n            int r = dist_idx(rng);\n            int c = dist_idx(rng);\n\n            int old_rot = rot[r][c];\n            rot[r][c] = (rot[r][c] + 1) % 4;\n\n            long long new_score = calc_score(lengths);\n\n            // Acceptance criteria\n            bool accept = false;\n            if (new_score > current_score) {\n                accept = true;\n                no_improve_count = 0;\n            } else if (new_score == current_score) {\n                accept = true;\n            } else {\n                double prob = exp((new_score - current_score) / T);\n                if (dist_prob(rng) < prob) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    copy_rot(rot, best_rot);\n                }\n            } else {\n                rot[r][c] = old_rot;\n                no_improve_count++;\n            }\n\n            // Occasionally try larger moves (flip 2-3 tiles)\n            if (no_improve_count % 100 == 0 && dist_prob(rng) < 0.1) {\n                int num_tiles = 2 + (dist_idx(rng) % 2);\n                vector<pair<int,int>> flipped;\n                \n                for (int k = 0; k < num_tiles; ++k) {\n                    int rr = dist_idx(rng);\n                    int cc = dist_idx(rng);\n                    flipped.push_back({rr, cc});\n                }\n                \n                // Apply flips\n                for (auto& p : flipped) {\n                    rot[p.first][p.second] = (rot[p.first][p.second] + 1) % 4;\n                }\n                \n                long long new_score2 = calc_score(lengths);\n                \n                if (new_score2 > current_score) {\n                    current_score = new_score2;\n                    no_improve_count = 0;\n                    if (new_score2 > best_score) {\n                        best_score = new_score2;\n                        copy_rot(rot, best_rot);\n                    }\n                } else {\n                    // Revert\n                    for (auto& p : flipped) {\n                        rot[p.first][p.second] = (rot[p.first][p.second] + 3) % 4;\n                    }\n                }\n            }\n\n            T *= 0.9995;\n            if (T < 1.0) T = 1.0;\n        }\n    }\n\n    // Final output\n    string out = \"\";\n    out.reserve(900);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            out += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << out << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n\nusing namespace std;\n\nint N, T;\nint board[12][12];\nstring moves;\nint empty_r, empty_c;\nbool solved[12][12];\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dchar[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return 0;\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nvoid apply_move(char move) {\n    int dir = -1;\n    if (move == 'U') dir = 0;\n    else if (move == 'D') dir = 1;\n    else if (move == 'L') dir = 2;\n    else if (move == 'R') dir = 3;\n    \n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    \n    if (!is_valid(nr, nc)) return;\n    \n    int tile = board[nr][nc];\n    board[empty_r][empty_c] = tile;\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    moves += move;\n}\n\n// Simple BFS for empty square movement\nstring bfs_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return \"\";\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\n    \n    char parent_move[12][12];\n    bool visited[12][12];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        visited[i][j] = false;\n        parent_move[i][j] = 0;\n    }\n    \n    visited[empty_r][empty_c] = true;\n    \n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            string path = \"\";\n            int cr = tr, cc = tc;\n            while(cr != empty_r || cc != empty_c) {\n                char m = parent_move[cr][cc];\n                path += m;\n                int dir = -1;\n                if (m == 'U') dir = 0;\n                else if (m == 'D') dir = 1;\n                else if (m == 'L') dir = 2;\n                else if (m == 'R') dir = 3;\n                int rev_dr = -dr[dir];\n                int rev_dc = -dc[dir];\n                cr += rev_dr;\n                cc += rev_dc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (is_valid(nr, nc) && !visited[nr][nc] && !solved[nr][nc]) {\n                visited[nr][nc] = true;\n                parent_move[nr][nc] = dchar[i];\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\";\n}\n\n// Find position of a tile value\npair<int, int> find_tile(int val) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == val) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Place a tile at target position\nvoid place_tile_at(int tr, int tc, int target_val) {\n    // Skip if already correct\n    if (board[tr][tc] == target_val) {\n        solved[tr][tc] = true;\n        return;\n    }\n    \n    // Find where the target tile is\n    auto pos = find_tile(target_val);\n    int fr = pos.first, fc = pos.second;\n    \n    if (fr == -1) return; // Should not happen\n    \n    // Move tile from (fr, fc) to (tr, tc)\n    while (fr != tr || fc != tc) {\n        // Find best direction to move tile towards target\n        int best_dir = -1;\n        int best_dist = 1e9;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = fr + dr[i];\n            int nc = fc + dc[i];\n            if (is_valid(nr, nc) && !solved[nr][nc]) {\n                int dist = abs(nr - tr) + abs(nc - tc);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_dir = i;\n                }\n            }\n        }\n        \n        if (best_dir == -1) {\n            // Try any unsolved neighbor\n            for (int i = 0; i < 4; ++i) {\n                int nr = fr + dr[i];\n                int nc = fc + dc[i];\n                if (is_valid(nr, nc) && !solved[nr][nc]) {\n                    best_dir = i;\n                    break;\n                }\n            }\n        }\n        \n        if (best_dir == -1) break;\n        \n        int nr = fr + dr[best_dir];\n        int nc = fc + dc[best_dir];\n        \n        // Move empty square to (nr, nc)\n        string path = bfs_to(nr, nc);\n        for (char m : path) apply_move(m);\n        \n        // Move tile to (nr, nc)\n        int reverse_dir = (best_dir + 2) % 4;\n        apply_move(dchar[reverse_dir]);\n        \n        // Update tile position\n        fr = nr;\n        fc = nc;\n        \n        // Check move limit\n        if (moves.size() > T) {\n            cout << moves << endl;\n            exit(0);\n        }\n    }\n    solved[tr][tc] = true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T)) return 0;\n    \n    vector<string> input_board(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> input_board[i];\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(input_board[i][j]);\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    // Initialize solved array\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            solved[i][j] = false;\n    \n    // Strategy: Place tiles in order, but skip the last cell (empty square)\n    // We'll create a simple pattern that should work\n    \n    // Count available tiles\n    int counts[16] = {0};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] != 0) {\n                counts[board[i][j]]++;\n            }\n        }\n    }\n    \n    // Create target configuration (simple row-by-row placement)\n    int target[12][12];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            target[i][j] = -1;\n        }\n    }\n    \n    // Fill target with available tiles (skip last cell for empty square)\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) {\n                target[i][j] = 0; // Empty square\n            } else {\n                // Find next available tile\n                for (int t = 1; t <= 15; ++t) {\n                    if (counts[t] > 0) {\n                        target[i][j] = t;\n                        counts[t]--;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Solve puzzle\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) continue; // Skip empty square\n            \n            int target_val = target[i][j];\n            if (target_val == -1) continue;\n            \n            place_tile_at(i, j, target_val);\n            \n            if (moves.size() > T) {\n                cout << moves << endl;\n                return 0;\n            }\n        }\n    }\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\n// Cross product to determine which side of line a point is on\nint point_side(const Line& line, const Point& p) {\n    long long dx = line.qx - line.px;\n    long long dy = line.qy - line.py;\n    long long px = p.x - line.px;\n    long long py = p.y - line.py;\n    long long cp = dx * py - dy * px;\n    if (cp > 0) return 1;\n    if (cp < 0) return -1;\n    return 0;\n}\n\n// Calculate score for current cut configuration\nint calculate_score(const vector<Point>& strawberries, \n                    const vector<Line>& cuts, \n                    const vector<int>& a) {\n    int n = strawberries.size();\n    int k = cuts.size();\n    \n    // For each strawberry, determine its region (bitmask of which side of each cut)\n    vector<int> region(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < k; j++) {\n            int side = point_side(cuts[j], strawberries[i]);\n            if (side == 1) {\n                region[i] |= (1 << j);\n            }\n            // If side == 0, strawberry is on the line (doesn't count)\n        }\n    }\n    \n    // Count strawberries in each region\n    map<int, int> region_count;\n    for (int i = 0; i < n; i++) {\n        region_count[region[i]]++;\n    }\n    \n    // Calculate score\n    int total_attendees = 0;\n    for (int d = 1; d <= 10; d++) {\n        total_attendees += a[d];\n    }\n    \n    if (total_attendees == 0) return 0;\n    \n    // Count pieces with each number of strawberries\n    vector<int> b(11, 0);\n    for (const auto& [region_id, count] : region_count) {\n        if (count >= 1 && count <= 10) {\n            b[count]++;\n        }\n    }\n    \n    int distributed = 0;\n    for (int d = 1; d <= 10; d++) {\n        distributed += min(a[d], b[d]);\n    }\n    \n    return round(1e6 * distributed / total_attendees);\n}\n\n// Generate a random line\nLine generate_random_line(mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    line.px = dist(gen);\n    line.py = dist(gen);\n    line.qx = dist(gen);\n    line.qy = dist(gen);\n    \n    // Ensure points are different\n    while (line.px == line.qx && line.py == line.qy) {\n        line.qx = dist(gen);\n        line.qy = dist(gen);\n    }\n    \n    return line;\n}\n\n// Generate a line that passes between two strawberries\nLine generate_separating_line(const Point& p1, const Point& p2, \n                              mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    \n    // Create a line perpendicular to the segment p1-p2\n    long long dx = p2.x - p1.x;\n    long long dy = p2.y - p1.y;\n    \n    // Midpoint\n    long long mx = (p1.x + p2.x) / 2;\n    long long my = (p1.y + p2.y) / 2;\n    \n    // Perpendicular direction\n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    // Add some randomness\n    long long offset_x = dist(gen) % 100000 - 50000;\n    long long offset_y = dist(gen) % 100000 - 50000;\n    \n    line.px = mx + pdx + offset_x;\n    line.py = my + pdy + offset_y;\n    line.qx = mx - pdx + offset_x;\n    line.qy = my - pdy + offset_y;\n    \n    return line;\n}\n\n// Generate a line that separates a specific group of strawberries\nLine generate_group_separating_line(const vector<Point>& strawberries,\n                                    const vector<int>& group_indices,\n                                    mt19937& gen, uniform_int_distribution<long long>& dist) {\n    if (group_indices.empty()) {\n        return generate_random_line(gen, dist);\n    }\n    \n    // Find centroid of the group\n    long long cx = 0, cy = 0;\n    for (int idx : group_indices) {\n        cx += strawberries[idx].x;\n        cy += strawberries[idx].y;\n    }\n    cx /= group_indices.size();\n    cy /= group_indices.size();\n    \n    // Find a point outside the group\n    int outside_idx = -1;\n    for (int i = 0; i < (int)strawberries.size(); i++) {\n        bool in_group = false;\n        for (int gidx : group_indices) {\n            if (gidx == i) {\n                in_group = true;\n                break;\n            }\n        }\n        if (!in_group) {\n            outside_idx = i;\n            break;\n        }\n    }\n    \n    if (outside_idx == -1) {\n        return generate_random_line(gen, dist);\n    }\n    \n    // Create line perpendicular to centroid-outside direction\n    long long dx = strawberries[outside_idx].x - cx;\n    long long dy = strawberries[outside_idx].y - cy;\n    \n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    long long offset_x = dist(gen) % 50000 - 25000;\n    long long offset_y = dist(gen) % 50000 - 25000;\n    \n    Line line;\n    line.px = cx + pdx + offset_x;\n    line.py = cy + pdy + offset_y;\n    line.qx = cx - pdx + offset_x;\n    line.qy = cy - pdy + offset_y;\n    \n    return line;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(11);\n    for (int i = 1; i <= 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<long long> dist(-1000000000, 1000000000);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = start_time + chrono::milliseconds(2800);\n    \n    vector<Line> best_cuts;\n    int best_score = 0;\n    \n    // Multiple restart strategy\n    int num_restarts = 20;\n    int restarts_done = 0;\n    \n    while (restarts_done < num_restarts && chrono::steady_clock::now() < time_limit) {\n        restarts_done++;\n        vector<Line> cuts;\n        \n        // Phase 1: Generate initial random cuts\n        for (int i = 0; i < min(K, 20); i++) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            cuts.push_back(generate_random_line(gen, dist));\n        }\n        \n        // Phase 2: Iterative improvement\n        int no_improve_count = 0;\n        int max_no_improve = 500;\n        \n        while (chrono::steady_clock::now() < time_limit && no_improve_count < max_no_improve) {\n            no_improve_count++;\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            Line best_new_cut;\n            int best_new_score = old_score;\n            int best_idx = -1;\n            \n            // Try adding a cut\n            if (cuts.size() < (size_t)K) {\n                for (int trial = 0; trial < 50; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    Line new_cut;\n                    if (gen() % 3 == 0 && N >= 2) {\n                        // Strategic cut between two random strawberries\n                        int i1 = gen() % N;\n                        int i2 = gen() % N;\n                        while (i2 == i1) i2 = gen() % N;\n                        new_cut = generate_separating_line(strawberries[i1], strawberries[i2], gen, dist);\n                    } else {\n                        new_cut = generate_random_line(gen, dist);\n                    }\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts.push_back(new_cut);\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = -1; // -1 means add\n                    }\n                }\n            }\n            \n            // Try replacing a cut\n            if (cuts.size() >= 1) {\n                for (int trial = 0; trial < 30; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    int idx = gen() % cuts.size();\n                    Line new_cut = generate_random_line(gen, dist);\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts[idx] = new_cut;\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = idx;\n                    }\n                }\n            }\n            \n            // Apply best improvement\n            if (best_new_score > old_score) {\n                no_improve_count = 0;\n                if (best_idx == -1) {\n                    cuts.push_back(best_new_cut);\n                } else {\n                    cuts[best_idx] = best_new_cut;\n                }\n            }\n        }\n        \n        // Try removing unnecessary cuts\n        for (int i = (int)cuts.size() - 1; i >= 0; i--) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.erase(test_cuts.begin() + i);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n        \n        // Update best solution\n        int current_score = calculate_score(strawberries, cuts, a);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_cuts = cuts;\n        }\n    }\n    \n    // Output\n    cout << best_cuts.size() << endl;\n    for (const auto& cut : best_cuts) {\n        cout << cut.px << \" \" << cut.py << \" \" << cut.qx << \" \" << cut.qy << endl;\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Point structure\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\n// Rectangle edge representation\nstruct Edge {\n    int x1, y1, x2, y2;\n    bool operator<(const Edge& other) const {\n        if (x1 != other.x1) return x1 < other.x1;\n        if (y1 != other.y1) return y1 < other.y1;\n        if (x2 != other.x2) return x2 < other.x2;\n        return y2 < other.y2;\n    }\n};\n\n// Operation record\nstruct Operation {\n    Point p1, p2, p3, p4;\n    double score;\n};\n\nclass RectJoinSolver {\nprivate:\n    int N, M;\n    set<Point> dots;\n    set<Edge> drawnEdges;\n    vector<Operation> operations;\n    int cx, cy;\n    \n    // Calculate weight of a point\n    double weight(int x, int y) const {\n        return (double)(x - cx) * (x - cx) + (double)(y - cy) * (y - cy) + 1.0;\n    }\n    \n    // Check if point is within grid\n    bool inGrid(int x, int y) const {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    }\n    \n    // Check if point has a dot\n    bool hasDot(int x, int y) const {\n        return dots.count({x, y}) > 0;\n    }\n    \n    // Normalize edge for consistent representation\n    Edge normalizeEdge(int x1, int y1, int x2, int y2) const {\n        if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n            return {x2, y2, x1, y1};\n        }\n        return {x1, y1, x2, y2};\n    }\n    \n    // Check if edge already exists\n    bool edgeExists(int x1, int y1, int x2, int y2) const {\n        return drawnEdges.count(normalizeEdge(x1, y1, x2, y2)) > 0;\n    }\n    \n    // Add edge to drawn edges\n    void addEdge(int x1, int y1, int x2, int y2) {\n        drawnEdges.insert(normalizeEdge(x1, y1, x2, y2));\n    }\n    \n    // Check if two edges share a segment of positive length\n    bool edgesOverlap(const Edge& e1, const Edge& e2) const {\n        // Check if edges are on the same line\n        if (e1.x1 == e1.x2 && e2.x1 == e2.x2) {\n            // Both vertical\n            if (e1.x1 != e2.x1) return false;\n            int yMin1 = min(e1.y1, e1.y2), yMax1 = max(e1.y1, e1.y2);\n            int yMin2 = min(e2.y1, e2.y2), yMax2 = max(e2.y1, e2.y2);\n            int overlapMin = max(yMin1, yMin2), overlapMax = min(yMax1, yMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        if (e1.y1 == e1.y2 && e2.y1 == e2.y2) {\n            // Both horizontal\n            if (e1.y1 != e2.y1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            int overlapMin = max(xMin1, xMin2), overlapMax = min(xMax1, xMax2);\n            return overlapMax - overlapMin > 0;\n        }\n        return false;\n    }\n    \n    // Check if any edge of rectangle overlaps with existing edges\n    bool rectangleOverlaps(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const {\n        Edge edges[4] = {\n            normalizeEdge(x1, y1, x2, y2),\n            normalizeEdge(x2, y2, x3, y3),\n            normalizeEdge(x3, y3, x4, y4),\n            normalizeEdge(x4, y4, x1, y1)\n        };\n        \n        for (const auto& e : edges) {\n            for (const auto& existing : drawnEdges) {\n                if (edgesOverlap(e, existing)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n    \n    // Check if there are dots on rectangle perimeter (excluding the 3 existing dots)\n    bool hasDotsOnPerimeter(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,\n                           const Point& p2, const Point& p3, const Point& p4) const {\n        auto checkEdge = [&](int x1, int y1, int x2, int y2) {\n            int dx = x2 - x1, dy = y2 - y1;\n            int steps = max(abs(dx), abs(dy));\n            for (int i = 1; i < steps; i++) {\n                int x = x1 + dx * i / steps;\n                int y = y1 + dy * i / steps;\n                // Skip the three existing dots\n                if ((x == p2.x && y == p2.y) || (x == p3.x && y == p3.y) || \n                    (x == p4.x && y == p4.y)) continue;\n                if (hasDot(x, y)) return true;\n            }\n            return false;\n        };\n        \n        return checkEdge(x1, y1, x2, y2) ||\n               checkEdge(x2, y2, x3, y3) ||\n               checkEdge(x3, y3, x4, y4) ||\n               checkEdge(x4, y4, x1, y1);\n    }\n    \n    // Find 4th point for rectangle given 3 points\n    // Returns true if valid rectangle can be formed\n    bool findRectanglePoint(const Point& p2, const Point& p3, const Point& p4, Point& p1) const {\n        // Try all 6 permutations to find which 3 points form 3 corners of rectangle\n        // and calculate the 4th point\n        \n        // For axis-aligned rectangle: opposite corners have same x or same y\n        // For 45-degree rectangle: diagonal properties differ\n        \n        // Case 1: p2, p3, p4 are consecutive corners\n        // p1 should complete the rectangle\n        \n        // Check if p2-p3 and p3-p4 are perpendicular\n        int dx1 = p3.x - p2.x, dy1 = p3.y - p2.y;\n        int dx2 = p4.x - p3.x, dy2 = p4.y - p3.y;\n        \n        // For axis-aligned: one of dx1,dy1 is 0, one of dx2,dy2 is 0\n        // For 45-degree: |dx1| == |dy1| and |dx2| == |dy2|\n        \n        // Calculate potential p1 for different configurations\n        // Rectangle: p1, p2, p3, p4 in order\n        \n        // Configuration 1: p2, p3, p4 are corners, find p1\n        // p1 = p2 + p4 - p3 (vector addition)\n        p1.x = p2.x + p4.x - p3.x;\n        p1.y = p2.y + p4.y - p3.y;\n        \n        if (!inGrid(p1.x, p1.y)) return false;\n        \n        // Verify rectangle properties\n        int dx21 = p1.x - p2.x, dy21 = p1.y - p2.y;\n        int dx34 = p4.x - p3.x, dy34 = p4.y - p3.y;\n        int dx14 = p4.x - p1.x, dy14 = p4.y - p1.y;\n        int dx23 = p3.x - p2.x, dy23 = p3.y - p2.y;\n        \n        // Check if opposite sides are equal and parallel\n        bool axisAligned = (dx21 == dx34 && dy21 == dy34) && \n                          (dx14 == dx23 && dy14 == dy23);\n        \n        bool diagonal45 = (abs(dx21) == abs(dy21) && abs(dx14) == abs(dy14)) &&\n                         (abs(dx34) == abs(dy34) && abs(dx23) == abs(dy23));\n        \n        if (!axisAligned && !diagonal45) return false;\n        \n        return true;\n    }\n    \n    // Find all valid moves\n    vector<Operation> findValidMoves() {\n        vector<Operation> validMoves;\n        vector<Point> dotList(dots.begin(), dots.end());\n        int nDots = dotList.size();\n        \n        // Try all combinations of 3 dots\n        for (int i = 0; i < nDots; i++) {\n            for (int j = i + 1; j < nDots; j++) {\n                for (int k = j + 1; k < nDots; k++) {\n                    Point p2 = dotList[i];\n                    Point p3 = dotList[j];\n                    Point p4 = dotList[k];\n                    \n                    // Try to find p1 that completes rectangle\n                    Point p1;\n                    if (!findRectanglePoint(p2, p3, p4, p1)) continue;\n                    \n                    // p1 must not have a dot yet\n                    if (hasDot(p1.x, p1.y)) continue;\n                    \n                    // Check rectangle overlaps\n                    if (rectangleOverlaps(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y)) continue;\n                    \n                    // Check dots on perimeter\n                    if (hasDotsOnPerimeter(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y,\n                                          p2, p3, p4)) continue;\n                    \n                    Operation op;\n                    op.p1 = p1;\n                    op.p2 = p2;\n                    op.p3 = p3;\n                    op.p4 = p4;\n                    op.score = weight(p1.x, p1.y);\n                    \n                    validMoves.push_back(op);\n                }\n            }\n        }\n        \n        return validMoves;\n    }\n    \n    // Execute a move\n    void executeMove(const Operation& op) {\n        dots.insert(op.p1);\n        addEdge(op.p1.x, op.p1.y, op.p2.x, op.p2.y);\n        addEdge(op.p2.x, op.p2.y, op.p3.x, op.p3.y);\n        addEdge(op.p3.x, op.p3.y, op.p4.x, op.p4.y);\n        addEdge(op.p4.x, op.p4.y, op.p1.x, op.p1.y);\n        operations.push_back(op);\n    }\n    \npublic:\n    RectJoinSolver(int n, int m, const vector<pair<int,int>>& initial) {\n        N = n; M = m;\n        cx = (N - 1) / 2;\n        cy = (N - 1) / 2;\n        \n        for (const auto& p : initial) {\n            dots.insert({p.first, p.second});\n        }\n    }\n    \n    void solve() {\n        auto startTime = chrono::steady_clock::now();\n        auto timeLimit = chrono::seconds(4); // Leave margin for 5 sec limit\n        \n        int maxIterations = 10000;\n        int iteration = 0;\n        \n        while (iteration < maxIterations) {\n            auto currentTime = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::seconds>(currentTime - startTime).count() >= 4) {\n                break;\n            }\n            \n            vector<Operation> moves = findValidMoves();\n            \n            if (moves.empty()) break;\n            \n            // Sort by weight (higher weight first)\n            sort(moves.begin(), moves.end(), [](const Operation& a, const Operation& b) {\n                return a.score > b.score;\n            });\n            \n            // Execute best move\n            executeMove(moves[0]);\n            iteration++;\n        }\n    }\n    \n    void output() const {\n        cout << operations.size() << endl;\n        for (const auto& op : operations) {\n            cout << op.p1.x << \" \" << op.p1.y << \" \"\n                 << op.p2.x << \" \" << op.p2.y << \" \"\n                 << op.p3.x << \" \" << op.p3.y << \" \"\n                 << op.p4.x << \" \" << op.p4.y << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    \n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initial[i].first >> initial[i].second;\n    }\n    \n    RectJoinSolver solver(N, M, initial);\n    solver.solve();\n    solver.output();\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Board representation: 10x10 grid, 0=empty, 1-3=flavors\nstruct Board {\n    int grid[10][10];\n    \n    Board() {\n        for(int i = 0; i < 10; i++)\n            for(int j = 0; j < 10; j++)\n                grid[i][j] = 0;\n    }\n};\n\n// Count connected components and calculate score\nlong long calculateScore(const Board& b) {\n    int visited[10][10];\n    for(int i = 0; i < 10; i++)\n        for(int j = 0; j < 10; j++)\n            visited[i][j] = 0;\n    \n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n    \n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] != 0 && !visited[i][j]) {\n                // BFS for connected component\n                int flavor = b.grid[i][j];\n                int size = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = 1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    size++;\n                    \n                    for(int d = 0; d < 4; d++) {\n                        int nr = r + dr[d];\n                        int nc = c + dc[d];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10) {\n                            if(!visited[nr][nc] && b.grid[nr][nc] == flavor) {\n                                visited[nr][nc] = 1;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Tilt board in given direction\nvoid tilt(Board& b, char dir) {\n    Board newb = b;\n    \n    if(dir == 'F') { // Forward (up)\n        for(int j = 0; j < 10; j++) {\n            int write = 0;\n            for(int i = 0; i < 10; i++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int i = write; i < 10; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'B') { // Backward (down)\n        for(int j = 0; j < 10; j++) {\n            int write = 9;\n            for(int i = 9; i >= 0; i--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int i = 0; i < write; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'L') { // Left\n        for(int i = 0; i < 10; i++) {\n            int write = 0;\n            for(int j = 0; j < 10; j++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int j = write; j < 10; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'R') { // Right\n        for(int i = 0; i < 10; i++) {\n            int write = 9;\n            for(int j = 9; j >= 0; j--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int j = 0; j < write; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    }\n    \n    b = newb;\n}\n\n// Count candies of each flavor\nvoid countFlavors(const Board& b, int& f1, int& f2, int& f3) {\n    f1 = f2 = f3 = 0;\n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] == 1) f1++;\n            else if(b.grid[i][j] == 2) f2++;\n            else if(b.grid[i][j] == 3) f3++;\n        }\n    }\n}\n\n// Calculate normalized score\ndouble getNormalizedScore(const Board& b) {\n    int f1, f2, f3;\n    countFlavors(b, f1, f2, f3);\n    long long numerator = calculateScore(b);\n    long long denominator = (long long)f1*f1 + (long long)f2*f2 + (long long)f3*f3;\n    if(denominator == 0) return 0;\n    return (double)numerator / denominator;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read all flavors in advance\n    vector<int> flavors(100);\n    for(int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    Board board;\n    char directions[] = {'F', 'B', 'L', 'R'};\n    \n    // Process each candy placement\n    for(int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Place candy in p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int count = 0;\n        for(int i = 0; i < 10; i++) {\n            for(int j = 0; j < 10; j++) {\n                if(board.grid[i][j] == 0) {\n                    count++;\n                    if(count == p) {\n                        board.grid[i][j] = flavors[t];\n                        break;\n                    }\n                }\n                if(count == p) break;\n            }\n            if(count == p) break;\n        }\n        \n        // Skip output for last step (nothing happens)\n        if(t == 99) {\n            cout << \"F\" << endl;\n            continue;\n        }\n        \n        // Try all 4 directions and pick the best\n        double bestScore = -1;\n        char bestDir = 'F';\n        \n        for(char dir : directions) {\n            Board temp = board;\n            tilt(temp, dir);\n            double score = getNormalizedScore(temp);\n            \n            if(score > bestScore) {\n                bestScore = score;\n                bestDir = dir;\n            }\n        }\n        \n        // Apply the best direction\n        tilt(board, bestDir);\n        cout << bestDir << endl;\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <bitset>\n\nusing namespace std;\n\nconst int MAX_N = 100;\n\nstruct Graph {\n    int n;\n    vector<bitset<MAX_N>> adj;\n\n    Graph(int n = 0) : n(n), adj(n) {}\n\n    static Graph from_string(int n, const string& s) {\n        Graph g(n);\n        size_t idx = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (idx < s.size()) {\n                    if (s[idx] == '1') {\n                        g.adj[i][j] = 1;\n                        g.adj[j][i] = 1;\n                    }\n                }\n                idx++;\n            }\n        }\n        return g;\n    }\n\n    string to_string() const {\n        string s;\n        s.reserve(n * (n - 1) / 2);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                s += (adj[i][j] ? '1' : '0');\n            }\n        }\n        return s;\n    }\n\n    static Graph random(int n, double p, mt19937& gen) {\n        Graph g(n);\n        uniform_real_distribution<double> dist(0.0, 1.0);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (dist(gen) < p) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                }\n            }\n        }\n        return g;\n    }\n\n    static Graph complete(int n) {\n        Graph g(n);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                g.adj[i][j] = 1;\n                g.adj[j][i] = 1;\n            }\n        }\n        return g;\n    }\n\n    static Graph empty(int n) {\n        return Graph(n);\n    }\n};\n\nstruct Features {\n    double edge_count;\n    double triangle_count;\n    double sum_sq_deg;\n    double sum_cube_deg;\n    vector<double> sorted_degrees;\n\n    Features() : edge_count(0), triangle_count(0), sum_sq_deg(0), sum_cube_deg(0) {}\n    \n    Features(int n) : edge_count(0), triangle_count(0), sum_sq_deg(0), sum_cube_deg(0) {\n        sorted_degrees.resize(n);\n    }\n};\n\nFeatures compute_features(const Graph& g) {\n    Features f;\n    f.sorted_degrees.resize(g.n);\n    \n    for (int i = 0; i < g.n; ++i) {\n        f.sorted_degrees[i] = (double)g.adj[i].count();\n        f.sum_sq_deg += f.sorted_degrees[i] * f.sorted_degrees[i];\n        f.sum_cube_deg += f.sorted_degrees[i] * f.sorted_degrees[i] * f.sorted_degrees[i];\n    }\n    f.edge_count = 0;\n    for (int i = 0; i < g.n; ++i) {\n        f.edge_count += f.sorted_degrees[i];\n    }\n    f.edge_count /= 2.0;\n    \n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Count triangles\n    for (int i = 0; i < g.n; ++i) {\n        for (int j = i + 1; j < g.n; ++j) {\n            if (g.adj[i][j]) {\n                for (int k = j + 1; k < g.n; ++k) {\n                    if (g.adj[i][k] && g.adj[j][k]) {\n                        f.triangle_count++;\n                    }\n                }\n            }\n        }\n    }\n    return f;\n}\n\nFeatures compute_expected_features(const Graph& g, double eps) {\n    Features f;\n    int n = g.n;\n    int total_edges = n * (n - 1) / 2;\n    f.sorted_degrees.resize(n);\n\n    // Expected Edge Count\n    long long e_g = 0;\n    for(int i=0; i<n; ++i) e_g += g.adj[i].count();\n    e_g /= 2;\n    f.edge_count = e_g * (1.0 - 2.0 * eps) + total_edges * eps;\n\n    // Expected Degree Sequence\n    for (int i = 0; i < n; ++i) {\n        double d_i = (double)g.adj[i].count();\n        f.sorted_degrees[i] = d_i * (1.0 - 2.0 * eps) + (n - 1) * eps;\n    }\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Expected Sum Sq Deg\n    double var_deg = (n - 1) * eps * (1.0 - eps);\n    for (int i = 0; i < n; ++i) {\n        double mean_d = f.sorted_degrees[i];\n        f.sum_sq_deg += var_deg + mean_d * mean_d;\n        f.sum_cube_deg += mean_d * mean_d * mean_d + 3.0 * mean_d * var_deg;\n    }\n\n    // Expected Triangle Count\n    double p0 = pow(eps, 3);\n    double p1 = pow(eps, 2) * (1.0 - eps);\n    double p2 = eps * pow(1.0 - eps, 2);\n    double p3 = pow(1.0 - eps, 3);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            for (int k = j + 1; k < n; ++k) {\n                int edges = 0;\n                if (g.adj[i][j]) edges++;\n                if (g.adj[i][k]) edges++;\n                if (g.adj[j][k]) edges++;\n                if (edges == 0) f.triangle_count += p0;\n                else if (edges == 1) f.triangle_count += p1;\n                else if (edges == 2) f.triangle_count += p2;\n                else f.triangle_count += p3;\n            }\n        }\n    }\n\n    return f;\n}\n\ndouble feature_distance(const Features& f1, const Features& f2) {\n    double dist = 0.0;\n    double s_ec = 1.0;\n    double s_tc = 1.0 / 100.0;\n    double s_sq = 1.0 / 1000.0;\n    double s_cb = 1.0 / 10000.0;\n    double s_deg = 1.0 / 10.0;\n\n    dist += s_ec * (f1.edge_count - f2.edge_count) * (f1.edge_count - f2.edge_count);\n    dist += s_tc * (f1.triangle_count - f2.triangle_count) * (f1.triangle_count - f2.triangle_count);\n    dist += s_sq * (f1.sum_sq_deg - f2.sum_sq_deg) * (f1.sum_sq_deg - f2.sum_sq_deg);\n    dist += s_cb * (f1.sum_cube_deg - f2.sum_cube_deg) * (f1.sum_cube_deg - f2.sum_cube_deg);\n    \n    for (size_t i = 0; i < f1.sorted_degrees.size(); ++i) {\n        dist += s_deg * (f1.sorted_degrees[i] - f2.sorted_degrees[i]) * \n                (f1.sorted_degrees[i] - f2.sorted_degrees[i]);\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n    int best_N = 40;\n    vector<Graph> best_Gs;\n    vector<Features> best_ExpectedFeatures;\n    double best_score = -1.0;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 3.5;\n\n    vector<int> N_candidates = {30, 40, 50, 60, 70, 80};\n    if (M > 50) N_candidates = {40, 50, 60, 70, 80, 90};\n    if (M > 80) N_candidates = {50, 60, 70, 80, 90};\n\n    for (int N : N_candidates) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        int pool_size = min(200, M * 3);\n        vector<Graph> candidates;\n        candidates.reserve(pool_size + 2);\n        \n        // Generate diverse graphs\n        for (int i = 0; i < pool_size; ++i) {\n            double p = 0.1 + 0.8 * ((double)rand() / RAND_MAX);\n            candidates.push_back(Graph::random(N, p, gen));\n        }\n        candidates.push_back(Graph::empty(N));\n        candidates.push_back(Graph::complete(N));\n\n        vector<Features> cand_expected;\n        cand_expected.reserve(candidates.size());\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            cand_expected.push_back(compute_expected_features(candidates[i], eps));\n        }\n\n        vector<int> selected_indices;\n        selected_indices.reserve(M);\n        selected_indices.push_back(0);\n        \n        for (int i = 1; i < M; ++i) {\n            int best_idx = -1;\n            double max_min_dist = -1.0;\n            \n            for (size_t j = 0; j < candidates.size(); ++j) {\n                bool found = false;\n                for (int k : selected_indices) {\n                    if (k == (int)j) { found = true; break; }\n                }\n                if (found) continue;\n                \n                double min_d = 1e18;\n                for (int k : selected_indices) {\n                    double d = feature_distance(cand_expected[j], cand_expected[k]);\n                    if (d < min_d) min_d = d;\n                }\n                \n                if (min_d > max_min_dist) {\n                    max_min_dist = min_d;\n                    best_idx = (int)j;\n                }\n            }\n            \n            if (best_idx != -1) {\n                selected_indices.push_back(best_idx);\n            } else {\n                int r = rand() % candidates.size();\n                while (true) {\n                    bool found = false;\n                    for (int k : selected_indices) {\n                        if (k == r) { found = true; break; }\n                    }\n                    if (!found) break;\n                    r = rand() % candidates.size();\n                }\n                selected_indices.push_back(r);\n            }\n        }\n\n        double min_pair_dist = 1e18;\n        for (size_t i = 0; i < selected_indices.size(); ++i) {\n            for (size_t j = i + 1; j < selected_indices.size(); ++j) {\n                double d = feature_distance(cand_expected[selected_indices[i]], cand_expected[selected_indices[j]]);\n                if (d < min_pair_dist) min_pair_dist = d;\n            }\n        }\n\n        double E_est = 100.0 * exp(-min_pair_dist / 3000.0);\n        if (E_est < 0.0) E_est = 0.0;\n        if (E_est > 100.0) E_est = 100.0;\n\n        double score = pow(0.9, E_est) / N;\n        \n        if (score > best_score || (abs(score - best_score) < 1e-9 && N < best_N)) {\n            best_score = score;\n            best_N = N;\n            best_Gs.clear();\n            best_ExpectedFeatures.clear();\n            for (int idx : selected_indices) {\n                best_Gs.push_back(candidates[idx]);\n                best_ExpectedFeatures.push_back(cand_expected[idx]);\n            }\n        }\n    }\n\n    cout << best_N << endl;\n    for (const auto& g : best_Gs) {\n        cout << g.to_string() << endl;\n    }\n    cout.flush();\n\n    string H_str;\n    for (int q = 0; q < 100; ++q) {\n        cin >> H_str;\n        Graph H = Graph::from_string(best_N, H_str);\n        Features h_feat = compute_features(H);\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double d = feature_distance(h_feat, best_ExpectedFeatures[k]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint N, M, D, K;\nstruct Edge {\n    int u, v, w, id;\n};\nvector<Edge> edges;\nvector<int> edge_day;\nvector<vector<long long>> dist_original;\nvector<vector<pair<int, int>>> adj;\nvector<pair<int, int>> sampled_pairs;\nvector<long long> day_frustration;\nlong long total_frustration;\nmt19937 rng;\nchrono::steady_clock::time_point start_time;\n\nvoid init_rng() {\n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n}\n\nvoid build_adjacency() {\n    adj.assign(N + 1, vector<pair<int, int>>());\n    for (int i = 0; i < M; i++) {\n        adj[edges[i].u].push_back({edges[i].v, i});\n        adj[edges[i].v].push_back({edges[i].u, i});\n    }\n}\n\nvoid calc_original_distances() {\n    dist_original.assign(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int start = 1; start <= N; start++) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        dist_original[start][start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist_original[start][u]) continue;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (dist_original[start][v] > dist_original[start][u] + edges[eid].w) {\n                    dist_original[start][v] = dist_original[start][u] + edges[eid].w;\n                    pq.push({dist_original[start][v], v});\n                }\n            }\n        }\n    }\n}\n\nvoid sample_pairs() {\n    sampled_pairs.clear();\n    int num_samples = min(N * N, 800);\n    \n    vector<pair<int, int>> all_pairs;\n    for (int i = 1; i <= N; i++) {\n        for (int j = 1; j <= N; j++) {\n            if (i != j) all_pairs.push_back({i, j});\n        }\n    }\n    \n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    for (int i = 0; i < min((int)all_pairs.size(), num_samples); i++) {\n        sampled_pairs.push_back(all_pairs[i]);\n    }\n}\n\nlong long calc_frustration_day(int k) {\n    long long total_increase = 0;\n    \n    for (auto& [start, end] : sampled_pairs) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, 1e18);\n        dist[start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == end) break;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (edge_day[eid] == k) continue;\n                \n                if (dist[v] > dist[u] + edges[eid].w) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        if (dist[end] >= 1e9) {\n            total_increase += 1e9;\n        } else {\n            total_increase += max(0LL, dist[end] - dist_original[start][end]);\n        }\n    }\n    \n    return total_increase;\n}\n\nvoid calc_all_frustrations() {\n    day_frustration.assign(D + 1, 0);\n    total_frustration = 0;\n    for (int k = 1; k <= D; k++) {\n        day_frustration[k] = calc_frustration_day(k);\n        total_frustration += day_frustration[k];\n    }\n}\n\nbool check_time() {\n    auto now = chrono::steady_clock::now();\n    auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed < 5000;\n}\n\nvoid init_solution() {\n    edge_day.assign(M, 0);\n    vector<int> day_count(D + 1, 0);\n    \n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    shuffle(edge_order.begin(), edge_order.end(), rng);\n    \n    for (int i : edge_order) {\n        int best_day = 1;\n        for (int d = 2; d <= D; d++) {\n            if (day_count[d] < day_count[best_day]) {\n                best_day = d;\n            }\n        }\n        edge_day[i] = best_day;\n        day_count[best_day]++;\n    }\n}\n\nvoid local_search() {\n    calc_all_frustrations();\n    long long best_frustration = total_frustration;\n    vector<int> best_day = edge_day;\n    vector<long long> best_day_frustration = day_frustration;\n    \n    int iterations = 0;\n    int max_iterations = 15;\n    \n    while (check_time() && iterations < max_iterations) {\n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) {\n            iterations++;\n            continue;\n        }\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        // Swap edges\n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        // Only recalculate affected days\n        long long old_frustration = total_frustration - day_frustration[d1] - day_frustration[d2];\n        day_frustration[d1] = calc_frustration_day(d1);\n        day_frustration[d2] = calc_frustration_day(d2);\n        long long new_frustration = old_frustration + day_frustration[d1] + day_frustration[d2];\n        \n        if (new_frustration < best_frustration) {\n            best_frustration = new_frustration;\n            best_day = edge_day;\n            best_day_frustration = day_frustration;\n        } else {\n            // Undo swap\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            day_frustration[d1] = best_day_frustration[d1];\n            day_frustration[d2] = best_day_frustration[d2];\n            total_frustration = best_frustration;\n        }\n        \n        iterations++;\n    }\n    \n    edge_day = best_day;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> D >> K;\n    \n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i;\n    }\n    \n    vector<int> x(N + 1), y(N + 1);\n    for (int i = 1; i <= N; i++) {\n        cin >> x[i] >> y[i];\n    }\n    \n    init_rng();\n    build_adjacency();\n    calc_original_distances();\n    sample_pairs();\n    init_solution();\n    \n    if (check_time()) {\n        local_search();\n    }\n    \n    for (int i = 0; i < M; i++) {\n        cout << edge_day[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int MAXD = 15;\n\nint D;\nvector<string> f[2], r[2];\nint b[2][MAXD][MAXD][MAXD];\n\n// Block structure\nstruct Block {\n    int id;\n    vector<tuple<int,int,int>> cells;\n    int volume;\n    \n    Block() : id(0), volume(0) {}\n    Block(int i, const vector<tuple<int,int,int>>& c) : id(i), cells(c), volume(c.size()) {}\n};\n\n// Get all 24 rotations of a shape\nvector<vector<tuple<int,int,int>>> get_rotations(const vector<tuple<int,int,int>>& shape) {\n    vector<vector<tuple<int,int,int>>> rotations;\n    \n    auto normalize = [](vector<tuple<int,int,int>> s) {\n        int min_x = 0, min_y = 0, min_z = 0;\n        for (auto& [x, y, z] : s) {\n            min_x = min(min_x, x);\n            min_y = min(min_y, y);\n            min_z = min(min_z, z);\n        }\n        for (auto& [x, y, z] : s) {\n            x -= min_x;\n            y -= min_y;\n            z -= min_z;\n        }\n        sort(s.begin(), s.end());\n        return s;\n    };\n    \n    auto rotate_x = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(x, z, -y);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_y = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-z, y, x);\n        }\n        return normalize(s);\n    };\n    \n    auto rotate_z = [](vector<tuple<int,int,int>> s) {\n        for (auto& [x, y, z] : s) {\n            tie(x, y, z) = make_tuple(-y, x, z);\n        }\n        return normalize(s);\n    };\n    \n    vector<tuple<int,int,int>> current = shape;\n    set<vector<tuple<int,int,int>>> seen;\n    queue<vector<tuple<int,int,int>>> q;\n    \n    current = normalize(current);\n    seen.insert(current);\n    q.push(current);\n    rotations.push_back(current);\n    \n    while (!q.empty()) {\n        auto cur = q.front();\n        q.pop();\n        \n        for (auto& rot : {rotate_x, rotate_y, rotate_z}) {\n            auto next = rot(cur);\n            if (seen.find(next) == seen.end()) {\n                seen.insert(next);\n                q.push(next);\n                rotations.push_back(next);\n            }\n        }\n    }\n    \n    return rotations;\n}\n\n// Check if two shapes can match through rotation/translation\nbool can_match_shapes(const vector<tuple<int,int,int>>& shape1, const vector<tuple<int,int,int>>& shape2) {\n    if (shape1.size() != shape2.size()) return false;\n    \n    auto norm2 = normalize(shape2);\n    auto rotations = get_rotations(shape1);\n    \n    for (const auto& rot : rotations) {\n        if (rot == norm2) return true;\n    }\n    \n    return false;\n}\n\n// Normalize a shape for comparison\nvector<tuple<int,int,int>> normalize(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> s = shape;\n    if (s.empty()) return s;\n    \n    int min_x = 0, min_y = 0, min_z = 0;\n    for (auto& [x, y, z] : s) {\n        min_x = min(min_x, x);\n        min_y = min(min_y, y);\n        min_z = min(min_z, z);\n    }\n    for (auto& [x, y, z] : s) {\n        x -= min_x;\n        y -= min_y;\n        z -= min_z;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\n// Find connected components in a 3D grid\nvector<vector<tuple<int,int,int>>> find_connected_components(int id, const int (*grid)[MAXD][MAXD][MAXD]) {\n    vector<vector<tuple<int,int,int>>> components;\n    bool visited[MAXD][MAXD][MAXD] = {0};\n    \n    auto bfs = [&](int sx, int sy, int sz, int target_id) {\n        vector<tuple<int,int,int>> component;\n        queue<tuple<int,int,int>> q;\n        \n        visited[sx][sy][sz] = true;\n        q.push({sx, sy, sz});\n        component.push_back({sx, sy, sz});\n        \n        int dx[] = {1, -1, 0, 0, 0, 0};\n        int dy[] = {0, 0, 1, -1, 0, 0};\n        int dz[] = {0, 0, 0, 0, 1, -1};\n        \n        while (!q.empty()) {\n            auto [x, y, z] = q.front();\n            q.pop();\n            \n            for (int i = 0; i < 6; i++) {\n                int nx = x + dx[i];\n                int ny = y + dy[i];\n                int nz = z + dz[i];\n                \n                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                    !visited[nx][ny][nz] && (*grid)[nx][ny][nz] == target_id) {\n                    visited[nx][ny][nz] = true;\n                    q.push({nx, ny, nz});\n                    component.push_back({nx, ny, nz});\n                }\n            }\n        }\n        \n        return component;\n    };\n    \n    // Find all blocks with their IDs\n    map<int, vector<tuple<int,int,int>>> blocks;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if ((*grid)[x][y][z] > 0) {\n                    blocks[(*grid)[x][y][z]].push_back({x, y, z});\n                }\n            }\n        }\n    }\n    \n    for (auto& [id, cells] : blocks) {\n        components.push_back(cells);\n    }\n    \n    return components;\n}\n\n// Main optimization function\nvoid optimize() {\n    // Phase 1: Initial placement - place unit blocks at all valid positions\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent blocks with same ID to form larger blocks\n    // This is already done by the initial placement\n    \n    // Phase 3: Try to find common blocks between the two constructions\n    // Group blocks by their normalized shapes\n    map<vector<tuple<int,int,int>>, vector<pair<int,int>>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back({id, i});\n        }\n    }\n    \n    // Phase 4: Try to merge blocks that have matching shapes\n    // This is a heuristic - we prioritize larger blocks and shared blocks\n    \n    // For now, output the initial solution\n    // A more sophisticated solution would use simulated annealing or genetic algorithms\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        r[i].resize(D);\n        for (int z = 0; z < D; z++) {\n            cin >> f[i][z];\n        }\n        for (int z = 0; z < D; z++) {\n            cin >> r[i][z];\n        }\n    }\n    \n    // Initialize block arrays\n    memset(b, 0, sizeof(b));\n    \n    // Phase 1: Initial placement\n    int block_counter = 0;\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = ++block_counter;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent cells into connected components\n    // This creates larger blocks from adjacent unit blocks\n    int new_block_counter = 0;\n    int temp_b[2][MAXD][MAXD][MAXD];\n    memset(temp_b, 0, sizeof(temp_b));\n    \n    for (int i = 0; i < 2; i++) {\n        // Find connected components\n        bool visited[MAXD][MAXD][MAXD] = {0};\n        \n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0 && !visited[x][y][z]) {\n                        // BFS to find connected component\n                        vector<tuple<int,int,int>> component;\n                        queue<tuple<int,int,int>> q;\n                        \n                        visited[x][y][z] = true;\n                        q.push({x, y, z});\n                        component.push_back({x, y, z});\n                        \n                        int dx[] = {1, -1, 0, 0, 0, 0};\n                        int dy[] = {0, 0, 1, -1, 0, 0};\n                        int dz[] = {0, 0, 0, 0, 1, -1};\n                        \n                        while (!q.empty()) {\n                            auto [cx, cy, cz] = q.front();\n                            q.pop();\n                            \n                            for (int d = 0; d < 6; d++) {\n                                int nx = cx + dx[d];\n                                int ny = cy + dy[d];\n                                int nz = cz + dz[d];\n                                \n                                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                    !visited[nx][ny][nz] && b[i][nx][ny][nz] > 0) {\n                                    visited[nx][ny][nz] = true;\n                                    q.push({nx, ny, nz});\n                                    component.push_back({nx, ny, nz});\n                                }\n                            }\n                        }\n                        \n                        // Assign new block ID to all cells in component\n                        new_block_counter++;\n                        for (auto& [cx, cy, cz] : component) {\n                            temp_b[i][cx][cy][cz] = new_block_counter;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Copy back\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    b[i][x][y][z] = temp_b[i][x][y][z];\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Try to match blocks between the two constructions\n    // Group blocks by normalized shape\n    map<vector<tuple<int,int,int>>, vector<int>> shape_to_blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        map<int, vector<tuple<int,int,int>>> blocks;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n        \n        for (auto& [id, cells] : blocks) {\n            auto norm = normalize(cells);\n            shape_to_blocks[i][norm].push_back(id);\n        }\n    }\n    \n    // Try to reuse blocks with matching shapes\n    int reused_blocks = 0;\n    for (auto& [norm, ids1] : shape_to_blocks[0]) {\n        if (shape_to_blocks[1].find(norm) != shape_to_blocks[1].end()) {\n            auto& ids2 = shape_to_blocks[1][norm];\n            // Reuse the first matching block\n            if (!ids1.empty() && !ids2.empty()) {\n                int reuse_id = ids1[0];\n                for (int x = 0; x < D; x++) {\n                    for (int y = 0; y < D; y++) {\n                        for (int z = 0; z < D; z++) {\n                            if (b[1][x][y][z] == ids2[0]) {\n                                b[1][x][y][z] = reuse_id;\n                            }\n                        }\n                    }\n                }\n                reused_blocks++;\n            }\n        }\n    }\n    \n    // Output\n    cout << new_block_counter << \"\\n\";\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    cout << b[i][x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \");\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst long long INF_COST = 1e18;\nconst int MAX_P = 5000;\n\n// Data structures\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int _x, int _y) : x(_x), y(_y) {}\n    \n    long long distSq(const Point& other) const {\n        return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y);\n    }\n    \n    double dist(const Point& other) const {\n        return sqrt(distSq(other));\n    }\n};\n\nstruct Edge {\n    int u, v, w;\n    int id;\n};\n\nstruct Resident {\n    int x, y, id;\n};\n\n// Global data\nint N, M, K;\nvector<Point> stations;\nvector<Edge> edges;\nvector<Resident> residents;\nvector<int> P;\nvector<int> B;\nvector<int> activeStations;\nvector<vector<int>> stationResidents;\nvector<vector<int>> adj;\nvector<long long> edgeCost;\n\n// Calculate total cost\nlong long calculateCost() {\n    long long cost = 0;\n    \n    // Edge costs\n    for (int j = 0; j < M; j++) {\n        if (B[j]) cost += edges[j].w;\n    }\n    \n    // Coverage costs\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    \n    return cost;\n}\n\n// Check if all residents are covered\nbool allCovered() {\n    for (int k = 0; k < K; k++) {\n        bool covered = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && stations[i].distSq(residents[k]) <= 1LL * P[i] * P[i]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\n// Check connectivity from vertex 1\nbool isConnected() {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    \n    q.push(0);\n    visited[0] = true;\n    \n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        \n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int edgeIdx = edge.second;\n            \n            if (B[edgeIdx] && !visited[v]) {\n                visited[v] = true;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Check if all stations with P > 0 are reachable\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && !visited[i]) {\n            return false;\n        }\n    }\n    \n    return true;\n}\n\n// Get minimum P needed to cover a resident\nint getPForResident(int stationIdx, int residentIdx) {\n    long long d2 = stations[stationIdx].distSq(residents[residentIdx]);\n    if (d2 > 1LL * MAX_P * MAX_P) return -1;\n    return (int)ceil(sqrt(d2));\n}\n\n// Assign residents to nearest active station\nvoid assignResidentsToStations() {\n    stationResidents.assign(N, vector<int>());\n    \n    for (int k = 0; k < K; k++) {\n        int bestStation = -1;\n        long long minDist = INF_COST;\n        \n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0) {\n                long long d = stations[i].distSq(residents[k]);\n                if (d < minDist) {\n                    minDist = d;\n                    bestStation = i;\n                }\n            }\n        }\n        \n        if (bestStation >= 0) {\n            stationResidents[bestStation].push_back(k);\n        }\n    }\n}\n\n// Calculate optimal P for each station based on assigned residents\nvoid optimizeP() {\n    for (int i = 0; i < N; i++) {\n        if (stationResidents[i].empty()) {\n            P[i] = 0;\n            continue;\n        }\n        \n        // Find maximum distance to any assigned resident\n        long long maxDist = 0;\n        for (int k : stationResidents[i]) {\n            maxDist = max(maxDist, stations[i].distSq(residents[k]));\n        }\n        \n        if (maxDist > 1LL * MAX_P * MAX_P) {\n            P[i] = MAX_P;\n        } else {\n            P[i] = (int)ceil(sqrt(maxDist));\n        }\n    }\n}\n\n// Build MST to connect active stations to vertex 1\nvoid buildNetwork() {\n    // Reset all edges\n    fill(B.begin(), B.end(), 0);\n    \n    // Collect active stations\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0) active.push_back(i);\n    }\n    \n    // If vertex 1 is not active, make it active\n    if (P[0] == 0 && !active.empty()) {\n        P[0] = 1;\n        active.push_back(0);\n    }\n    \n    // Use Kruskal's algorithm to connect all active stations\n    struct EdgeWithCost {\n        int u, v, w, id;\n    };\n    \n    vector<EdgeWithCost> edgeList;\n    for (int j = 0; j < M; j++) {\n        edgeList.push_back({edges[j].u - 1, edges[j].v - 1, edges[j].w, j});\n    }\n    \n    sort(edgeList.begin(), edgeList.end(), [](const EdgeWithCost& a, const EdgeWithCost& b) {\n        return a.w < b.w;\n    });\n    \n    // Union-Find\n    vector<int> parent(N);\n    iota(parent.begin(), parent.end(), 0);\n    \n    function<int(int)> find = [&](int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    };\n    \n    auto unite = [&](int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x != y) {\n            parent[x] = y;\n            return true;\n        }\n        return false;\n    };\n    \n    // Connect all active stations to vertex 1\n    for (auto& e : edgeList) {\n        if (find(e.u) != find(e.v)) {\n            unite(e.u, e.v);\n            B[e.id] = 1;\n        }\n    }\n}\n\n// Local search: try adding/removing stations\nvoid localSearch() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int iterations = 10000;\n    double temperature = 1000000.0;\n    double coolingRate = 0.9995;\n    \n    long long bestCost = calculateCost();\n    vector<int> bestP = P;\n    vector<int> bestB = B;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        // Try random modification\n        int action = rng() % 5;\n        \n        if (action == 0) {\n            // Try activating a new station\n            int station = rng() % N;\n            if (P[station] == 0) {\n                int oldP = P[station];\n                P[station] = 1;\n                \n                // Assign nearby residents\n                for (int k = 0; k < K; k++) {\n                    long long d = stations[station].distSq(residents[k]);\n                    if (d <= 1LL * MAX_P * MAX_P) {\n                        // Check if this is better than current assignment\n                        int currentBest = -1;\n                        long long currentDist = INF_COST;\n                        for (int i = 0; i < N; i++) {\n                            if (P[i] > 0) {\n                                long long d2 = stations[i].distSq(residents[k]);\n                                if (d2 < currentDist) {\n                                    currentDist = d2;\n                                    currentBest = i;\n                                }\n                            }\n                        }\n                        \n                        if (currentBest < 0 || d < currentDist) {\n                            // Reassign to this station\n                            optimizeP();\n                        }\n                    }\n                }\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 1) {\n            // Try deactivating a station\n            vector<int> activeStations;\n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) activeStations.push_back(i);\n            }\n            \n            if (activeStations.size() > 1) {\n                int idx = rng() % activeStations.size();\n                int station = activeStations[idx];\n                \n                // Skip vertex 1\n                if (station == 0) continue;\n                \n                int oldP = P[station];\n                P[station] = 0;\n                \n                // Reassign residents\n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 2) {\n            // Try increasing P\n            int station = rng() % N;\n            if (P[station] < MAX_P) {\n                int oldP = P[station];\n                P[station] = min(MAX_P, P[station] + rng() % 500 + 1);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else if (action == 3) {\n            // Try decreasing P\n            int station = rng() % N;\n            if (P[station] > 0) {\n                int oldP = P[station];\n                P[station] = max(0, P[station] - rng() % 500);\n                \n                optimizeP();\n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[station] = oldP;\n                    buildNetwork();\n                }\n            }\n        } else {\n            // Try reassigning a random resident\n            int resident = rng() % K;\n            int bestStation = -1;\n            long long minDist = INF_COST;\n            \n            for (int i = 0; i < N; i++) {\n                if (P[i] > 0) {\n                    long long d = stations[i].distSq(residents[resident]);\n                    if (d < minDist) {\n                        minDist = d;\n                        bestStation = i;\n                    }\n                }\n            }\n            \n            if (bestStation >= 0) {\n                int oldP = P[bestStation];\n                int newP = (int)ceil(sqrt(minDist));\n                P[bestStation] = newP;\n                \n                buildNetwork();\n                long long newCost = calculateCost();\n                \n                if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n                    bestCost = newCost;\n                    bestP = P;\n                    bestB = B;\n                } else {\n                    P[bestStation] = oldP;\n                    buildNetwork();\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    P = bestP;\n    B = bestB;\n}\n\n// Initial solution\nvoid initSolution() {\n    P.assign(N, 0);\n    B.assign(M, 0);\n    \n    // Find nearest station for each resident\n    vector<int> residentStation(K, -1);\n    vector<long long> residentDist(K, INF_COST);\n    \n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d = stations[i].distSq(residents[k]);\n            if (d < residentDist[k]) {\n                residentDist[k] = d;\n                residentStation[k] = i;\n            }\n        }\n    }\n    \n    // Set P for each station based on assigned residents\n    for (int i = 0; i < N; i++) {\n        long long maxDist = 0;\n        for (int k = 0; k < K; k++) {\n            if (residentStation[k] == i) {\n                maxDist = max(maxDist, residentDist[k]);\n            }\n        }\n        \n        if (maxDist > 0) {\n            P[i] = (int)ceil(sqrt(maxDist));\n            if (P[i] > MAX_P) P[i] = MAX_P;\n        }\n    }\n    \n    // Ensure vertex 1 is active if needed\n    if (P[0] == 0) {\n        P[0] = 1;\n    }\n    \n    // Build network\n    buildNetwork();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N >> M >> K;\n    \n    stations.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    edgeCost.resize(M);\n    \n    for (int j = 0; j < M; j++) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n        edges[j].u--;\n        edges[j].v--;\n        edges[j].id = j;\n        adj[edges[j].u].push_back({edges[j].v, j});\n        adj[edges[j].v].push_back({edges[j].u, j});\n        edgeCost[j] = edges[j].w;\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n    \n    // Initial solution\n    initSolution();\n    \n    // Local search with simulated annealing\n    localSearch();\n    \n    // Final optimization\n    optimizeP();\n    buildNetwork();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\n\nint N = 30;\nvector<vector<int>> grid;\nvector<tuple<int, int, int, int>> operations;\n\n// Get all 6 adjacent positions\nvector<pair<int, int>> get_adj(int x, int y) {\n    vector<pair<int, int>> adj;\n    int dx[] = {-1, -1, 0, 0, 1, 1};\n    int dy[] = {-1, 0, -1, 1, 0, 1};\n    \n    for (int i = 0; i < 6; i++) {\n        int nx = x + dx[i];\n        int ny = y + dy[i];\n        if (nx >= 0 && nx < N && ny >= 0 && ny <= nx) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\n// BFS to find shortest path from (sx, sy) to (tx, ty)\nvector<pair<int, int>> bfs_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {};\n    \n    queue<pair<int, int>> q;\n    map<pair<int, int>, pair<int, int>> parent;\n    \n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == tx && y == ty) {\n            vector<pair<int, int>> path;\n            auto curr = make_pair(tx, ty);\n            while (curr.first != -1 && curr.second != -1) {\n                path.push_back(curr);\n                curr = parent[curr];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto [nx, ny] : get_adj(x, y)) {\n            if (parent.find({nx, ny}) == parent.end()) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    return {};\n}\n\n// Swap balls at two positions and record operation\nvoid swap_positions(int x1, int y1, int x2, int y2) {\n    int temp = grid[x1][y1];\n    grid[x1][y1] = grid[x2][y2];\n    grid[x2][y2] = temp;\n    operations.emplace_back(x1, y1, x2, y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    grid.resize(N);\n    for (int x = 0; x < N; x++) {\n        grid[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n        }\n    }\n    \n    // Track which positions are already filled\n    vector<vector<bool>> filled(N);\n    for (int x = 0; x < N; x++) {\n        filled[x].assign(x + 1, false);\n    }\n    \n    // Process positions from top to bottom\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (filled[x][y]) continue;\n            \n            // Find smallest ball among all unfilled positions\n            int best_val = 1e9;\n            int best_x = -1, best_y = -1;\n            \n            for (int px = x; px < N; px++) {\n                for (int py = 0; py <= px; py++) {\n                    if (!filled[px][py] && grid[px][py] < best_val) {\n                        best_val = grid[px][py];\n                        best_x = px;\n                        best_y = py;\n                    }\n                }\n            }\n            \n            // Move the best ball to current position\n            if (best_x != -1 && (best_x != x || best_y != y)) {\n                vector<pair<int, int>> path = bfs_path(best_x, best_y, x, y);\n                \n                // Perform swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); i++) {\n                    auto [x1, y1] = path[i];\n                    auto [x2, y2] = path[i + 1];\n                    swap_positions(x1, y1, x2, y2);\n                }\n            }\n            \n            filled[x][y] = true;\n        }\n    }\n    \n    // Output results\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <tuple>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\n// Grid dimensions\nconst int D = 9;\nint N;\nvector<pair<int, int>> obstacles;\nvector<vector<int>> grid; // 0: empty, 1: obstacle, 2: container\nvector<vector<int>> container_id; // ID of container at (i, j), -1 if empty\nvector<pair<int, int>> used_coords; // To track placed containers\n\n// Directions\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\n// BFS to find reachable empty squares and distances\n// Returns a map of (i, j) -> distance\nmap<pair<int, int>, int> get_distances(int start_i, int start_j) {\n    map<pair<int, int>, int> dist;\n    queue<pair<int, int>> q;\n    q.push({start_i, start_j});\n    dist[{start_i, start_j}] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n            if (nr >= 0 && nr < D && nc >= 0 && nc < D) {\n                if (grid[nr][nc] == 0 && dist.find({nr, nc}) == dist.end()) {\n                    dist[{nr, nc}] = dist[{r, c}] + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return dist;\n}\n\n// Check if a square is \"Safe\" to place a container\n// Safe means removing it (making it occupied) does not disconnect any other empty squares from entrance\nbool is_safe(int r, int c, int entrance_r, int entrance_c) {\n    // Temporarily mark as occupied\n    int original = grid[r][c];\n    grid[r][c] = 2; // Mark as occupied\n    \n    // Count reachable empty squares\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    int reachable_count = 0;\n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            reachable_count++;\n        }\n    }\n    \n    // Restore\n    grid[r][c] = original;\n    \n    // Calculate total empty squares\n    int total_empty = 0;\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (grid[i][j] == 0) total_empty++;\n        }\n    }\n    \n    // If we placed at (r, c), one less empty square.\n    // So we expect reachable_count == total_empty - 1\n    // Note: (r, c) is now occupied, so it's not counted in total_empty in the check above?\n    // Wait, total_empty is calculated with (r, c) as empty (restored).\n    // So if (r, c) is occupied, total empty is total_empty - 1.\n    // We need all other empty squares to be reachable.\n    // So reachable_count should be total_empty - 1.\n    \n    return reachable_count == total_empty - 1;\n}\n\n// Sort empty squares by accessibility for placement\n// We want to fill Leaves (Far) first, then Closer.\n// So sort by Distance Descending.\n// Safe squares are prioritized.\nvector<pair<int, int>> get_sorted_candidates(int entrance_r, int entrance_c) {\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    vector<pair<int, int>> candidates;\n    \n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            candidates.push_back(pos);\n        }\n    }\n    \n    // Sort by Distance Descending (Far first)\n    // Tie-breaker: Coordinate order for stability\n    sort(candidates.begin(), candidates.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {\n        if (dist[a] != dist[b]) return dist[a] > dist[b];\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    \n    // Filter Safe squares\n    vector<pair<int, int>> safe_candidates;\n    for (auto p : candidates) {\n        if (is_safe(p.first, p.second, entrance_r, entrance_c)) {\n            safe_candidates.push_back(p);\n        }\n    }\n    \n    // If no safe candidates (should not happen unless 1 square left), return all reachable\n    if (safe_candidates.empty() && !candidates.empty()) {\n        return candidates;\n    }\n    \n    return safe_candidates;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int entrance_r = 0;\n    int entrance_c = (D - 1) / 2;\n    \n    if (!(cin >> D >> N)) return 0;\n    \n    obstacles.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    // Initialize grid\n    grid.assign(D, vector<int>(D, 0));\n    container_id.assign(D, vector<int>(D, -1));\n    \n    for (auto obs : obstacles) {\n        grid[obs.first][obs.second] = 1;\n    }\n    // Entrance is (0, (D-1)/2)\n    // It is not an obstacle.\n    // We treat entrance as empty for placement logic, but we cannot place container there.\n    // Actually problem says \"It is neither the entrance nor an obstacle square\".\n    // So entrance is effectively blocked for placement.\n    grid[entrance_r][entrance_c] = 1; // Mark as obstacle for placement logic\n    \n    set<int> used_ids;\n    int total_containers = D * D - 1 - N;\n    \n    // Placement Phase\n    for (int d = 0; d < total_containers; ++d) {\n        int t;\n        cin >> t;\n        used_ids.insert(t);\n        \n        // Calculate rank r among remaining IDs\n        // r = number of unused IDs smaller than t\n        // Since used_ids contains all IDs placed so far,\n        // unused IDs are those not in used_ids.\n        // But we know t is the current ID.\n        // We can count how many IDs < t are already used.\n        int smaller_used = 0;\n        for (int u : used_ids) {\n            if (u < t) smaller_used++;\n        }\n        // Total IDs < t is t.\n        // So unused IDs < t is t - smaller_used.\n        int r = t - smaller_used;\n        \n        // Get sorted candidates\n        vector<pair<int, int>> candidates = get_sorted_candidates(entrance_r, entrance_c);\n        \n        int U = candidates.size();\n        // We want to place Large IDs at Far (Index 0), Small IDs at Close (Index U-1).\n        // Index k = U - 1 - r.\n        // Clamp k to [0, U-1]\n        int k = U - 1 - r;\n        if (k < 0) k = 0;\n        if (k >= U) k = U - 1;\n        \n        pair<int, int> chosen = candidates[k];\n        grid[chosen.first][chosen.second] = 2;\n        container_id[chosen.first][chosen.second] = t;\n        used_coords.push_back(chosen);\n        \n        cout << chosen.first << \" \" << chosen.second << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval Phase\n    // Greedy: Pick reachable container with min ID\n    vector<pair<int, int>> retrieval_order;\n    // Reset entrance to empty for retrieval logic?\n    // Entrance is (0, 4). It is marked as obstacle (1).\n    // For retrieval, we need to find reachable containers.\n    // Path must be through empty squares.\n    // Entrance is empty (conceptually).\n    // Let's mark entrance as 0 for BFS.\n    grid[entrance_r][entrance_c] = 0;\n    \n    int remaining = total_containers;\n    while (remaining > 0) {\n        // Find all reachable containers\n        // BFS from entrance\n        map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n        \n        int min_id = 1e9;\n        pair<int, int> best_pos = {-1, -1};\n        \n        for (auto const& [pos, d] : dist) {\n            if (grid[pos.first][pos.second] == 2) {\n                int id = container_id[pos.first][pos.second];\n                if (id < min_id) {\n                    min_id = id;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if (best_pos.first != -1) {\n            retrieval_order.push_back(best_pos);\n            grid[best_pos.first][best_pos.second] = 0; // Becomes empty\n            container_id[best_pos.first][best_pos.second] = -1;\n            remaining--;\n        } else {\n            // Should not happen\n            break;\n        }\n    }\n    \n    for (auto p : retrieval_order) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 101;\n\nint n, m;\nint grid[MAXN][MAXN];\nint adj_count[MAXM][MAXM];\nbool required_adj[MAXM][MAXM];\nint num_tiles[MAXM];\nvector<pair<int, int>> tiles[MAXM];\nint pos[MAXN][MAXN];\nvector<pair<int, int>> all_nonzero;\n\nint visited[MAXN][MAXN];\nint visited_cookie = 0;\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < n && c >= 0 && c < n;\n}\n\n// Check connectivity of a specific color\nbool check_connectivity(int color) {\n    if (num_tiles[color] <= 1) return true;\n    \n    visited_cookie++;\n    int start_r = tiles[color][0].first;\n    int start_c = tiles[color][0].second;\n    \n    int count = 0;\n    vector<pair<int, int>> q;\n    q.reserve(num_tiles[color]);\n    q.push_back({start_r, start_c});\n    visited[start_r][start_c] = visited_cookie;\n    count++;\n    \n    int head = 0;\n    while(head < q.size()){\n        auto [r, c] = q[head++];\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_cookie){\n                visited[nr][nc] = visited_cookie;\n                q.push_back({nr, nc});\n                count++;\n            }\n        }\n    }\n    return count == num_tiles[color];\n}\n\n// Try to remove tile at (r, c)\nbool try_remove(int r, int c) {\n    int color = grid[r][c];\n    if(color == 0) return false;\n    \n    // Check adjacency impact\n    bool adj_ok = true;\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != color){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                // If this is the last edge between c1 and c2, and they are required to be adjacent\n                if(adj_count[c1][c2] == 1 && required_adj[c1][c2]){\n                    adj_ok = false;\n                    break;\n                }\n            }\n        }\n    }\n    if(!adj_ok) return false;\n    \n    // Temporarily remove\n    int idx = pos[r][c];\n    tiles[color].erase(tiles[color].begin() + idx);\n    num_tiles[color]--;\n    grid[r][c] = 0;\n    \n    // Update adj_count\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != 0){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                adj_count[c1][c2]--;\n            }\n        }\n    }\n    \n    bool conn_ok = check_connectivity(color);\n    \n    if(!conn_ok){\n        // Revert\n        grid[r][c] = color;\n        num_tiles[color]++;\n        tiles[color].push_back({r, c});\n        pos[r][c] = tiles[color].size() - 1;\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc)){\n                int ncolor = grid[nr][nc];\n                if(ncolor != 0){\n                    int c1 = min(color, ncolor);\n                    int c2 = max(color, ncolor);\n                    adj_count[c1][c2]++;\n                }\n            }\n        }\n        return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> n >> m)) return 0;\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cin >> grid[i][j];\n            if(grid[i][j] != 0){\n                tiles[grid[i][j]].push_back({i, j});\n                pos[i][j] = tiles[grid[i][j]].size() - 1;\n                num_tiles[grid[i][j]]++;\n                all_nonzero.push_back({i, j});\n            }\n        }\n    }\n    \n    memset(required_adj, 0, sizeof(required_adj));\n    memset(adj_count, 0, sizeof(adj_count));\n    \n    // Compute required adjacencies and counts\n    // Count each edge once\n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            int c = grid[i][j];\n            for(int k=0; k<4; k++){\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if(is_valid(ni, nj)){\n                    int nc = grid[ni][nj];\n                    if(c != nc){\n                        int c1 = min(c, nc);\n                        int c2 = max(c, nc);\n                        // Count only once by checking coordinate order\n                        if((i < ni) || (i == ni && j < nj)){\n                             required_adj[c1][c2] = true;\n                             adj_count[c1][c2]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    mt19937 rng(1337);\n    uniform_int_distribution<int> dist_idx(0, (int)all_nonzero.size() - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int no_change = 0;\n    // Run greedy removal\n    while(true){\n        auto now = chrono::steady_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.9) break;\n        \n        if(all_nonzero.empty()) break;\n        \n        int idx = dist_idx((int)all_nonzero.size());\n        auto [r, c] = all_nonzero[idx];\n        \n        if(try_remove(r, c)){\n            // Remove from all_nonzero\n            int last_idx = all_nonzero.size() - 1;\n            all_nonzero[idx] = all_nonzero[last_idx];\n            all_nonzero.pop_back();\n            no_change = 0;\n        } else {\n            no_change++;\n            if(no_change > 5000) break;\n        }\n    }\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cout << grid[i][j] << (j == n-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for problem constraints\nint N, D, Q;\nvector<double> estimated_weights;\nvector<int> assignment;\nvector<vector<int>> sets;\nvector<double> set_sums;\n\n// Random number generator\nmt19937 rng(123456);\n\n// Function to output a query\nvoid output_query(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n}\n\n// Function to read query response\nstring read_response() {\n    string res;\n    cin >> res;\n    return res;\n}\n\n// Calculate variance of set sums\ndouble calculate_variance() {\n    double total_sum = 0.0;\n    for (double s : set_sums) total_sum += s;\n    double mean = total_sum / D;\n    double variance = 0.0;\n    for (double s : set_sums) {\n        variance += (s - mean) * (s - mean);\n    }\n    return variance / D;\n}\n\n// Simulated Annealing for partitioning\nvoid simulate_annealing() {\n    // Initialize assignment using LPT (Largest Processing Time) heuristic\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({estimated_weights[i], i});\n    }\n    sort(items.begin(), items.end(), [](const pair<double, int>& a, const pair<double, int>& b) {\n        return a.first > b.first;\n    });\n\n    // Initialize sets and sums\n    sets.assign(D, vector<int>());\n    set_sums.assign(D, 0.0);\n    assignment.assign(N, 0);\n\n    for (int i = 0; i < N; ++i) {\n        int item_idx = items[i].second;\n        double weight = items[i].first;\n        \n        // Find set with minimum current sum\n        int min_set = 0;\n        for (int j = 1; j < D; ++j) {\n            if (set_sums[j] < set_sums[min_set]) {\n                min_set = j;\n            }\n        }\n        \n        sets[min_set].push_back(item_idx);\n        set_sums[min_set] += weight;\n        assignment[item_idx] = min_set;\n    }\n\n    double best_variance = calculate_variance();\n    vector<int> best_assignment = assignment;\n\n    // SA parameters\n    double temperature = 10.0;\n    double cooling_rate = 0.997;\n    int iterations = 0;\n    const int max_iterations = 30000;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1400); // Leave 600ms margin\n\n    while (iterations < max_iterations && chrono::high_resolution_clock::now() < end_time) {\n        iterations++;\n        \n        // Select random move: swap or move\n        int move_type = uniform_int_distribution<int>(0, 1)(rng);\n        \n        if (move_type == 0) {\n            // Swap items between two different sets\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            if (sets[s1].empty() || sets[s2].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)sets[s2].size() - 1)(rng);\n            \n            int u = sets[s1][idx1];\n            int v = sets[s2][idx2];\n            \n            double w_u = estimated_weights[u];\n            double w_v = estimated_weights[v];\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u + w_v;\n            double new_sum_s2 = set_sums[s2] - w_v + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                assignment[v] = s1;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        } else {\n            // Move item from one set to another\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (sets[s1].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int u = sets[s1][idx1];\n            double w_u = estimated_weights[u];\n            \n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            \n            // Calculate new sums\n            double new_sum_s1 = set_sums[s1] - w_u;\n            double new_sum_s2 = set_sums[s2] + w_u;\n            \n            // Calculate new variance\n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                // Accept move\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < 1e-12) break;\n    }\n\n    assignment = best_assignment;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    estimated_weights.assign(N, 1.0);\n\n    // Weight Estimation Phase\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    int queries_used = 0;\n    \n    // First phase: pairwise comparisons to establish relative ordering\n    int pairs_to_compare = min(Q / 3, N * (N - 1) / 2);\n    \n    for (int i = 0; i < N && queries_used < pairs_to_compare; ++i) {\n        for (int j = i + 1; j < N && queries_used < pairs_to_compare; ++j) {\n            if (queries_used >= pairs_to_compare) break;\n            \n            vector<int> L = {p[i]};\n            vector<int> R = {p[j]};\n            \n            output_query(L, R);\n            string res = read_response();\n            queries_used++;\n            \n            if (res == \"<\") {\n                estimated_weights[p[i]] *= 0.85;\n                estimated_weights[p[j]] *= 1.15;\n            } else if (res == \">\") {\n                estimated_weights[p[i]] *= 1.15;\n                estimated_weights[p[j]] *= 0.85;\n            }\n            // Equal: no change\n        }\n    }\n    \n    // Normalize weights\n    double sum_w = 0.0;\n    for (double w : estimated_weights) sum_w += w;\n    for (double &w : estimated_weights) w = w / sum_w * N;\n    \n    // Second phase: balanced group comparisons\n    int queries_remaining = Q - queries_used;\n    \n    for (int q = 0; q < queries_remaining; ++q) {\n        // Shuffle items to ensure randomness in selection\n        shuffle(p.begin(), p.end(), rng);\n        \n        vector<int> L, R;\n        double sum_L = 0.0;\n        double sum_R = 0.0;\n        \n        // Greedy assignment to balance sums\n        for (int i = 0; i < N; ++i) {\n            int item = p[i];\n            if (sum_L <= sum_R) {\n                L.push_back(item);\n                sum_L += estimated_weights[item];\n            } else {\n                R.push_back(item);\n                sum_R += estimated_weights[item];\n            }\n        }\n        \n        // Ensure both sides are non-empty\n        if (L.empty() && !R.empty()) {\n            L.push_back(R.back());\n            R.pop_back();\n        }\n        if (R.empty() && !L.empty()) {\n            R.push_back(L.back());\n            L.pop_back();\n        }\n        \n        // Output query\n        output_query(L, R);\n        \n        // Read response\n        string res = read_response();\n        \n        // Update weights based on response\n        double diff = sum_L - sum_R;\n        double eta = 0.25 * (1.0 - (double)queries_used / Q); // Decaying learning rate\n        \n        if (res == \"<\") {\n            // L < R\n            if (diff > -1e-9) {\n                double adjustment = eta * max(0.0, diff + 1e-9);\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        } else if (res == \">\") {\n            // L > R\n            if (diff < 1e-9) {\n                double adjustment = eta * max(0.0, -diff + 1e-9);\n                for (int item : L) estimated_weights[item] += adjustment / L.size();\n                for (int item : R) estimated_weights[item] -= adjustment / R.size();\n            }\n        } else if (res == \"=\") {\n            // L = R\n            if (abs(diff) > 1e-9) {\n                double adjustment = eta * diff;\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        }\n        \n        // Ensure weights stay positive\n        for (double &w : estimated_weights) {\n            if (w < 0.1) w = 0.1;\n        }\n        \n        queries_used++;\n    }\n\n    // Partitioning Phase\n    simulate_annealing();\n\n    // Output final assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n\nusing namespace std;\n\n// Global variables to store state\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // pos[v] = {stack_idx, height} (0-indexed stack, 0-indexed height)\nvector<pair<int, int>> operations;\n\n// Function to calculate inversions between a block S and a stack Dest\n// S is a vector of box values in the block (from bottom to top)\n// Dest is the index of the destination stack\n// Returns the number of pairs (u, d) such that u in S, d in stacks[Dest], u > d\nint count_inversions(const vector<int>& S, int dest_idx) {\n    int count = 0;\n    const auto& dest_stack = stacks[dest_idx];\n    for (int u : S) {\n        for (int d : dest_stack) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to calculate inversions between a block S and boxes below v in Source stack\n// v is the box we want to expose (it is below S in the source stack)\n// S is the block above v\nint count_inversions_below(const vector<int>& S, int source_idx, int v) {\n    int count = 0;\n    const auto& source_stack = stacks[source_idx];\n    // Find position of v\n    int v_pos = -1;\n    for (int i = 0; i < source_stack.size(); ++i) {\n        if (source_stack[i] == v) {\n            v_pos = i;\n            break;\n        }\n    }\n    // Iterate boxes below v\n    for (int i = 0; i < v_pos; ++i) {\n        int d = source_stack[i];\n        for (int u : S) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to execute a move\n// Move block starting at box v (and all above it) to dest_stack_idx\n// Returns the number of boxes moved\nint move_block(int v, int dest_stack_idx) {\n    auto [src_idx, h] = pos[v];\n    if (src_idx == dest_stack_idx) return 0;\n    \n    const auto& src_stack = stacks[src_idx];\n    // Identify the block\n    // The block starts at h and goes to top\n    vector<int> block;\n    for (int i = h; i < src_stack.size(); ++i) {\n        block.push_back(src_stack[i]);\n    }\n    \n    // Move to dest\n    for (int u : block) {\n        stacks[dest_stack_idx].push_back(u);\n        pos[u] = {dest_stack_idx, (int)stacks[dest_stack_idx].size() - 1};\n    }\n    \n    // Remove from src\n    for (int i = 0; i < block.size(); ++i) {\n        stacks[src_idx].pop_back();\n    }\n    \n    operations.push_back({v, dest_stack_idx + 1}); // 1-indexed output\n    return block.size();\n}\n\n// Function to remove box v (Op 2)\nvoid remove_box(int v) {\n    auto [src_idx, h] = pos[v];\n    // It must be at the top\n    if (h != (int)stacks[src_idx].size() - 1) {\n        // Should not happen if logic is correct\n        return;\n    }\n    stacks[src_idx].pop_back();\n    operations.push_back({v, 0});\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    pos.resize(N + 1);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Main loop\n    for (int v = 1; v <= N; ++v) {\n        // Check if v is at the top\n        auto [src_idx, h] = pos[v];\n        while (h != (int)stacks[src_idx].size() - 1) {\n            // v is covered. Identify boxes above v.\n            const auto& src_stack = stacks[src_idx];\n            vector<int> boxes_above;\n            for (int i = h + 1; i < src_stack.size(); ++i) {\n                boxes_above.push_back(src_stack[i]);\n            }\n            \n            int k = boxes_above.size();\n            if (k == 0) break; // Should not happen\n\n            // Generate candidates\n            // We try moving suffixes of boxes_above\n            // Suffixes: top 1, top 2, ..., top k (whole block)\n            // To save time, if k is large, we limit suffixes.\n            \n            vector<int> suffix_lengths;\n            if (k <= 5) {\n                for (int len = 1; len <= k; ++len) suffix_lengths.push_back(len);\n            } else {\n                suffix_lengths.push_back(1);\n                suffix_lengths.push_back(2);\n                suffix_lengths.push_back(k);\n            }\n\n            int best_score = 1e9;\n            int best_move_v = -1;\n            int best_dest = -1;\n\n            // Random seed for tie-breaking\n            static mt19937 rng(1337);\n            vector<pair<int, int>> candidates;\n\n            for (int len : suffix_lengths) {\n                // The block to move is the top 'len' boxes of boxes_above\n                // boxes_above is from bottom to top.\n                // So top 'len' boxes are boxes_above[k-len ... k-1]\n                vector<int> S;\n                for (int i = k - len; i < k; ++i) {\n                    S.push_back(boxes_above[i]);\n                }\n                int v_to_move = S.back(); // The bottom-most box of the block being moved\n\n                for (int dest = 0; dest < M; ++dest) {\n                    if (dest == src_idx) continue;\n\n                    // Cost = len + 1\n                    int cost = len + 1;\n\n                    // Delta Potential = New Inversions - Removed Inversions\n                    // New Inversions: pairs (u, d) with u in S, d in stacks[dest], u > d\n                    int new_inv = count_inversions(S, dest);\n                    \n                    // Removed Inversions: pairs (u, d) with u in S, d in stacks[src_idx] below v, u > d\n                    int removed_inv = count_inversions_below(S, src_idx, v);\n\n                    int score = cost + (new_inv - removed_inv);\n\n                    if (score < best_score) {\n                        best_score = score;\n                        candidates.clear();\n                        candidates.push_back({v_to_move, dest});\n                    } else if (score == best_score) {\n                        candidates.push_back({v_to_move, dest});\n                    }\n                }\n            }\n\n            if (candidates.empty()) {\n                // Fallback: move top 1 box to random stack\n                int top_box = boxes_above.back();\n                int dest = src_idx;\n                while (dest == src_idx) dest = rng() % M;\n                move_block(top_box, dest);\n            } else {\n                int idx = rng() % candidates.size();\n                move_block(candidates[idx].first, candidates[idx].second);\n            }\n            \n            // Update pos[v] and h after move\n            // pos[v] is updated inside move_block\n            // But we need to re-check if v is at top\n            auto [new_src, new_h] = pos[v];\n            src_idx = new_src;\n            h = new_h;\n        }\n\n        // Now v should be at top\n        remove_box(v);\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring route;\nvector<pair<int, int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\nstring dir_chars = \"RDLU\";\n\nbool can_move(int i, int j, int di, int dj) {\n    int ni = i + di, nj = j + dj;\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // h has N-1 rows (0 to N-2), each with N characters\n    // v has N rows (0 to N-1), each with N-1 characters\n    if (di == 1) return h[i][j] == '0';      // moving down: check h[i][j]\n    if (di == -1) return h[ni][j] == '0';    // moving up: check h[i-1][j]\n    if (dj == 1) return v[i][j] == '0';      // moving right: check v[i][j]\n    if (dj == -1) return v[i][nj] == '0';    // moving left: check v[i][j-1]\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    // FIX: h has N-1 rows, v has N rows\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    d.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    visited.assign(N, vector<bool>(N, false));\n    \n    // Sort neighbors by dirtiness (descending) for prioritization\n    auto get_neighbors = [&](int i, int j) {\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !visited[ni][nj]) {\n                if (can_move(i, j, di, dj)) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        return neighbors;\n    };\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        auto neighbors = get_neighbors(i, j);\n        for (auto& [dirt, dir] : neighbors) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (!visited[ni][nj] && can_move(i, j, di, dj)) {\n                route += dir_chars[dir];\n                dfs(ni, nj);\n                route += dir_chars[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Validate the route\n    int cur_i = 0, cur_j = 0;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        \n        if (!can_move(cur_i, cur_j, di, dj)) {\n            cerr << \"Invalid move at position (\" << cur_i << \", \" << cur_j << \") with direction \" << c << endl;\n            return 1;\n        }\n        \n        cur_i += di;\n        cur_j += dj;\n    }\n    \n    // Verify we return to (0, 0)\n    if (cur_i != 0 || cur_j != 0) {\n        cerr << \"Route does not return to (0, 0)\" << endl;\n        return 1;\n    }\n    \n    // Verify all squares are visited\n    visited.assign(N, vector<bool>(N, false));\n    cur_i = 0, cur_j = 0;\n    visited[0][0] = true;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        cur_i += di;\n        cur_j += dj;\n        visited[cur_i][cur_j] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) {\n                cerr << \"Square (\" << i << \", \" << j << \") not visited\" << endl;\n                return 1;\n            }\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, M;\nint start_i, start_j;\nvector<string> grid(15);\nvector<string> targets;\nvector<pair<int, int>> char_pos[26];\nvector<pair<int, int>> path;\nint total_cost;\n\n// Precomputed costs\nint cost_from_start[200];\nint cost_between[200][200];\nint last_pos_i[200];\nint last_pos_j[200];\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nint move_cost(int i1, int j1, int i2, int j2) {\n    return manhattan(i1, j1, i2, j2) + 1;\n}\n\npair<int, int> find_nearest(char c, int curr_i, int curr_j) {\n    const vector<pair<int, int>>& positions = char_pos[c - 'A'];\n    if (positions.empty()) return {0, 0};\n    \n    int best_dist = 1e9;\n    pair<int, int> best_pos = {-1, -1};\n    for (auto& p : positions) {\n        int d = manhattan(curr_i, curr_j, p.first, p.second);\n        if (d < best_dist) {\n            best_dist = d;\n            best_pos = p;\n        }\n    }\n    return best_pos;\n}\n\nvoid precompute_costs() {\n    for (int i = 0; i < M; i++) {\n        int ci = start_i, cj = start_j;\n        int cost = 0;\n        for (char c : targets[i]) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            cost += move_cost(ci, cj, pos.first, pos.second);\n            ci = pos.first;\n            cj = pos.second;\n        }\n        cost_from_start[i] = cost;\n        last_pos_i[i] = ci;\n        last_pos_j[i] = cj;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int ci = last_pos_i[i], cj = last_pos_j[i];\n            int cost = 0;\n            for (char c : targets[j]) {\n                pair<int, int> pos = find_nearest(c, ci, cj);\n                cost += move_cost(ci, cj, pos.first, pos.second);\n                ci = pos.first;\n                cj = pos.second;\n            }\n            cost_between[i][j] = cost;\n        }\n    }\n}\n\nint calculate_cost(const vector<int>& order) {\n    int cost = cost_from_start[order[0]];\n    for (int i = 1; i < M; i++) {\n        cost += cost_between[order[i-1]][order[i]];\n    }\n    return cost;\n}\n\nvector<pair<int, int>> generate_path(const vector<int>& order) {\n    vector<pair<int, int>> result;\n    int ci = start_i, cj = start_j;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            result.push_back(pos);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return result;\n}\n\n// Calculate cost change from swapping positions i and j\nint calc_swap_delta(const vector<int>& order, int i, int j) {\n    if (i == j) return 0;\n    \n    int delta = 0;\n    \n    // Cost before: order[i-1]->order[i]->order[i+1] and order[j-1]->order[j]->order[j+1]\n    // Cost after:  order[i-1]->order[j]->order[i+1] and order[j-1]->order[i]->order[j+1]\n    \n    if (i > 0) {\n        delta -= cost_between[order[i-1]][order[i]];\n        delta += cost_between[order[i-1]][order[j]];\n    }\n    if (i + 1 < M) {\n        delta -= cost_between[order[i]][order[i+1]];\n        delta += cost_between[order[j]][order[i+1]];\n    }\n    if (j > 0) {\n        delta -= cost_between[order[j-1]][order[j]];\n        delta += cost_between[order[j-1]][order[i]];\n    }\n    if (j + 1 < M) {\n        delta -= cost_between[order[j]][order[j+1]];\n        delta += cost_between[order[i]][order[j+1]];\n    }\n    \n    return delta;\n}\n\nvoid optimize() {\n    precompute_costs();\n    \n    vector<int> best_order(M);\n    int best_cost = 1e9;\n    \n    // Multiple restarts with different strategies\n    int restarts = 8;\n    for (int r = 0; r < restarts; r++) {\n        vector<int> order(M);\n        \n        // Different initialization strategies\n        if (r == 0) {\n            // Sequential order\n            iota(order.begin(), order.end(), 0);\n        } else if (r == 1) {\n            // Random shuffle\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine(r * 1000 + 42));\n        } else {\n            // Greedy nearest neighbor\n            vector<bool> used(M, false);\n            int curr = rand() % M;\n            order[0] = curr;\n            used[curr] = true;\n            \n            int ci = last_pos_i[curr], cj = last_pos_j[curr];\n            for (int pos = 1; pos < M; pos++) {\n                int best_next = -1;\n                int best_cost = 1e9;\n                for (int next = 0; next < M; next++) {\n                    if (!used[next]) {\n                        int cost = cost_between[curr][next];\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_next = next;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    order[pos] = best_next;\n                    used[best_next] = true;\n                    curr = best_next;\n                }\n            }\n        }\n        \n        int current_cost = calculate_cost(order);\n        \n        // Greedy local search with swaps\n        int greedy_iters = 2000;\n        int no_improve = 0;\n        \n        while (greedy_iters-- > 0 && no_improve < 30) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            // Try random swaps\n            for (int iter = 0; iter < 100; iter++) {\n                int i = rand() % M;\n                int j = rand() % M;\n                if (i == j) continue;\n                \n                int delta = calc_swap_delta(order, i, j);\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                current_cost += best_delta;\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        }\n        \n        // Simulated annealing\n        double temp = 80.0;\n        double decay = 0.9990;\n        int sa_iters = 12000;\n        \n        for (int iter = 0; iter < sa_iters; iter++) {\n            int i = rand() % M;\n            int j = rand() % M;\n            if (i == j) continue;\n            \n            int delta = calc_swap_delta(order, i, j);\n            \n            if (delta <= 0 || (double)rand() / RAND_MAX < exp(-delta / temp)) {\n                swap(order[i], order[j]);\n                current_cost += delta;\n            }\n            \n            temp *= decay;\n        }\n        \n        // Final greedy refinement\n        for (int iter = 0; iter < 500; iter++) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    int delta = calc_swap_delta(order, i, j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                current_cost += best_delta;\n            } else {\n                break;\n            }\n        }\n        \n        if (current_cost < best_cost) {\n            best_cost = current_cost;\n            best_order = order;\n        }\n    }\n    \n    path = generate_path(best_order);\n    total_cost = calculate_cost(best_order);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> M >> start_i >> start_j;\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_pos[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    memset(cost_from_start, 0, sizeof(cost_from_start));\n    memset(cost_between, 0, sizeof(cost_between));\n    memset(last_pos_i, 0, sizeof(last_pos_i));\n    memset(last_pos_j, 0, sizeof(last_pos_j));\n    \n    optimize();\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables\nint N, M;\ndouble epsilon;\nstruct Shape {\n    int id;\n    int area;\n    vector<pair<int, int>> cells;\n};\nvector<Shape> shapes;\nmap<pair<int, int>, int> drilled_values;\nbool solved = false;\n\n// Random number generator\nmt19937 rng(1337);\n\n// Function to query a single cell\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    int v;\n    cin >> v;\n    drilled_values[{r, c}] = v;\n    return v;\n}\n\n// Function to query a set of cells\nint divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Submit answer\nvoid submit(const vector<pair<int, int>>& cells) {\n    cout << \"a \" << cells.size();\n    for (auto p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) {\n        solved = true;\n        exit(0);\n    }\n}\n\n// Check if a shape at position (r, c) covers (i, j)\nbool covers(const Shape& s, int r, int c, int i, int j) {\n    for (auto p : s.cells) {\n        if (r + p.first == i && c + p.second == j) return true;\n    }\n    return false;\n}\n\n// Calculate predicted v(i, j) for a configuration\nint predict_v(const vector<pair<int, int>>& config, int i, int j) {\n    int count = 0;\n    for (int k = 0; k < M; ++k) {\n        int r = config[k].first;\n        int c = config[k].second;\n        if (covers(shapes[k], r, c, i, j)) count++;\n    }\n    return count;\n}\n\n// Check if a configuration is consistent with drilled values\nbool is_consistent(const vector<pair<int, int>>& config) {\n    for (auto const& [pos, val] : drilled_values) {\n        int i = pos.first;\n        int j = pos.second;\n        int pred = predict_v(config, i, j);\n        if (pred != val) return false;\n    }\n    return true;\n}\n\n// Backtracking solver\n// candidates[k] is a list of possible positions for shape k\n// config[k] stores the chosen position for shape k\nbool solve(int k, vector<pair<int, int>>& config, vector<vector<pair<int, int>>>& candidates) {\n    if (k == M) {\n        return is_consistent(config);\n    }\n    \n    // Try all candidates for shape k\n    for (auto pos : candidates[k]) {\n        config[k] = pos;\n        // Pruning: Check consistency with drilled cells so far\n        bool possible = true;\n        for (auto const& [p, val] : drilled_values) {\n            int i = p.first;\n            int j = p.second;\n            // Calculate partial sum for this shape\n            int current_contribution = covers(shapes[k], pos.first, pos.second, i, j) ? 1 : 0;\n            // We need to check if it's possible to reach 'val' with remaining shapes\n            // This is a bit expensive to check fully, so let's just check exact match for drilled cells\n            // Actually, we can check if current config so far is consistent with drilled cells\n            // But we don't know other shapes yet.\n            // So we just check if the current shape doesn't violate any 0 constraints\n            if (val == 0 && current_contribution == 1) {\n                possible = false;\n                break;\n            }\n        }\n        if (!possible) continue;\n\n        if (solve(k + 1, config, candidates)) return true;\n    }\n    return false;\n}\n\n// Collect all possible positions for each shape\nvoid generate_candidates(vector<vector<pair<int, int>>>& candidates) {\n    candidates.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& s = shapes[k];\n        int max_r = N - 1;\n        int max_c = N - 1;\n        // Find bounding box of shape to determine max valid top-left\n        int s_max_r = 0, s_max_c = 0;\n        for (auto p : s.cells) {\n            s_max_r = max(s_max_r, p.first);\n            s_max_c = max(s_max_c, p.second);\n        }\n        for (int r = 0; r <= N - 1 - s_max_r; ++r) {\n            for (int c = 0; c <= N - 1 - s_max_c; ++c) {\n                // Check consistency with drilled cells\n                bool ok = true;\n                for (auto const& [pos, val] : drilled_values) {\n                    if (val == 0 && covers(s, r, c, pos.first, pos.second)) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) {\n                    candidates[k].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\n// Recursive region processing\nvoid process_region(int r1, int c1, int r2, int c2) {\n    int h = r2 - r1 + 1;\n    int w = c2 - c1 + 1;\n    int area = h * w;\n    \n    if (area <= 16) {\n        for (int r = r1; r <= r2; ++r) {\n            for (int c = c1; c <= c2; ++c) {\n                if (drilled_values.find({r, c}) == drilled_values.end()) {\n                    drill(r, c);\n                }\n            }\n        }\n        return;\n    }\n\n    // Query region\n    vector<pair<int, int>> cells;\n    for (int r = r1; r <= r2; ++r) {\n        for (int c = c1; c <= c2; ++c) {\n            cells.push_back({r, c});\n        }\n    }\n    \n    int k = cells.size();\n    int total_obs = 0;\n    int Q = 10; // Number of queries\n    for (int q = 0; q < Q; ++q) {\n        total_obs += divine(cells);\n    }\n    double avg_obs = (double)total_obs / Q;\n    \n    // Estimate true sum\n    // mu = k*eps + v*(1-2*eps)\n    // v_est = (avg_obs - k*eps) / (1-2*eps)\n    double v_est = (avg_obs - k * epsilon) / (1.0 - 2.0 * epsilon);\n    \n    // Threshold for \"empty\"\n    // If v_est is very small, assume empty.\n    // To be safe, we require v_est < 0.2 (since min non-zero is 1)\n    // But noise can make it negative.\n    // Let's say if v_est < 0.5, suspect empty.\n    if (v_est < 0.5) {\n        // Suspected empty. Verify with 1 drill.\n        int vr = r1 + (rng() % h);\n        int vc = c1 + (rng() % w);\n        int val = drill(vr, vc);\n        if (val > 0) {\n            // Not empty, recurse\n            int mr = (r1 + r2) / 2;\n            int mc = (c1 + c2) / 2;\n            process_region(r1, c1, mr, mc);\n            process_region(r1, c1, mr, c2); // Overlap? No, split properly\n            process_region(r1, c1, mr, mc); // Wait, standard quad split\n            // Correct split:\n            // Top-Left, Top-Right, Bottom-Left, Bottom-Right\n            // To avoid overlap, split at mid\n            int mid_r = (r1 + r2) / 2;\n            int mid_c = (c1 + c2) / 2;\n            process_region(r1, c1, mid_r, mid_c);\n            process_region(r1, mid_c + 1, mid_r, c2);\n            process_region(mid_r + 1, c1, r2, mid_c);\n            process_region(mid_r + 1, mid_c + 1, r2, c2);\n        } else {\n            // Assume empty, do nothing\n        }\n    } else {\n        // Definitely has oil, recurse\n        int mid_r = (r1 + r2) / 2;\n        int mid_c = (c1 + c2) / 2;\n        process_region(r1, c1, mid_r, mid_c);\n        process_region(r1, mid_c + 1, mid_r, c2);\n        process_region(mid_r + 1, c1, r2, mid_c);\n        process_region(mid_r + 1, mid_c + 1, r2, c2);\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> epsilon;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        shapes[k].id = k;\n        int d;\n        cin >> d;\n        shapes[k].area = d;\n        shapes[k].cells.resize(d);\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n        }\n    }\n\n    // Heuristic search for regions with oil\n    process_region(0, 0, N - 1, N - 1);\n\n    // Solve for configuration\n    vector<vector<pair<int, int>>> candidates;\n    generate_candidates(candidates);\n    \n    // Sort shapes by number of candidates (MRV)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return candidates[a].size() < candidates[b].size();\n    });\n\n    // We need to map back to original indices\n    // Let's just use the sorted order in recursion\n    // But the config vector needs to be indexed by original shape index\n    // Let's modify solve to take shape index from order\n    \n    vector<pair<int, int>> config(M);\n    // We need to re-implement solve to use the order\n    // Or just permute candidates\n    \n    // Let's create a permuted candidates list\n    vector<vector<pair<int, int>>> perm_candidates(M);\n    for(int i=0; i<M; ++i) perm_candidates[i] = candidates[order[i]];\n    \n    // We need a helper solve that takes the permuted candidates\n    // But predict_v uses original shape indices.\n    // So we need to keep track of which original shape we are placing.\n    \n    // Let's rewrite solve to accept a mapping\n    // Actually, simpler: just use the original candidates but pick the shape with fewest candidates first.\n    // We can do this by reordering the recursion.\n    \n    // Let's implement a custom solver\n    vector<int> shape_order = order;\n    vector<pair<int, int>> final_config(M);\n    \n    // We need to pass the current depth and the shape index we are deciding\n    // But since we reordered, we need to map back.\n    // Let's just use a lambda or a separate function with state\n    \n    // To keep it simple, let's just use the original candidates but sort them by size\n    // and pass the permutation to the solver.\n    \n    // Re-implementing solve with permutation\n    // We will fill final_config based on shape_order[k]\n    \n    auto solve_perm = [&](auto&& self, int k) -> bool {\n        if (k == M) {\n            return is_consistent(final_config);\n        }\n        int shape_idx = shape_order[k];\n        for (auto pos : candidates[shape_idx]) {\n            final_config[shape_idx] = pos;\n            // Pruning\n            bool possible = true;\n            for (auto const& [p, val] : drilled_values) {\n                if (val == 0 && covers(shapes[shape_idx], pos.first, pos.second, p.first, p.second)) {\n                    possible = false;\n                    break;\n                }\n            }\n            if (!possible) continue;\n            \n            if (self(self, k + 1)) return true;\n        }\n        return false;\n    };\n\n    if (solve_perm(solve_perm, 0)) {\n        // Found a configuration\n        // Collect all cells with v > 0\n        vector<pair<int, int>> result;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (predict_v(final_config, i, j) > 0) {\n                    result.push_back({i, j});\n                }\n            }\n        }\n        submit(result);\n    } else {\n        // Failed to find configuration.\n        // This might mean we missed some oil (false empty).\n        // We can try to drill more cells.\n        // But to keep it simple for the contest, we can just drill all remaining cells.\n        // Or submit an empty set? No, that's wrong.\n        // Let's drill all cells that are not drilled yet.\n        // This ensures we find the answer, but costs more.\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drilled_values.find({i, j}) == drilled_values.end()) {\n                    drill(i, j);\n                }\n            }\n        }\n        // Retry solving\n        generate_candidates(candidates);\n        if (solve_perm(solve_perm, 0)) {\n            vector<pair<int, int>> result;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (predict_v(final_config, i, j) > 0) {\n                        result.push_back({i, j});\n                    }\n                }\n            }\n            submit(result);\n        } else {\n            // Still failed? Fallback to all drilled cells with v>0\n            vector<pair<int, int>> result;\n            for (auto const& [pos, val] : drilled_values) {\n                if (val > 0) result.push_back(pos);\n            }\n            submit(result);\n        }\n    }\n\n    return 0;\n}","ahc031":"```cpp\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <iomanip>\n#include <queue>\n\nusing namespace std;\n\n// Rectangle structure\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\n// Problem parameters\nint W, D, N;\nvector<vector<int>> a;  // desired areas\nvector<vector<Rect>> rects;  // assigned rectangles\n\n// Check if rectangles overlap\nbool checkOverlap(const vector<Rect>& day_rects) {\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!(day_rects[i].i1 <= day_rects[j].i0 ||\n                  day_rects[i].i0 >= day_rects[j].i1 ||\n                  day_rects[i].j1 <= day_rects[j].j0 ||\n                  day_rects[i].j0 >= day_rects[j].j1)) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\n// Calculate area cost for a day\nlong long calculateAreaCost(int d) {\n    long long cost = 0;\n    for (int k = 0; k < N; k++) {\n        int actual = rects[d][k].area();\n        if (actual < a[d][k]) {\n            cost += 100LL * (a[d][k] - actual);\n        }\n    }\n    return cost;\n}\n\n// Calculate partition segments for a day\nvector<vector<int>> getHorizontalSegments(int d) {\n    vector<vector<int>> H(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) H[i0][j] = 1;\n            if (i1 > 0 && i1 < W) H[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) H[i][j0] = 1;\n            if (j1 > 0 && j1 < W) H[i][j1] = 1;\n        }\n    }\n    return H;\n}\n\nvector<vector<int>> getVerticalSegments(int d) {\n    vector<vector<int>> V(W, vector<int>(W, 0));\n    for (int k = 0; k < N; k++) {\n        int i0 = rects[d][k].i0, i1 = rects[d][k].i1;\n        int j0 = rects[d][k].j0, j1 = rects[d][k].j1;\n        // Top and bottom edges\n        for (int j = j0; j < j1; j++) {\n            if (i0 > 0 && i0 < W) V[i0][j] = 1;\n            if (i1 > 0 && i1 < W) V[i1][j] = 1;\n        }\n        // Left and right edges\n        for (int i = i0; i < i1; i++) {\n            if (j0 > 0 && j0 < W) V[i][j0] = 1;\n            if (j1 > 0 && j1 < W) V[i][j1] = 1;\n        }\n    }\n    return V;\n}\n\nlong long calculatePartitionCost(int d) {\n    if (d == 0) return 0;\n    long long cost = 0;\n    auto H_prev = getHorizontalSegments(d - 1);\n    auto H_curr = getHorizontalSegments(d);\n    auto V_prev = getVerticalSegments(d - 1);\n    auto V_curr = getVerticalSegments(d);\n    \n    for (int i = 1; i < W; i++) {\n        for (int j = 0; j < W; j++) {\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; i++) {\n        for (int j = 1; j < W; j++) {\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n        }\n    }\n    return cost;\n}\n\nlong long calculateTotalCost() {\n    long long total = 0;\n    for (int d = 0; d < D; d++) {\n        total += calculateAreaCost(d);\n        total += calculatePartitionCost(d);\n    }\n    return total;\n}\n\n// Initialize with better packing strategy\nvoid initializeSolution() {\n    rects.resize(D);\n    for (int d = 0; d < D; d++) {\n        rects[d].resize(N);\n        \n        // Sort reservations by area (descending) for better packing\n        vector<pair<int, int>> sorted_idx(N);\n        for (int k = 0; k < N; k++) sorted_idx[k] = {a[d][k], k};\n        sort(sorted_idx.rbegin(), sorted_idx.rend());\n        \n        // Use a simple row-based packing\n        int current_i = 0, current_j = 0;\n        for (int idx = 0; idx < N; idx++) {\n            int k = sorted_idx[idx].second;\n            int desired = a[d][k];\n            \n            // Calculate dimensions to minimize perimeter\n            int best_h = 1, best_w = desired;\n            int best_perimeter = 2 * (1 + desired);\n            for (int h = 1; h * h <= desired; h++) {\n                if (desired % h == 0) {\n                    int w = desired / h;\n                    int perimeter = 2 * (h + w);\n                    if (perimeter < best_perimeter) {\n                        best_perimeter = perimeter;\n                        best_h = h;\n                        best_w = w;\n                    }\n                }\n            }\n            \n            // Try to fit in current row\n            if (current_j + best_w <= W) {\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            } else {\n                // Move to next row\n                current_i += best_h;\n                current_j = 0;\n                if (current_i + best_h > W) {\n                    // Need to reorganize - use simpler approach\n                    current_i = 0;\n                    current_j = 0;\n                    for (int x = 0; x < idx; x++) {\n                        int pk = sorted_idx[x].second;\n                        int ph = rects[d][pk].i1 - rects[d][pk].i0;\n                        current_i += ph;\n                        if (current_i >= W) {\n                            current_i = 0;\n                            current_j = 0;\n                        }\n                    }\n                }\n                rects[d][k] = {current_i, current_j, current_i + best_h, current_j + best_w};\n                current_j += best_w;\n            }\n        }\n    }\n}\n\n// Simulated Annealing optimization\nvoid optimizeSolution() {\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    uniform_int_distribution<int> int_dist(0, W - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double initial_temp = 5000.0;\n    const double cooling_rate = 0.998;\n    const double final_temp = 0.1;\n    \n    double temp = initial_temp;\n    long long current_cost = calculateTotalCost();\n    long long best_cost = current_cost;\n    \n    while (temp > final_temp) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > 2.8) break;  // Leave margin for output\n        \n        // Randomly select a day and rectangle\n        int d = dist(gen) * D;\n        int k = dist(gen) * N;\n        \n        Rect original = rects[d][k];\n        int attempts = 0;\n        bool valid = false;\n        Rect new_rect = original;\n        \n        while (attempts < 200 && !valid) {\n            int h = original.i1 - original.i0;\n            int w = original.j1 - original.j0;\n            \n            // Random perturbation with bias toward stability\n            int di = (dist(gen) * 15 - 7);\n            int dj = (dist(gen) * 15 - 7);\n            int dh = (dist(gen) * 8 - 4);\n            int dw = (dist(gen) * 8 - 4);\n            \n            int ni0 = max(0, min(W - 1, original.i0 + di));\n            int nj0 = max(0, min(W - 1, original.j0 + dj));\n            int ni1 = max(ni0 + 1, min(W, original.i1 + dh));\n            int nj1 = max(nj0 + 1, min(W, original.j1 + dw));\n            \n            new_rect = {ni0, nj0, ni1, nj1};\n            \n            if (!checkOverlap(rects[d])) {\n                valid = true;\n            } else {\n                attempts++;\n            }\n        }\n        \n        rects[d][k] = new_rect;\n        long long new_cost = calculateTotalCost();\n        double delta = new_cost - current_cost;\n        \n        if (delta < 0 || dist(gen) < exp(-delta / temp)) {\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n            }\n        } else {\n            rects[d][k] = original;\n        }\n        \n        temp *= cooling_rate;\n    }\n}\n\n// Local search for area satisfaction\nvoid improveAreaSatisfaction() {\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int current_area = rects[d][k].area();\n            if (current_area < a[d][k]) {\n                int needed = a[d][k] - current_area;\n                int h = rects[d][k].i1 - rects[d][k].i0;\n                int w = rects[d][k].j1 - rects[d][k].j0;\n                \n                // Try expanding in different directions\n                int[] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};\n                for (int dir = 0; dir < 4; dir++) {\n                    int di = dirs[dir][0];\n                    int dj = dirs[dir][1];\n                    \n                    int ni0 = rects[d][k].i0 + di * h;\n                    int nj0 = rects[d][k].j0 + dj * w;\n                    int ni1 = rects[d][k].i1 + di * h;\n                    int nj1 = rects[d][k].j1 + dj * w;\n                    \n                    if (ni0 >= 0 && ni1 <= W && nj0 >= 0 && nj1 <= W) {\n                        if (!checkOverlap(rects[d])) {\n                            rects[d][k] = {ni0, nj0, ni1, nj1};\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Try to reduce partition costs by aligning with previous day\nvoid improvePartitionStability() {\n    for (int d = 1; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            // Try to match previous day's partition pattern\n            if (d - 1 >= 0) {\n                int best_cost = 1e18;\n                Rect best_rect = rects[d][k];\n                \n                // Try small adjustments\n                for (int di = -3; di <= 3; di++) {\n                    for (int dj = -3; dj <= 3; dj++) {\n                        int ni0 = max(0, min(W - 1, rects[d][k].i0 + di));\n                        int nj0 = max(0, min(W - 1, rects[d][k].j0 + dj));\n                        int ni1 = max(ni0 + 1, min(W, rects[d][k].i1 + di));\n                        int nj1 = max(nj0 + 1, min(W, rects[d][k].j1 + dj));\n                        \n                        Rect test_rect = {ni0, nj0, ni1, nj1};\n                        if (!checkOverlap(rects[d])) {\n                            long long test_cost = calculateTotalCost();\n                            if (test_cost < best_cost) {\n                                best_cost = test_cost;\n                                best_rect = test_rect;\n                            }\n                        }\n                    }\n                }\n                rects[d][k] = best_rect;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n    \n    // Initialize solution\n    initializeSolution();\n    \n    // Optimize\n    optimizeSolution();\n    \n    // Final improvements\n    improveAreaSatisfaction();\n    improvePartitionStability();\n    \n    // Output\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[d][k].i0 << \" \" << rects[d][k].j0 << \" \"\n                 << rects[d][k].i1 << \" \" << rects[d][k].j1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst long long MOD = 998244353;\n\n// Structures\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\n// Global variables\nint initial_board[N][N];\nint board[N][N];\nint stamps[M][3][3];\nlong long best_score;\nvector<Op> best_ops;\n\n// Random number generator\nmt19937_64 rng;\n\n// Function to calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += (board[i][j] % MOD);\n        }\n    }\n    return score;\n}\n\n// Function to apply an operation\nvoid apply_op(const Op& op, int val) {\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            board[op.p + i][op.q + j] += val * stamps[op.m][i][j];\n        }\n    }\n}\n\n// Function to calculate delta score for an operation\nlong long get_delta_score(const Op& op, int val) {\n    long long delta = 0;\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            int r = op.p + i;\n            int c = op.q + j;\n            long long old_val = board[r][c] % MOD;\n            long long new_val = (board[r][c] + val * stamps[op.m][i][j]) % MOD;\n            delta += new_val - old_val;\n        }\n    }\n    return delta;\n}\n\n// Solver class to manage state for each restart\nstruct Solver {\n    vector<Op> ops;\n    long long score;\n    double temperature;\n    int iterations;\n    \n    Solver() : iterations(0), temperature(1e9) {}\n    \n    void init_random() {\n        ops.clear();\n        ops.reserve(K);\n        uniform_int_distribution<int> dist_m(0, M - 1);\n        uniform_int_distribution<int> dist_p(0, N - 3);\n        uniform_int_distribution<int> dist_q(0, N - 3);\n        \n        for (int i = 0; i < K; ++i) {\n            ops.push_back({dist_m(rng), dist_p(rng), dist_q(rng)});\n        }\n        \n        reset_board();\n        for (const auto& op : ops) {\n            apply_op(op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void init_greedy() {\n        ops.clear();\n        ops.reserve(K);\n        \n        reset_board();\n        \n        // Greedy initialization - try to find best operations\n        for (int iter = 0; iter < K; ++iter) {\n            long long max_delta = -1e18;\n            Op best_op = {0, 0, 0};\n            \n            // Sample a subset of operations to find a good one\n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            \n            for (int sample = 0; sample < 200; ++sample) {\n                Op op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n                long long delta = get_delta_score(op, 1);\n                if (delta > max_delta) {\n                    max_delta = delta;\n                    best_op = op;\n                }\n            }\n            \n            ops.push_back(best_op);\n            apply_op(best_op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void reset_board() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                board[i][j] = initial_board[i][j];\n            }\n        }\n    }\n    \n    void step() {\n        iterations++;\n        \n        // Select a random operation index to change\n        uniform_int_distribution<int> dist_idx(0, K - 1);\n        int idx = dist_idx(rng);\n        Op old_op = ops[idx];\n        \n        // Decide move type with adaptive probabilities\n        uniform_real_distribution<double> dist_type(0.0, 1.0);\n        double r = dist_type(rng);\n        \n        Op new_op = old_op;\n        \n        if (r < 0.05) {\n            // 5%: Full random replacement\n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            new_op.m = dist_m(rng);\n            new_op.p = dist_p(rng);\n            new_op.q = dist_q(rng);\n        } else if (r < 0.25) {\n            // 20%: Change stamp type\n            uniform_real_distribution<double> dist_m_change(0.0, 1.0);\n            if (dist_m_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_m(0, M - 1);\n                new_op.m = dist_m(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.m = (old_op.m + delta + M) % M;\n            }\n        } else if (r < 0.50) {\n            // 25%: Change p position\n            uniform_real_distribution<double> dist_p_change(0.0, 1.0);\n            if (dist_p_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                new_op.p = dist_p(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta));\n            }\n        } else if (r < 0.75) {\n            // 25%: Change q position\n            uniform_real_distribution<double> dist_q_change(0.0, 1.0);\n            if (dist_q_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.q = max(0, min(N - 3, old_op.q + delta));\n            }\n        } else {\n            // 25%: Change both p and q\n            uniform_real_distribution<double> dist_pq_change(0.0, 1.0);\n            if (dist_pq_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.p = dist_p(rng);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta_p = (rng() % 3) - 1;\n                int delta_q = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta_p));\n                new_op.q = max(0, min(N - 3, old_op.q + delta_q));\n            }\n        }\n        \n        // Calculate delta\n        long long delta = 0;\n        \n        // Remove old op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = old_op.p + i;\n                int c = old_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                if (temp_val < 0) temp_val += MOD;\n                delta += temp_val - old_val;\n            }\n        }\n        \n        // Add new op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = new_op.p + i;\n                int c = new_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Acceptance probability\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            uniform_real_distribution<double> dist_prob(0.0, 1.0);\n            double prob = exp(delta / temperature);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            ops[idx] = new_op;\n            // Apply the change to the board\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = old_op.p + i;\n                    int c = old_op.q + j;\n                    board[r][c] -= stamps[old_op.m][i][j];\n                }\n            }\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = new_op.p + i;\n                    int c = new_op.q + j;\n                    board[r][c] += stamps[new_op.m][i][j];\n                }\n            }\n            score += delta;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_ops = ops;\n            }\n        }\n        \n        // Cool down\n        temperature *= 0.9998;\n        if (temperature < 1e-9) temperature = 1e-9;\n    }\n    \n    void local_search() {\n        // Final local search to fine-tune\n        int improved = 1;\n        while (improved && iterations < K * 10) {\n            improved = 0;\n            \n            for (int idx = 0; idx < K; ++idx) {\n                Op old_op = ops[idx];\n                \n                // Try all possible changes for this operation\n                for (int sm = 0; sm < M; ++sm) {\n                    for (int sp = 0; sp <= N - 3; ++sp) {\n                        for (int sq = 0; sq <= N - 3; ++sq) {\n                            if (sm == old_op.m && sp == old_op.p && sq == old_op.q) continue;\n                            \n                            Op new_op = {sm, sp, sq};\n                            \n                            // Calculate delta\n                            long long delta = 0;\n                            for (int i = 0; i < 3; ++i) {\n                                for (int j = 0; j < 3; ++j) {\n                                    int r = old_op.p + i;\n                                    int c = old_op.q + j;\n                                    long long old_val = board[r][c] % MOD;\n                                    long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                                    if (temp_val < 0) temp_val += MOD;\n                                    delta += temp_val - old_val;\n                                }\n                            }\n                            for (int i = 0; i < 3; ++i) {\n                                for (int j = 0; j < 3; ++j) {\n                                    int r = new_op.p + i;\n                                    int c = new_op.q + j;\n                                    long long old_val = board[r][c] % MOD;\n                                    long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                                    delta += new_val - old_val;\n                                }\n                            }\n                            \n                            if (delta > 0) {\n                                // Apply the change\n                                for (int i = 0; i < 3; ++i) {\n                                    for (int j = 0; j < 3; ++j) {\n                                        int r = old_op.p + i;\n                                        int c = old_op.q + j;\n                                        board[r][c] -= stamps[old_op.m][i][j];\n                                    }\n                                }\n                                for (int i = 0; i < 3; ++i) {\n                                    for (int j = 0; j < 3; ++j) {\n                                        int r = new_op.p + i;\n                                        int c = new_op.q + j;\n                                        board[r][c] += stamps[new_op.m][i][j];\n                                    }\n                                }\n                                ops[idx] = new_op;\n                                score += delta;\n                                improved = 1;\n                                iterations++;\n                                \n                                if (score > best_score) {\n                                    best_score = score;\n                                    best_ops = ops;\n                                }\n                                \n                                // Break and restart search after improvement\n                                goto next_idx;\n                            }\n                        }\n                    }\n                }\n                next_idx:;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    // Read board\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> board[i][j];\n            initial_board[i][j] = board[i][j];\n        }\n    }\n\n    // Read stamps\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            for (int l = 0; l < 3; ++l) {\n                cin >> stamps[i][j][l];\n            }\n        }\n    }\n\n    best_score = -1;\n    best_ops.clear();\n\n    // Time management\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1950); // Leave 50ms for output\n    \n    Solver solver;\n    int restart_count = 0;\n    \n    // Multiple restarts with mixed initialization\n    while (chrono::steady_clock::now() < end_time) {\n        restart_count++;\n        \n        // Alternate between random and greedy initialization\n        if (restart_count % 2 == 1) {\n            solver.init_greedy();\n        } else {\n            solver.init_random();\n        }\n        \n        // Run SA\n        while (chrono::steady_clock::now() < end_time && solver.temperature > 1e-9) {\n            solver.step();\n            if (solver.temperature < 1e-9) break;\n        }\n        \n        // Final local search\n        solver.local_search();\n    }\n\n    // Output best solution\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int INF = 1e9;\n\n// Container ID\nconst int EMPTY = -1;\n\nstruct Crane {\n    int id;\n    int x, y;\n    int holding; // Container ID or EMPTY\n    bool is_large;\n    bool active;\n};\n\nstruct State {\n    int grid[N][N]; // Container IDs\n    vector<Crane> cranes;\n    vector<vector<int>> input_queue; // input_queue[i] = list of containers for row i\n    vector<int> dispatch_expected; // dispatch_expected[i] = next expected container for row i\n    vector<vector<int>> dispatch_order; // To calculate M1 later if needed, but heuristic focuses on current state\n    int turn;\n    int dispatched_count;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = EMPTY;\n            input_queue.push_back({});\n            dispatch_expected.push_back(N * i);\n            dispatch_order.push_back({});\n        }\n        cranes.resize(N);\n        for(int i=0; i<N; ++i) {\n            cranes[i] = {i, i, 0, EMPTY, (i == 0), true};\n        }\n        turn = 0;\n        dispatched_count = 0;\n    }\n};\n\n// Check if a move is valid for a specific crane in isolation (ignoring other crane collisions)\nbool isMoveValidForCrane(const Crane& c, char action, const State& s) {\n    if (!c.active) return false;\n    int nx = c.x, ny = c.y;\n    int holding = c.holding;\n\n    if (action == 'P') {\n        if (holding != EMPTY) return false;\n        if (s.grid[c.x][c.y] == EMPTY) return false;\n        return true;\n    }\n    if (action == 'Q') {\n        if (holding == EMPTY) return false;\n        if (s.grid[c.x][c.y] != EMPTY) return false;\n        return true;\n    }\n    if (action == 'B') {\n        if (holding != EMPTY) return false;\n        return true;\n    }\n    if (action == 'U') ny--;\n    else if (action == 'D') ny++;\n    else if (action == 'L') nx--;\n    else if (action == 'R') nx++;\n    else if (action == '.') return true;\n    else return false;\n\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    \n    // Small crane carrying container cannot move to occupied square\n    if (!c.is_large && holding != EMPTY && s.grid[nx][ny] != EMPTY) return false;\n\n    return true;\n}\n\n// Check if a combination of actions is valid (collisions)\nbool isComboValid(const vector<char>& actions, const State& s, vector<Crane>& next_cranes) {\n    int N_cranes = s.cranes.size();\n    vector<pair<int, int>> start_pos(N_cranes);\n    vector<pair<int, int>> end_pos(N_cranes);\n    \n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        start_pos[i] = {s.cranes[i].x, s.cranes[i].y};\n        \n        int nx = s.cranes[i].x;\n        int ny = s.cranes[i].y;\n        char act = actions[i];\n        if (act == 'U') ny--;\n        else if (act == 'D') ny++;\n        else if (act == 'L') nx--;\n        else if (act == 'R') nx++;\n        \n        end_pos[i] = {nx, ny};\n    }\n\n    // Check overlap and swap\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) continue;\n        for(int j=i+1; j<N_cranes; ++j) {\n            if (!s.cranes[j].active) continue;\n            \n            // Overlap\n            if (end_pos[i] == end_pos[j]) return false;\n            \n            // Swap\n            if (start_pos[i] == end_pos[j] && start_pos[j] == end_pos[i]) return false;\n        }\n    }\n    \n    // Apply to next_cranes for simulation\n    for(int i=0; i<N_cranes; ++i) {\n        if (!s.cranes[i].active) {\n            next_cranes[i] = s.cranes[i];\n            continue;\n        }\n        next_cranes[i] = s.cranes[i];\n        char act = actions[i];\n        if (act == 'P') {\n            next_cranes[i].holding = s.grid[s.cranes[i].x][s.cranes[i].y];\n        } else if (act == 'Q') {\n            next_cranes[i].holding = EMPTY;\n        } else if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    return true;\n}\n\n// Calculate Heuristic Score\nint calculateScore(const State& s) {\n    int score = 0;\n    int undispatched = 0;\n    int wrong_gate = 0;\n    int inversions = 0;\n    int dist_sum = 0;\n    \n    // Check dispatched containers\n    // We simulate the dispatch step for the heuristic\n    // Actually, we can just check current state.\n    // If container at (i, 4) is correct, it counts as dispatched for next turn.\n    \n    vector<int> current_dispatched(N, 0); // Count of dispatched for each row\n    \n    for(int i=0; i<N; ++i) {\n        int cx = i;\n        int cy = N-1;\n        int container = s.grid[cx][cy];\n        if (container != EMPTY) {\n            int expected = N * i + s.dispatch_order[i].size(); // This is tricky, we need to know order\n            // Simplified: Check if container belongs to this row\n            if (container / N == i) {\n                // It belongs to this row.\n                // To check inversion, we need to know previous dispatched.\n                // For heuristic, we just count if it's at correct gate.\n                // We assume if it's at correct gate, it's good.\n                // Inversion penalty is small compared to M2, M3.\n                // We can estimate inversions by checking if container < last dispatched.\n                // But we don't store history in State efficiently here.\n                // Let's just count containers at wrong gates.\n            } else {\n                wrong_gate++;\n            }\n        }\n    }\n    \n    // Count undispatched\n    // Total containers = 25.\n    // Count how many are still on grid or in input queue.\n    int on_grid = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) on_grid++;\n        }\n    }\n    int in_queue = 0;\n    for(int i=0; i<N; ++i) in_queue += s.input_queue[i].size();\n    undispatched = on_grid + in_queue;\n    \n    // Distance\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (s.grid[i][j] != EMPTY) {\n                int c = s.grid[i][j];\n                int target_r = c / N;\n                int target_c = N - 1;\n                dist_sum += abs(i - target_r) + abs(j - target_c);\n            }\n        }\n    }\n    \n    // Input Blocking Penalty\n    // If a crane is at (i, 0), it blocks input.\n    // If a container is at (i, 0), it blocks input (until picked).\n    for(int i=0; i<N; ++i) {\n        bool blocked = false;\n        if (s.grid[i][0] != EMPTY) blocked = true;\n        for(const auto& c : s.cranes) {\n            if (c.active && c.x == i && c.y == 0) blocked = true;\n        }\n        if (blocked && !s.input_queue[i].empty()) {\n            // Huge penalty for blocking input\n            score += 100000; \n        }\n    }\n    \n    // Dispatch Gate Penalty\n    // If container at (i, 4) is not the expected one, it blocks dispatch.\n    // Expected for row i is N*i, N*i+1, ...\n    // We can track expected in State.\n    for(int i=0; i<N; ++i) {\n        int expected = N * i + s.dispatch_order[i].size();\n        int container = s.grid[i][4];\n        if (container != EMPTY && container != expected) {\n            // Wrong container at dispatch gate\n            score += 100000;\n        }\n    }\n    \n    score += 1000000 * undispatched;\n    score += 10000 * wrong_gate;\n    score += 100 * dist_sum;\n    score += s.turn; // Minimize turns\n    \n    return score;\n}\n\n// Simulate one turn and return new state\nState simulateTurn(const State& s, const vector<char>& actions) {\n    State next = s;\n    next.turn = s.turn + 1;\n    \n    // Step 1: Receiving Gates\n    for(int i=0; i<N; ++i) {\n        if (!next.input_queue[i].empty()) {\n            bool blocked = false;\n            if (next.grid[i][0] != EMPTY) blocked = true;\n            for(const auto& c : next.cranes) {\n                if (c.active && c.x == i && c.y == 0) blocked = true;\n            }\n            if (!blocked) {\n                next.grid[i][0] = next.input_queue[i].front();\n                next.input_queue[i].erase(next.input_queue[i].begin());\n            }\n        }\n    }\n    \n    // Step 2: Crane Actions\n    // We need to update grid and cranes based on actions\n    // Since we already validated actions in isComboValid, we can apply them.\n    // But we need to handle P/Q on grid correctly.\n    \n    vector<Crane> next_cranes = next.cranes;\n    vector<int> next_grid[N]; // Temporary to handle P/Q order? No, simultaneous.\n    // Actually, P/Q updates grid.\n    // We should apply moves first, then P/Q? No, P/Q happens at current square.\n    // Move happens to adjacent.\n    // The problem says \"Perform the actions of each crane\".\n    // It implies P/Q/Move are atomic per crane.\n    // So we update grid based on P/Q at current pos, then move cranes.\n    // Wait, if P happens, container leaves grid. If Q happens, container enters grid.\n    // If Move happens, crane changes pos.\n    // Order:\n    // 1. Check P/Q validity (already done).\n    // 2. Apply P: remove from grid, set crane holding.\n    // 3. Apply Q: set crane holding to EMPTY, put to grid.\n    // 4. Apply Move: update crane pos.\n    // Note: If a crane moves from A to B, and another Q at B?\n    // \"Cranes cannot overlap\". So if A moves to B, B must be empty of cranes.\n    // But can B have a container? Yes.\n    // If crane Q at B, it puts container at B.\n    // If crane A moves to B, it arrives at B.\n    // If A moves to B, and B was empty, now A is at B.\n    // If Q happens at B (by crane C), C must be at B.\n    // So A cannot move to B if C is at B.\n    // So Crane positions are updated simultaneously.\n    // Grid updates:\n    // - P removes from grid.\n    // - Q adds to grid.\n    // - Container at (i,0) added in Step 1.\n    // - Container at (i,4) removed in Step 3.\n    \n    // Apply P\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'P') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = EMPTY;\n            next_cranes[i].holding = s.grid[next_cranes[i].x][next_cranes[i].y];\n        }\n    }\n    // Apply Q\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        if (actions[i] == 'Q') {\n            next.grid[next_cranes[i].x][next_cranes[i].y] = next_cranes[i].holding;\n            next_cranes[i].holding = EMPTY;\n        }\n    }\n    // Apply Move / Bomb\n    for(int i=0; i<N; ++i) {\n        if (!next_cranes[i].active) continue;\n        char act = actions[i];\n        if (act == 'B') {\n            next_cranes[i].active = false;\n        } else if (act == 'U') next_cranes[i].y--;\n        else if (act == 'D') next_cranes[i].y++;\n        else if (act == 'L') next_cranes[i].x--;\n        else if (act == 'R') next_cranes[i].x++;\n    }\n    next.cranes = next_cranes;\n    \n    // Step 3: Dispatch\n    for(int i=0; i<N; ++i) {\n        int container = next.grid[i][4];\n        if (container != EMPTY) {\n            // Check if correct\n            int expected = N * i + next.dispatch_order[i].size();\n            if (container == expected) {\n                next.dispatch_order[i].push_back(container);\n                next.grid[i][4] = EMPTY;\n                next.dispatched_count++;\n            }\n        }\n    }\n    \n    return next;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int N_in;\n    if (!(cin >> N_in)) return 0;\n    \n    State s;\n    // Read Input\n    // A_{i,j}\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int val;\n            cin >> val;\n            s.input_queue[i].push_back(val);\n        }\n    }\n    \n    vector<string> result(N, \"\");\n    \n    // Precompute valid actions for each crane to speed up\n    // But valid actions depend on state.\n    \n    // Loop\n    for(int t=0; t<MAX_TURNS; ++t) {\n        if (s.dispatched_count == N*N) break;\n        \n        // Generate candidate actions for each crane\n        vector<vector<pair<char, int>>> candidates(N);\n        \n        for(int i=0; i<N; ++i) {\n            if (!s.cranes[i].active) {\n                candidates[i].push_back({'.', 0});\n                continue;\n            }\n            const Crane& c = s.cranes[i];\n            vector<char> moves = {'P', 'Q', 'U', 'D', 'L', 'R', '.'};\n            for(char m : moves) {\n                if (isMoveValidForCrane(c, m, s)) {\n                    // Estimate score for this move alone (others do '.')\n                    // To save time, we can use a simpler heuristic or just add to list.\n                    // Let's just collect valid moves.\n                    candidates[i].push_back({m, 0});\n                }\n            }\n            // Sort candidates by some priority?\n            // Priority:\n            // 1. If at (i,0) and container exists: P\n            // 2. If holding: Q or Move towards target\n            // 3. If empty: Move towards (i,0) or container\n            // We can sort here to pick top K.\n            // For now, take all valid.\n            // Limit to top 5 to keep 5^5 small.\n            if (candidates[i].size() > 5) {\n                // Sort by heuristic improvement\n                // We can't compute full heuristic for each.\n                // Use simple priority.\n                // Just take first 5.\n                candidates[i].resize(5);\n            }\n        }\n        \n        // Iterate combinations\n        // We need to find the best valid combination.\n        // Since candidates are small (<=5), 5^5 = 3125.\n        // We can use a recursive search or nested loops.\n        // To find BEST, we can iterate all and track best.\n        \n        int best_score = INF;\n        vector<char> best_actions(N, '.');\n        bool found = false;\n        \n        // Use a simple iterative approach with indices\n        vector<int> idx(N, 0);\n        vector<int> sizes(N);\n        for(int i=0; i<N; ++i) sizes[i] = candidates[i].size();\n        \n        // We can use a priority queue to explore combinations in order of estimated utility?\n        // No, just iterate all valid ones and pick best.\n        // 3125 is small enough.\n        \n        // To optimize, we can prune invalid combos early.\n        // But 3125 is very small.\n        \n        // We need to generate all combinations.\n        // Recursive function\n        auto search = [&](auto&& self, int crane_idx, vector<char>& current_actions, State& temp_s, vector<Crane>& temp_cranes) -> void {\n            if (crane_idx == N) {\n                // Check validity of full combo\n                if (isComboValid(current_actions, s, temp_cranes)) {\n                    // Calculate score\n                    // We can simulate the turn to get exact score\n                    // But simulation is expensive.\n                    // Let's use calculateScore on the resulting state.\n                    // To avoid full simulation, we can approximate.\n                    // But for correctness, simulate.\n                    // Actually, we can just calculate score on 's' with modifications.\n                    // Let's just simulate.\n                    State next_s = simulateTurn(s, current_actions);\n                    int sc = calculateScore(next_s);\n                    if (sc < best_score) {\n                        best_score = sc;\n                        best_actions = current_actions;\n                        found = true;\n                    }\n                }\n                return;\n            }\n            \n            for(int i=0; i<sizes[crane_idx]; ++i) {\n                current_actions[crane_idx] = candidates[crane_idx][i].first;\n                self(self, crane_idx + 1, current_actions, temp_s, temp_cranes);\n            }\n        };\n        \n        vector<char> current_actions(N);\n        State temp_s = s;\n        vector<Crane> temp_cranes = s.cranes;\n        search(search, 0, current_actions, temp_s, temp_cranes);\n        \n        if (!found) {\n            // Fallback: all '.'\n            best_actions.assign(N, '.');\n        }\n        \n        // Apply best actions\n        for(int i=0; i<N; ++i) {\n            result[i] += best_actions[i];\n        }\n        \n        s = simulateTurn(s, best_actions);\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << result[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nint dist(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<vector<int>> h(N, vector<int>(N));\n    vector<Point> sources, sinks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n            }\n        }\n    }\n\n    int num_sources = sources.size();\n    int num_sinks = sinks.size();\n\n    // Simple greedy matching: match sources to sinks based on distance\n    // We'll use a priority queue approach to find the best matches\n    vector<vector<pair<int, int>>> requests(num_sources);\n    vector<int> remaining_supply(num_sources);\n    vector<int> remaining_demand(num_sinks, 0);\n    \n    for (int i = 0; i < num_sources; ++i) {\n        remaining_supply[i] = h[sources[i].x][sources[i].y];\n    }\n    for (int i = 0; i < num_sinks; ++i) {\n        remaining_demand[i] = abs(h[sinks[i].x][sinks[i].y]);\n    }\n\n    // Greedy matching: always match the closest source-sink pair\n    while (true) {\n        int best_u = -1, best_v = -1;\n        int min_d = 1e9;\n        \n        for (int i = 0; i < num_sources; ++i) {\n            if (remaining_supply[i] <= 0) continue;\n            for (int j = 0; j < num_sinks; ++j) {\n                if (remaining_demand[j] <= 0) continue;\n                int d = dist(sources[i], sinks[j]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_u = i;\n                    best_v = j;\n                }\n            }\n        }\n        \n        if (best_u == -1) break;\n        \n        int amount = min(remaining_supply[best_u], remaining_demand[best_v]);\n        remaining_supply[best_u] -= amount;\n        remaining_demand[best_v] -= amount;\n        requests[best_u].push_back({best_v, amount});\n    }\n\n    // Routing\n    int cur_x = 0, cur_y = 0;\n    vector<bool> source_done(num_sources, false);\n    int remaining_sources = num_sources;\n    \n    vector<string> ops;\n    \n    auto move_to = [&](int tx, int ty) {\n        while (cur_x < tx) {\n            cur_x++;\n            ops.push_back(\"D\");\n        }\n        while (cur_x > tx) {\n            cur_x--;\n            ops.push_back(\"U\");\n        }\n        while (cur_y < ty) {\n            cur_y++;\n            ops.push_back(\"R\");\n        }\n        while (cur_y > ty) {\n            cur_y--;\n            ops.push_back(\"L\");\n        }\n    };\n\n    auto load = [&](int amount) {\n        ops.push_back(\"+\" + to_string(amount));\n    };\n\n    auto unload = [&](int amount) {\n        ops.push_back(\"-\" + to_string(amount));\n    };\n\n    // Main Loop - Greedy nearest source\n    while (remaining_sources > 0) {\n        // Find nearest source that is not done\n        int best_u = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < num_sources; ++i) {\n            if (!source_done[i]) {\n                int d = dist({cur_x, cur_y}, sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_u = i;\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n\n        // Move to source\n        move_to(sources[best_u].x, sources[best_u].y);\n\n        // Load soil\n        int total_load = 0;\n        for (const auto &p : requests[best_u]) {\n            total_load += p.second;\n        }\n        if (total_load > 0) {\n            load(total_load);\n        }\n\n        // Plan Sink Tour using Nearest Neighbor\n        vector<int> sink_order;\n        vector<bool> sink_done_local(requests[best_u].size(), false);\n        int cur_sink_x = sources[best_u].x;\n        int cur_sink_y = sources[best_u].y;\n        \n        for (size_t k = 0; k < requests[best_u].size(); ++k) {\n            int best_v = -1;\n            int min_d_sink = 1e9;\n            for (size_t i = 0; i < requests[best_u].size(); ++i) {\n                if (!sink_done_local[i]) {\n                    int v_idx = requests[best_u][i].first;\n                    int d = dist({cur_sink_x, cur_sink_y}, sinks[v_idx]);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                        best_v = (int)i;\n                    }\n                }\n            }\n            if (best_v != -1) {\n                sink_done_local[best_v] = true;\n                sink_order.push_back(best_v);\n                int v_idx = requests[best_u][best_v].first;\n                cur_sink_x = sinks[v_idx].x;\n                cur_sink_y = sinks[v_idx].y;\n            }\n        }\n\n        // Execute Sink Tour\n        for (int idx : sink_order) {\n            int v_idx = requests[best_u][idx].first;\n            int amount = requests[best_u][idx].second;\n            int tx = sinks[v_idx].x;\n            int ty = sinks[v_idx].y;\n            \n            move_to(tx, ty);\n            unload(amount);\n        }\n\n        source_done[best_u] = true;\n        remaining_sources--;\n    }\n\n    // Output\n    for (const string &s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_int(0, 35);\nuniform_real_distribution<double> dist_real(0.0, 1.0);\n\nint N, M, T;\nint seed_count;\nvector<vector<int>> seeds;\nvector<int> seed_val;\nvector<vector<int>> adj;\nvector<int> pos_order;\nvector<int> grid;\nlong long current_score;\n\nlong long calc_edge_score(int u, int v) {\n    long long s = 0;\n    for (int l = 0; l < M; ++l) {\n        s += max(seeds[u][l], seeds[v][l]);\n    }\n    return s;\n}\n\nvoid init_adj() {\n    adj.assign(N * N, vector<int>());\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (i > 0) adj[u].push_back((i - 1) * N + j);\n            if (i < N - 1) adj[u].push_back((i + 1) * N + j);\n            if (j > 0) adj[u].push_back(i * N + (j - 1));\n            if (j < N - 1) adj[u].push_back(i * N + (j + 1));\n        }\n    }\n}\n\nvoid init_pos_order() {\n    pos_order.resize(N * N);\n    iota(pos_order.begin(), pos_order.end(), 0);\n    sort(pos_order.begin(), pos_order.end(), [&](int a, int b) {\n        return adj[a].size() > adj[b].size();\n    });\n}\n\nvoid init_grid() {\n    vector<int> p(seed_count);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        return seed_val[a] > seed_val[b];\n    });\n\n    for (int k = 0; k < N * N; ++k) {\n        grid[pos_order[k]] = p[k];\n    }\n\n    current_score = 0;\n    for (int i = 0; i < N * N; ++i) {\n        for (int n : adj[i]) {\n            if (i < n) {\n                current_score += calc_edge_score(grid[i], grid[n]);\n            }\n        }\n    }\n}\n\nvoid sa() {\n    double temp = 10000.0;\n    double cooling = 0.995;\n    int iterations = 50000;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int u = dist_int(gen);\n        int v = dist_int(gen);\n        if (u == v) continue;\n\n        long long delta = 0;\n        \n        // Remove contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta -= calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta -= calc_edge_score(grid[v], grid[n]);\n        }\n\n        swap(grid[u], grid[v]);\n\n        // Add contributions of edges connected to u and v\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta += calc_edge_score(grid[u], grid[n]);\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta += calc_edge_score(grid[v], grid[n]);\n        }\n\n        if (delta >= 0 || dist_real(gen) < exp(delta / temp)) {\n            current_score += delta;\n        } else {\n            swap(grid[u], grid[v]);\n        }\n\n        temp *= cooling;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> T;\n    seed_count = 2 * N * (N - 1);\n    seeds.resize(seed_count, vector<int>(M));\n    seed_val.resize(seed_count);\n\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n            seed_val[i] += seeds[i][j];\n        }\n    }\n\n    init_adj();\n    init_pos_order();\n    grid.resize(N * N);\n\n    for (int t = 0; t < T; ++t) {\n        // Recalculate seed_val in case we need to re-sort (though we do it inside init_grid)\n        // Actually, seeds change every turn, so we must update seed_val\n        for (int i = 0; i < seed_count; ++i) {\n            seed_val[i] = 0;\n            for (int j = 0; j < M; ++j) {\n                seed_val[i] += seeds[i][j];\n            }\n        }\n\n        init_grid();\n        sa();\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << grid[i * N + j] << (j == N - 1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Takoyaki {\n    Point src, tgt;\n    int id;\n    bool done = false;\n};\n\nint N, M, V;\nvector<string> s_grid, t_grid;\nvector<Takoyaki> takoyakis;\nvector<int> edge_len;\nint root_x, root_y;\nint dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // R, D, L, U\nchar dir_char[4] = {'R', 'D', 'L', 'U'};\n\n// Current state\nint arm_dir[16]; // direction of each edge (0-3)\nbool holding[16]; // whether each fingertip is holding\nPoint fingertip_pos[16]; // current position of each fingertip\n\n// Calculate fingertip positions based on root and directions\nvoid update_fingertip_positions() {\n    for (int i = 1; i < edge_len.size() + 1; i++) {\n        int fx = root_x + dir[arm_dir[i]][0] * edge_len[i];\n        int fy = root_y + dir[arm_dir[i]][1] * edge_len[i];\n        fingertip_pos[i] = {fx, fy};\n    }\n}\n\n// Check if position is valid\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there's a takoyaki at position\nbool has_takoyaki(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1';\n}\n\n// Check if position is a target\nbool is_target(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return t_grid[x][y] == '1';\n}\n\n// Check if position has been filled (target completed)\nbool is_filled(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1' && t_grid[x][y] == '1';\n}\n\n// Find nearest available source for a fingertip\nPoint find_nearest_source(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].src.x) + abs(fp.y - takoyakis[i].src.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].src;\n        }\n    }\n    return best;\n}\n\n// Find nearest available target for a fingertip\nPoint find_nearest_target(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].tgt.x) + abs(fp.y - takoyakis[i].tgt.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].tgt;\n        }\n    }\n    return best;\n}\n\n// Get direction to move towards a target\nint get_direction(Point current, Point target) {\n    if (current.x < target.x) return 1; // D\n    if (current.x > target.x) return 3; // U\n    if (current.y < target.y) return 0; // R\n    if (current.y > target.y) return 2; // L\n    return 0; // Default\n}\n\n// Get rotation to achieve desired direction\nchar get_rotation(int current_dir, int target_dir) {\n    int diff = (target_dir - current_dir + 4) % 4;\n    if (diff == 0) return '.';\n    if (diff == 1 || diff == 3) return 'R'; // clockwise\n    return 'L'; // counterclockwise\n}\n\n// Check if all takoyaki are delivered\nbool all_delivered() {\n    for (int i = 0; i < M; i++) {\n        if (!takoyakis[i].done) return false;\n    }\n    return true;\n}\n\n// Check if a source still has takoyaki\nbool source_has_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return s_grid[p.x][p.y] == '1' && t_grid[p.x][p.y] == '0';\n}\n\n// Check if a target needs takoyaki\nbool target_needs_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return t_grid[p.x][p.y] == '1' && s_grid[p.x][p.y] == '0';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> V;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    \n    for (int i = 0; i < N; i++) cin >> s_grid[i];\n    for (int i = 0; i < N; i++) cin >> t_grid[i];\n    \n    // Parse takoyaki positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                takoyakis.push_back({{i, j}, {0, 0}, (int)takoyakis.size()});\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (t_grid[i][j] == '1' && s_grid[i][j] == '0') {\n                // Find matching source\n                for (auto& t : takoyakis) {\n                    if (t.tgt.x == 0 && t.tgt.y == 0) {\n                        t.tgt = {i, j};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Design star topology robot\n    int num_fingertips = min(V - 1, M); // Each fingertip handles one takoyaki\n    \n    // Output robot design\n    cout << num_fingertips + 1 << \"\\n\";\n    edge_len.resize(num_fingertips + 1);\n    \n    // Use different edge lengths for better coverage\n    for (int i = 1; i <= num_fingertips; i++) {\n        edge_len[i] = min(i * 2, N - 1);\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Initial position: center of grid\n    root_x = N / 2;\n    root_y = N / 2;\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Initialize directions (all pointing right initially)\n    for (int i = 0; i <= num_fingertips; i++) {\n        arm_dir[i] = 0;\n        holding[i] = false;\n    }\n    \n    update_fingertip_positions();\n    \n    // Main operation loop\n    int turn = 0;\n    int max_turns = 80000; // Leave margin for system test\n    \n    while (turn < max_turns && !all_delivered()) {\n        string cmd = \"\";\n        \n        // Step 1: Decide arm movement\n        // Find average direction to move towards pending sources/targets\n        int total_dx = 0, total_dy = 0;\n        int count = 0;\n        \n        for (int i = 0; i < M; i++) {\n            if (takoyakis[i].done) continue;\n            if (holding[i % (num_fingertips + 1)]) {\n                // Moving towards target\n                total_dx += takoyakis[i].tgt.x - root_x;\n                total_dy += takoyakis[i].tgt.y - root_y;\n            } else {\n                // Moving towards source\n                total_dx += takoyakis[i].src.x - root_x;\n                total_dy += takoyakis[i].src.y - root_y;\n                count++;\n            }\n        }\n        \n        // Determine movement direction\n        char move = '.';\n        if (count > 0) {\n            if (abs(total_dx) > abs(total_dy)) {\n                if (total_dx > 0) move = 'D';\n                else if (total_dx < 0) move = 'U';\n            } else {\n                if (total_dy > 0) move = 'R';\n                else if (total_dy < 0) move = 'L';\n            }\n        }\n        \n        // Check if movement is valid\n        int nx = root_x, ny = root_y;\n        if (move == 'D') nx++;\n        else if (move == 'U') nx--;\n        else if (move == 'R') ny++;\n        else if (move == 'L') ny--;\n        \n        if (!is_valid(nx, ny)) move = '.';\n        else { root_x = nx; root_y = ny; }\n        \n        cmd += move;\n        \n        // Step 2: Decide rotations for each fingertip\n        for (int i = 1; i <= num_fingertips; i++) {\n            char rot = '.';\n            \n            // Find what this fingertip should do\n            Point fp = fingertip_pos[i];\n            \n            if (holding[i]) {\n                // Try to drop at target\n                Point tgt = find_nearest_target(fp);\n                if (tgt.x >= 0 && target_needs_takoyaki(tgt)) {\n                    // Calculate direction to reach target\n                    int dx = tgt.x - root_x;\n                    int dy = tgt.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            } else {\n                // Try to pick from source\n                Point src = find_nearest_source(fp);\n                if (src.x >= 0 && source_has_takoyaki(src)) {\n                    // Calculate direction to reach source\n                    int dx = src.x - root_x;\n                    int dy = src.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            }\n            \n            cmd += rot;\n        }\n        \n        // Step 3: Decide pick/place actions\n        for (int i = 1; i <= num_fingertips; i++) {\n            update_fingertip_positions();\n            Point fp = fingertip_pos[i];\n            char action = '.';\n            \n            if (is_valid(fp.x, fp.y)) {\n                if (holding[i] && target_needs_takoyaki(fp.x, fp.y)) {\n                    // Drop takoyaki\n                    action = 'P';\n                    holding[i] = false;\n                    s_grid[fp.x][fp.y] = '1';\n                    \n                    // Mark as done\n                    for (int j = 0; j < M; j++) {\n                        if (!takoyakis[j].done && \n                            takoyakis[j].tgt.x == fp.x && \n                            takoyakis[j].tgt.y == fp.y) {\n                            takoyakis[j].done = true;\n                            break;\n                        }\n                    }\n                } else if (!holding[i] && source_has_takoyaki(fp.x, fp.y)) {\n                    // Pick takoyaki\n                    action = 'P';\n                    holding[i] = true;\n                    s_grid[fp.x][fp.y] = '0';\n                }\n            }\n            \n            cmd += action;\n        }\n        \n        // Add '.' for root (not a fingertip)\n        cmd += '.';\n        \n        cout << cmd << \"\\n\";\n        turn++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Distance squared\nlong long distSq(Point p1, Point p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Simple DSU for clustering\nstruct SimpleDSU {\n    vector<int> parent;\n    SimpleDSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx != ry) parent[rx] = ry;\n    }\n};\n\nstruct ClusterInfo {\n    int id;\n    vector<int> indices;\n    long long minX, maxX, minY, maxY;\n    int m_count, s_count;\n    long long score;\n};\n\n// Check if point is inside or on boundary of orthogonal polygon\nbool isInside(const vector<Point>& poly, Point p) {\n    int n = poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        bool cond1 = ((poly[i].y > p.y) != (poly[j].y > p.y));\n        if (poly[j].y != poly[i].y) {\n            bool cond2 = (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (double)(poly[j].y - poly[i].y) + poly[i].x);\n            if (cond1 && cond2) inside = !inside;\n        }\n    }\n    if (!inside) {\n        for (int i = 0; i < n; ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % n];\n            if (p1.x == p2.x) {\n                if (p.x == p1.x && min(p1.y, p2.y) <= p.y && p.y <= max(p1.y, p2.y)) return true;\n            } else {\n                if (p.y == p1.y && min(p1.x, p2.x) <= p.x && p.x <= max(p1.x, p2.x)) return true;\n            }\n        }\n    }\n    return inside;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // 1. Cluster Mackerels\n    const long long CLUSTER_DIST_SQ = 6000LL * 6000LL;\n    SimpleDSU dsu_m(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (distSq(mackerels[i], mackerels[j]) <= CLUSTER_DIST_SQ) {\n                dsu_m.unite(i, j);\n            }\n        }\n    }\n\n    vector<vector<int>> m_clusters(N);\n    for (int i = 0; i < N; ++i) {\n        m_clusters[dsu_m.find(i)].push_back(i);\n    }\n\n    // 2. Evaluate Clusters\n    vector<ClusterInfo> good_clusters;\n    for (int i = 0; i < N; ++i) {\n        if (m_clusters[i].empty()) continue;\n        \n        long long minX = 1e9, maxX = -1e9, minY = 1e9, maxY = -1e9;\n        for (int idx : m_clusters[i]) {\n            minX = min(minX, mackerels[idx].x);\n            maxX = max(maxX, mackerels[idx].x);\n            minY = min(minY, mackerels[idx].y);\n            maxY = max(maxY, mackerels[idx].y);\n        }\n\n        int m_cnt = m_clusters[i].size();\n        int s_cnt = 0;\n        for (const auto& s : sardines) {\n            if (s.x >= minX && s.x <= maxX && s.y >= minY && s.y <= maxY) {\n                s_cnt++;\n            }\n        }\n\n        long long sc = (long long)m_cnt - s_cnt;\n        if (sc > 0) {\n            good_clusters.push_back({i, m_clusters[i], minX, maxX, minY, maxY, m_cnt, s_cnt, sc});\n        }\n    }\n\n    // 3. Merge Good Clusters\n    sort(good_clusters.begin(), good_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n        return a.score > b.score;\n    });\n\n    vector<int> used(N, 0);\n    vector<ClusterInfo> final_clusters;\n    \n    auto distBox = [](const ClusterInfo& a, const ClusterInfo& b) {\n        long long dx = max(0LL, max(a.minX, b.minX) - min(a.maxX, b.maxX));\n        long long dy = max(0LL, max(a.minY, b.minY) - min(a.maxY, b.maxY));\n        return dx * dx + dy * dy;\n    };\n\n    for (int i = 0; i < (int)good_clusters.size(); ++i) {\n        if (used[i]) continue;\n        \n        ClusterInfo current = good_clusters[i];\n        used[i] = 1;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int j = 0; j < (int)good_clusters.size(); ++j) {\n                if (i == j || used[j]) continue;\n                \n                long long d2 = distBox(current, good_clusters[j]);\n                if (d2 <= 2000LL * 2000LL) { \n                    current.minX = min(current.minX, good_clusters[j].minX);\n                    current.maxX = max(current.maxX, good_clusters[j].maxX);\n                    current.minY = min(current.minY, good_clusters[j].minY);\n                    current.maxY = max(current.maxY, good_clusters[j].maxY);\n                    \n                    int m_cnt = 0;\n                    int s_cnt = 0;\n                    for (const auto& m : mackerels) {\n                        if (m.x >= current.minX && m.x <= current.maxX && m.y >= current.minY && m.y <= current.maxY) m_cnt++;\n                    }\n                    for (const auto& s : sardines) {\n                        if (s.x >= current.minX && s.x <= current.maxX && s.y >= current.minY && s.y <= current.maxY) s_cnt++;\n                    }\n                    current.m_count = m_cnt;\n                    current.s_count = s_cnt;\n                    current.score = (long long)m_cnt - s_cnt;\n                    \n                    used[j] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (current.score > 0) {\n            final_clusters.push_back(current);\n        }\n    }\n\n    if (final_clusters.empty()) {\n        cout << 4 << \"\\n\";\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Try to find the best valid polygon\n    ClusterInfo best_cluster = final_clusters[0];\n    vector<Point> best_poly;\n    long long best_score = -1e18;\n\n    for (const auto& cluster : final_clusters) {\n        long long cur_minX = cluster.minX;\n        long long cur_maxX = cluster.maxX;\n        long long cur_minY = cluster.minY;\n        long long cur_maxY = cluster.maxY;\n\n        // Shrink Phase: Iteratively remove sardines on boundary\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (const auto& s : sardines) {\n                if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_minX) {\n                    cur_minX = s.x + 1;\n                    changed = true;\n                }\n                if (s.y >= cur_minY && s.y <= cur_maxY && s.x == cur_maxX) {\n                    cur_maxX = s.x - 1;\n                    changed = true;\n                }\n                if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_minY) {\n                    cur_minY = s.y + 1;\n                    changed = true;\n                }\n                if (s.x >= cur_minX && s.x <= cur_maxX && s.y == cur_maxY) {\n                    cur_maxY = s.y - 1;\n                    changed = true;\n                }\n            }\n        }\n\n        if (cur_minX > cur_maxX || cur_minY > cur_maxY) continue;\n\n        // Calculate score for this box\n        int m_cnt = 0;\n        int s_cnt = 0;\n        for (const auto& m : mackerels) {\n            if (m.x >= cur_minX && m.x <= cur_maxX && m.y >= cur_minY && m.y <= cur_maxY) m_cnt++;\n        }\n        for (const auto& s : sardines) {\n            if (s.x >= cur_minX && s.x <= cur_maxX && s.y >= cur_minY && s.y <= cur_maxY) s_cnt++;\n        }\n        long long sc = (long long)m_cnt - s_cnt;\n\n        if (sc > best_score) {\n            best_score = sc;\n            best_cluster = cluster; // Not strictly needed, but for debugging\n            best_poly.clear();\n            best_poly.push_back({cur_minX, cur_minY});\n            best_poly.push_back({cur_maxX, cur_minY});\n            best_poly.push_back({cur_maxX, cur_maxY});\n            best_poly.push_back({cur_minX, cur_maxY});\n        }\n    }\n\n    if (best_poly.empty()) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Notch Phase: Add notches to remove sardines on the boundary of the best_poly\n    // We only add notches on the 4 original sides to avoid intersection.\n    // We track intervals on each side to prevent overlapping notches.\n    \n    // Identify sardines on the 4 sides\n    struct SideSardine {\n        long long pos; // x for horizontal, y for vertical\n        int side; // 0: Bottom, 1: Top, 2: Left, 3: Right\n        Point p;\n    };\n    vector<SideSardine> sardines_on_sides;\n\n    long long minX = best_poly[0].x;\n    long long maxX = best_poly[1].x;\n    long long minY = best_poly[0].y;\n    long long maxY = best_poly[2].y;\n\n    for (const auto& s : sardines) {\n        // Check Bottom (y = minY)\n        if (s.y == minY && s.x > minX && s.x < maxX) {\n            sardines_on_sides.push_back({s.x, 0, s});\n        }\n        // Check Top (y = maxY)\n        if (s.y == maxY && s.x > minX && s.x < maxX) {\n            sardines_on_sides.push_back({s.x, 1, s});\n        }\n        // Check Left (x = minX)\n        if (s.x == minX && s.y > minY && s.y < maxY) {\n            sardines_on_sides.push_back({s.y, 2, s});\n        }\n        // Check Right (x = maxX)\n        if (s.x == maxX && s.y > minY && s.y < maxY) {\n            sardines_on_sides.push_back({s.y, 3, s});\n        }\n    }\n\n    // Sort by side and position\n    sort(sardines_on_sides.begin(), sardines_on_sides.end(), [](const SideSardine& a, const SideSardine& b) {\n        if (a.side != b.side) return a.side < b.side;\n        return a.pos < b.pos;\n    });\n\n    // Track used intervals\n    // For each side, store a list of [start, end] intervals that are notched\n    vector<vector<pair<long long, long long>>> used_intervals(4);\n\n    for (const auto& ss : sardines_on_sides) {\n        int side = ss.side;\n        long long pos = ss.pos;\n        \n        // Check overlap\n        bool overlap = false;\n        for (auto& interval : used_intervals[side]) {\n            // Notch at pos occupies [pos, pos+1] (since notch depth is 1 and width is 1)\n            // Actually, notch at x=pos on bottom edge creates vertices at pos and pos+1.\n            // So it occupies [pos, pos+1].\n            if (pos < interval.second && pos + 1 > interval.first) {\n                overlap = true;\n                break;\n            }\n        }\n        if (overlap) continue;\n\n        // Check if notch removes a mackerel\n        // Notch location:\n        // Bottom: (pos, minY+1)\n        // Top: (pos, maxY-1)\n        // Left: (minX+1, pos)\n        // Right: (maxX-1, pos)\n        Point notch_loc;\n        if (side == 0) notch_loc = {pos, minY + 1};\n        else if (side == 1) notch_loc = {pos, maxY - 1};\n        else if (side == 2) notch_loc = {minX + 1, pos};\n        else notch_loc = {maxX - 1, pos};\n\n        bool has_mackerel = false;\n        for (const auto& m : mackerels) {\n            if (m.x == notch_loc.x && m.y == notch_loc.y) {\n                has_mackerel = true;\n                break;\n            }\n        }\n        if (has_mackerel) continue; // Don't notch if it removes a mackerel\n\n        // Add notch\n        used_intervals[side].push_back({pos, pos + 1});\n        \n        // Insert vertices into best_poly\n        // We need to reconstruct the polygon with notches\n        // To keep it simple, we will rebuild the polygon from the intervals at the end\n    }\n\n    // Reconstruct polygon\n    vector<Point> final_poly;\n    \n    // Bottom edge (minY)\n    long long curr_x = minX;\n    for (auto& interval : used_intervals[0]) {\n        // Move to start of notch\n        final_poly.push_back({curr_x, minY});\n        // Notch\n        final_poly.push_back({interval.first, minY + 1});\n        final_poly.push_back({interval.second, minY + 1});\n        final_poly.push_back({interval.second, minY});\n        curr_x = interval.second;\n    }\n    final_poly.push_back({curr_x, minY}); // End of bottom edge (maxX)\n\n    // Right edge (maxX)\n    long long curr_y = minY;\n    for (auto& interval : used_intervals[3]) {\n        final_poly.push_back({maxX, curr_y});\n        final_poly.push_back({maxX - 1, interval.first});\n        final_poly.push_back({maxX - 1, interval.second});\n        final_poly.push_back({maxX, interval.second});\n        curr_y = interval.second;\n    }\n    final_poly.push_back({maxX, curr_y}); // End of right edge (maxY)\n\n    // Top edge (maxY)\n    curr_x = maxX;\n    for (auto& interval : used_intervals[1]) {\n        final_poly.push_back({curr_x, maxY});\n        final_poly.push_back({interval.second, maxY - 1}); // Note: Top edge goes right to left\n        final_poly.push_back({interval.first, maxY - 1});\n        final_poly.push_back({interval.first, maxY});\n        curr_x = interval.first;\n    }\n    final_poly.push_back({curr_x, maxY}); // End of top edge (minX)\n\n    // Left edge (minX)\n    curr_y = maxY;\n    for (auto& interval : used_intervals[2]) {\n        final_poly.push_back({minX, curr_y});\n        final_poly.push_back({minX + 1, interval.second}); // Left edge goes top to bottom\n        final_poly.push_back({minX + 1, interval.first});\n        final_poly.push_back({minX, interval.first});\n        curr_y = interval.first;\n    }\n    final_poly.push_back({minX, curr_y}); // End of left edge (minY)\n\n    // Remove duplicates\n    vector<Point> unique_poly;\n    for (int i = 0; i < final_poly.size(); ++i) {\n        if (i > 0 && final_poly[i].x == final_poly[i-1].x && final_poly[i].y == final_poly[i-1].y) continue;\n        unique_poly.push_back(final_poly[i]);\n    }\n    if (unique_poly.size() > 1 && unique_poly.front().x == unique_poly.back().x && unique_poly.front().y == unique_poly.back().y) {\n        unique_poly.pop_back();\n    }\n    final_poly = unique_poly;\n\n    if (final_poly.size() < 4) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << final_poly.size() << \"\\n\";\n    for (const auto& p : final_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Placement {\n    int p, r;\n    char d;\n    int b;\n};\n\nclass Solver {\nprivate:\n    int N, T;\n    double sigma;\n    vector<pair<int, int>> wh;\n    mt19937 rng;\n    \n    pair<int, int> calculatePosition(const vector<pair<int, int>>& placed_wh, \n                                     const vector<pair<int, int>>& placed_xy,\n                                     int rw, int rh, char dir, int ref) {\n        int x = 0, y = 0;\n        \n        if (dir == 'U') {\n            x = (ref == -1) ? 0 : placed_xy[ref].first + placed_wh[ref].first;\n            y = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (x < px + pw && x + rw > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            y = (ref == -1) ? 0 : placed_xy[ref].second + placed_wh[ref].second;\n            x = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (y < py + ph && y + rh > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        return {x, y};\n    }\n    \n    vector<Placement> greedyPlacement(int seed) {\n        vector<Placement> placements;\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        mt19937 local_rng(seed);\n        \n        for (int i = 0; i < N; i++) {\n            int best_score = 2e9;\n            Placement best_p = {i, 0, 'U', -1};\n            \n            int w = wh[i].first;\n            int h = wh[i].second;\n            // Prefer rotation that keeps larger dimension horizontal\n            bool prefer_horizontal = (w >= h);\n            \n            for (int rot = 0; rot < 2; rot++) {\n                int rw = rot ? h : w;\n                int rh = rot ? w : h;\n                \n                // Small penalty for non-preferred rotation\n                int rot_penalty = (rot != prefer_horizontal) ? 500 : 0;\n                \n                for (char dir : {'U', 'L'}) {\n                    // Try limited references for efficiency\n                    int max_refs = min(i, 8);\n                    vector<int> refs_to_try;\n                    refs_to_try.push_back(-1);\n                    for (int r = i - 1; r >= max(0, i - max_refs); r--) {\n                        refs_to_try.push_back(r);\n                    }\n                    \n                    for (int ref : refs_to_try) {\n                        auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, dir, ref);\n                        \n                        int W = 0, H = 0;\n                        for (size_t j = 0; j < placed_wh.size(); j++) {\n                            W = max(W, placed_xy[j].first + placed_wh[j].first);\n                            H = max(H, placed_xy[j].second + placed_wh[j].second);\n                        }\n                        W = max(W, x + rw);\n                        H = max(H, y + rh);\n                        \n                        int score = W + H + rot_penalty;\n                        if (score < best_score) {\n                            best_score = score;\n                            best_p = {i, rot, dir, ref};\n                        }\n                    }\n                }\n            }\n            \n            placements.push_back(best_p);\n            int rw = best_p.r ? h : w;\n            int rh = best_p.r ? w : h;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, best_p.d, best_p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        return placements;\n    }\n    \n    int calculateScore(const vector<Placement>& placements) {\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        \n        for (const auto& p : placements) {\n            int rw = p.r ? wh[p.p].second : wh[p.p].first;\n            int rh = p.r ? wh[p.p].first : wh[p.p].second;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, p.d, p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        int W = 0, H = 0;\n        for (size_t i = 0; i < placed_wh.size(); i++) {\n            W = max(W, placed_xy[i].first + placed_wh[i].first);\n            H = max(H, placed_xy[i].second + placed_wh[i].second);\n        }\n        \n        return W + H;\n    }\n    \n    vector<Placement> localSearch(const vector<Placement>& placements) {\n        vector<Placement> cur = placements;\n        int best_score = calculateScore(cur);\n        \n        // Try flipping rotation for each rectangle\n        for (int i = 0; i < N; i++) {\n            cur[i].r ^= 1;\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].r ^= 1;  // Revert if not better\n            }\n        }\n        \n        // Try changing direction for some rectangles\n        for (int i = 0; i < N; i++) {\n            char orig_d = cur[i].d;\n            cur[i].d = (orig_d == 'U' ? 'L' : 'U');\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].d = orig_d;  // Revert if not better\n            }\n        }\n        \n        return cur;\n    }\n    \npublic:\n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void solve() {\n        cin >> N >> T >> sigma;\n        wh.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> wh[i].first >> wh[i].second;\n        }\n        \n        auto startTime = chrono::steady_clock::now();\n        const double MAX_TIME = 2.6;  // Conservative for system test\n        \n        for (int t = 0; t < T; t++) {\n            auto currentTime = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed > MAX_TIME) break;\n            \n            int best_score = 2e9;\n            vector<Placement> best_placements;\n            \n            // Adaptive number of strategies - more exploration early\n            int num_strategies = max(2, 6 - t / (T / 4));\n            for (int s = 0; s < num_strategies; s++) {\n                vector<Placement> placements = greedyPlacement(t * 1000 + s);\n                placements = localSearch(placements);\n                int score = calculateScore(placements);\n                if (score < best_score) {\n                    best_score = score;\n                    best_placements = placements;\n                }\n            }\n            \n            cout << best_placements.size() << \"\\n\";\n            for (const auto& p : best_placements) {\n                cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n            }\n            cout.flush();\n            \n            int W, H;\n            cin >> W >> H;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.solve();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Global buffers to avoid reallocation overhead\nconst int MAXN = 1005;\nvector<int> adj[MAXN];\nint A[MAXN];\nint L[MAXN];\nint pc[MAXN]; // parent count: number of neighbors u with L[u] == L[v] - 1\nint p[MAXN];  // output parent array\nint x[MAXN], y[MAXN];\n\nvoid solve() {\n    int N, M, H;\n    // Read until EOF\n    while (cin >> N >> M >> H) {\n        // Read Beauty values\n        for (int i = 0; i < N; ++i) {\n            cin >> A[i];\n        }\n        // Read Edges\n        for (int i = 0; i < M; ++i) {\n            int u, v;\n            cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // Read Coordinates (ignored but must be read)\n        for (int i = 0; i < N; ++i) {\n            cin >> x[i] >> y[i];\n        }\n\n        // Initialize State\n        for (int i = 0; i < N; ++i) {\n            L[i] = 0;\n            pc[i] = 0;\n        }\n\n        // Random number generator\n        static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_int_distribution<int> dist_idx(0, N - 1);\n        uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n        // Simulated Annealing\n        // Increased iterations to 20,000 to allow better exploration within 2.0s\n        // T and decay tuned for longer run\n        int iterations = 20000;\n        double T = 1000.0;\n        double decay = 0.9995;\n\n        long long current_score = 0;\n        // current_score tracks sum L[v] * A[v]\n\n        // Pre-allocate candidate array to avoid vector allocation in loop\n        int candidates[2];\n        int c_count;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            // Pick random vertex\n            int v = dist_idx(rng);\n            \n            int old_L = L[v];\n            \n            // Candidate moves\n            c_count = 0;\n            if (old_L < H) candidates[c_count++] = old_L + 1;\n            if (old_L > 0) candidates[c_count++] = old_L - 1;\n            \n            // Shuffle candidates to avoid bias\n            shuffle(candidates, candidates + c_count, rng);\n            \n            bool move_accepted = false;\n            \n            for (int k = 0; k < c_count; ++k) {\n                int new_L = candidates[k];\n                if (new_L == old_L) continue;\n                \n                // Check validity\n                bool valid = true;\n                \n                // 1. Check v's own parent requirement\n                if (new_L > 0) {\n                    bool has_parent = false;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L - 1) {\n                            has_parent = true;\n                            break;\n                        }\n                    }\n                    if (!has_parent) valid = false;\n                }\n                \n                // 2. Check neighbors' parent count requirement\n                if (valid) {\n                    for (int u : adj[v]) {\n                        if (L[u] == old_L + 1) {\n                            // v was a parent, now not\n                            if (pc[u] == 1) {\n                                valid = false;\n                                break;\n                            }\n                        }\n                    }\n                }\n                \n                if (valid) {\n                    long long delta = (long long)(new_L - old_L) * A[v];\n                    // Calculate acceptance probability\n                    double prob = 1.0;\n                    if (delta < 0) {\n                        prob = exp((double)delta / T);\n                    }\n                    \n                    if (dist_prob(rng) < prob) {\n                        // Accept move\n                        L[v] = new_L;\n                        current_score += delta;\n                        \n                        // Update pc for neighbors\n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                pc[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                pc[u]++;\n                            }\n                        }\n                        move_accepted = true;\n                        break; // Accept first valid move\n                    }\n                }\n            }\n            \n            // Cool down\n            T *= decay;\n        }\n\n        // Construct parent array\n        for (int i = 0; i < N; ++i) {\n            if (L[i] == 0) {\n                p[i] = -1;\n            } else {\n                // Find a neighbor with L[u] == L[i] - 1\n                int parent = -1;\n                for (int u : adj[i]) {\n                    if (L[u] == L[i] - 1) {\n                        parent = u;\n                        break;\n                    }\n                }\n                p[i] = parent;\n            }\n        }\n\n        // Output\n        for (int i = 0; i < N; ++i) {\n            cout << p[i] << (i == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Move {\n    char d;\n    int p;\n};\n\nint N;\nvector<string> board;\nvector<Move> moves;\n\nint count_oni() {\n    int c = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\nvoid apply_move(char d, int p, int k) {\n    for (int step = 0; step < k; ++step) {\n        if (d == 'L') {\n            moves.push_back({'L', p});\n            for (int j = 0; j < N - 1; ++j) {\n                board[p][j] = board[p][j + 1];\n            }\n            board[p][N - 1] = '.';\n        } else if (d == 'R') {\n            moves.push_back({'R', p});\n            for (int j = N - 1; j > 0; --j) {\n                board[p][j] = board[p][j - 1];\n            }\n            board[p][0] = '.';\n        } else if (d == 'U') {\n            moves.push_back({'U', p});\n            for (int i = 0; i < N - 1; ++i) {\n                board[i][p] = board[i + 1][p];\n            }\n            board[N - 1][p] = '.';\n        } else if (d == 'D') {\n            moves.push_back({'D', p});\n            for (int i = N - 1; i > 0; --i) {\n                board[i][p] = board[i - 1][p];\n            }\n            board[0][p] = '.';\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n    board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> board[i];\n    }\n\n    while (count_oni() > 0) {\n        int best_score = -1e9;\n        char best_d = 0;\n        int best_p = -1;\n        int best_k = 0;\n\n        // Check all rows for left shift - check ALL safe shifts\n        for (int r = 0; r < N; ++r) {\n            // Find first Fuku position\n            int fuku_pos = N;\n            for (int j = 0; j < N; ++j) {\n                if (board[r][j] == 'o') {\n                    fuku_pos = j;\n                    break;\n                }\n            }\n            \n            // Try all safe shift amounts\n            for (int k = 1; k <= fuku_pos; ++k) {\n                int oni_removed = 0;\n                for (int jj = 0; jj < k; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                \n                if (oni_removed > 0) {\n                    int score = oni_removed * 10000 - k;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_d = 'L';\n                        best_p = r;\n                        best_k = k;\n                    }\n                }\n            }\n        }\n\n        // Check all rows for right shift\n        for (int r = 0; r < N; ++r) {\n            int fuku_pos = -1;\n            for (int j = N - 1; j >= 0; --j) {\n                if (board[r][j] == 'o') {\n                    fuku_pos = j;\n                    break;\n                }\n            }\n            \n            int max_k = (fuku_pos == -1) ? N : (N - 1 - fuku_pos);\n            for (int k = 1; k <= max_k; ++k) {\n                int oni_removed = 0;\n                for (int jj = N - k; jj < N; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                \n                if (oni_removed > 0) {\n                    int score = oni_removed * 10000 - k;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_d = 'R';\n                        best_p = r;\n                        best_k = k;\n                    }\n                }\n            }\n        }\n\n        // Check all columns for up shift\n        for (int c = 0; c < N; ++c) {\n            int fuku_pos = N;\n            for (int i = 0; i < N; ++i) {\n                if (board[i][c] == 'o') {\n                    fuku_pos = i;\n                    break;\n                }\n            }\n            \n            for (int k = 1; k <= fuku_pos; ++k) {\n                int oni_removed = 0;\n                for (int ii = 0; ii < k; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                \n                if (oni_removed > 0) {\n                    int score = oni_removed * 10000 - k;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_d = 'U';\n                        best_p = c;\n                        best_k = k;\n                    }\n                }\n            }\n        }\n\n        // Check all columns for down shift\n        for (int c = 0; c < N; ++c) {\n            int fuku_pos = -1;\n            for (int i = N - 1; i >= 0; --i) {\n                if (board[i][c] == 'o') {\n                    fuku_pos = i;\n                    break;\n                }\n            }\n            \n            int max_k = (fuku_pos == -1) ? N : (N - 1 - fuku_pos);\n            for (int k = 1; k <= max_k; ++k) {\n                int oni_removed = 0;\n                for (int ii = N - k; ii < N; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                \n                if (oni_removed > 0) {\n                    int score = oni_removed * 10000 - k;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_d = 'D';\n                        best_p = c;\n                        best_k = k;\n                    }\n                }\n            }\n        }\n\n        if (best_p == -1 || best_k == 0) {\n            break;\n        }\n\n        apply_move(best_d, best_p, best_k);\n    }\n\n    for (const auto& m : moves) {\n        cout << m.d << \" \" << m.p << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables to store problem data and state\nint N, L;\nint T[105];\nint A[105], B[105];\nint current_cnt[105];\n\n// Function to simulate the cleaning process and calculate error\nlong long evaluate() {\n    // Reset counts\n    memset(current_cnt, 0, sizeof(current_cnt));\n    int cur = 0;\n    for(int w=0; w<L; ++w) {\n        current_cnt[cur]++;\n        // If count is odd, go to A[cur], else B[cur]\n        if (current_cnt[cur] & 1) cur = A[cur];\n        else cur = B[cur];\n    }\n    // Calculate total absolute error\n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(current_cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // Initialize RNG\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_node(0, N-1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Initialization based on target frequencies T[i]\n    // We want to distribute 2*N edges such that in-degree of i is proportional to T[i]\n    vector<int> targets;\n    targets.reserve(2 * N);\n    vector<int> base_counts(N, 0);\n    long long distributed = 0;\n    for(int i=0; i<N; ++i) {\n        long long k = (2LL * N * T[i]) / L;\n        base_counts[i] = k;\n        distributed += k;\n    }\n    long long remainder = 2 * N - distributed;\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    // Sort indices by T[i] descending to distribute remainder\n    sort(p.begin(), p.end(), [&](int i, int j){\n        return T[i] > T[j];\n    });\n    for(int i=0; i<remainder && i<N; ++i) {\n        base_counts[p[i]]++;\n    }\n    for(int i=0; i<N; ++i) {\n        for(int k=0; k<base_counts[i]; ++k) {\n            targets.push_back(i);\n        }\n    }\n    // Shuffle to avoid deterministic structure\n    shuffle(targets.begin(), targets.end(), rng);\n    // Assign A and B\n    for(int i=0; i<N; ++i) {\n        A[i] = targets[2*i];\n        B[i] = targets[2*i+1];\n    }\n\n    // Initial evaluation\n    long long current_err = evaluate();\n    long long best_err = current_err;\n    vector<int> best_A(N), best_B(N);\n    for(int i=0; i<N; ++i) {\n        best_A[i] = A[i];\n        best_B[i] = B[i];\n    }\n\n    // Simulated Annealing parameters\n    double temp = 1e7;\n    double cooling = 0.999;\n    \n    // Time limit handling\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Save current counts for potential revert\n        vector<int> saved_cnt(N);\n        for(int i=0; i<N; ++i) saved_cnt[i] = current_cnt[i];\n        \n        // Pick node u to modify (biased by error)\n        int u = dist_node(rng);\n        long long total_err = 0;\n        for(int i=0; i<N; ++i) total_err += abs(current_cnt[i] - T[i]);\n        if (total_err > 0) {\n            long long r = rng() % total_err;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = abs(current_cnt[i] - T[i]);\n                sum += w;\n                if (sum > r) {\n                    u = i;\n                    break;\n                }\n            }\n        }\n\n        // Pick target node v (biased by need)\n        int v = dist_node(rng);\n        long long total_need = 0;\n        for(int i=0; i<N; ++i) {\n            if (T[i] > current_cnt[i]) total_need += (T[i] - current_cnt[i]);\n        }\n        if (total_need > 0) {\n            long long r = rng() % total_need;\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                long long w = max(0, T[i] - current_cnt[i]);\n                sum += w;\n                if (sum > r) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n\n        // Propose change: modify A[u] or B[u]\n        int edge_type = dist_node(rng) % 2;\n        int old_target = (edge_type == 0) ? A[u] : B[u];\n        \n        if (edge_type == 0) A[u] = v;\n        else B[u] = v;\n\n        // Evaluate new state\n        long long new_err = evaluate();\n        \n        // Acceptance probability\n        double delta = new_err - current_err;\n        double prob = exp(-delta / temp);\n        \n        if (delta < 0 || dist_prob(rng) < prob) {\n            current_err = new_err;\n            if (current_err < best_err) {\n                best_err = current_err;\n                for(int i=0; i<N; ++i) {\n                    best_A[i] = A[i];\n                    best_B[i] = B[i];\n                }\n            }\n        } else {\n            // Revert change\n            if (edge_type == 0) A[u] = old_target;\n            else B[u] = old_target;\n            // Restore counts\n            for(int i=0; i<N; ++i) current_cnt[i] = saved_cnt[i];\n        }\n        \n        // Cool down\n        temp *= cooling;\n        if (temp < 1e-3) temp = 1e-3;\n    }\n\n    // Output best solution\n    for(int i=0; i<N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    double cx, cy;\n};\n\nstruct Edge {\n    int u, v;\n    int dist;\n    bool queried;\n    bool operator<(const Edge& other) const {\n        if (dist != other.dist) return dist < other.dist;\n        if (queried != other.queried) return queried > other.queried;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\nclass DSU {\npublic:\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) {\n            parent[rootX] = rootY;\n            return true;\n        }\n        return false;\n    }\n};\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<City> cities;\nvector<vector<int>> groups;\nint query_cnt = 0;\nvector<vector<int>> dist_cache;\nvector<vector<bool>> edge_queried;\n\nint calc_dist(int i, int j) {\n    double dx = cities[i].cx - cities[j].cx;\n    double dy = cities[i].cy - cities[j].cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\nint get_dist(int i, int j) {\n    if (i > j) swap(i, j);\n    return dist_cache[i][j];\n}\n\nvoid perform_query(const vector<int>& subset) {\n    if (query_cnt >= Q) return;\n    cout << \"? \" << subset.size();\n    for (int id : subset) {\n        cout << \" \" << id;\n    }\n    cout << endl;\n    query_cnt++;\n}\n\nvector<pair<int, int>> read_query_response(int size) {\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < size - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.push_back({u, v});\n        dist_cache[u][v] = 0;\n        edge_queried[u][v] = true;\n    }\n    return edges;\n}\n\nvector<pair<int, int>> build_mst(const vector<int>& group) {\n    vector<Edge> all_edges;\n    int sz = (int)group.size();\n    \n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            bool queried = edge_queried[u][v];\n            all_edges.push_back({u, v, d, queried});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n\n    DSU dsu(sz);\n    vector<pair<int, int>> mst_edges;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        if (u_idx != -1 && v_idx != -1) {\n            if (dsu.unite(u_idx, v_idx)) {\n                mst_edges.push_back({e.u, e.v});\n                if ((int)mst_edges.size() == sz - 1) break;\n            }\n        }\n    }\n    return mst_edges;\n}\n\nint calc_estimated_cost(const vector<int>& group) {\n    int sz = (int)group.size();\n    if (sz <= 1) return 0;\n    \n    vector<Edge> all_edges;\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            all_edges.push_back({u, v, d, false});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n    \n    DSU dsu(sz);\n    int cost = 0;\n    int edges_count = 0;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        \n        if (u_idx != -1 && v_idx != -1 && dsu.unite(u_idx, v_idx)) {\n            cost += e.dist;\n            edges_count++;\n        }\n    }\n    return cost;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2.0;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2.0;\n    }\n\n    // Pre-calculate all distances\n    dist_cache.assign(N, vector<int>(N, 0));\n    edge_queried.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            dist_cache[i][j] = calc_dist(i, j);\n        }\n    }\n\n    // Sort cities by X then Y\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (cities[a].cx != cities[b].cx) return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n\n    // Assign cities to groups\n    groups.resize(M);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(p[current_idx++]);\n        }\n    }\n\n    // Simple local search - swap boundary cities (very limited iterations)\n    auto start_time = chrono::high_resolution_clock::now();\n    auto time_limit = chrono::high_resolution_clock::now() + chrono::milliseconds(800);\n\n    for (int iter = 0; iter < 3; ++iter) {\n        if (chrono::high_resolution_clock::now() > time_limit) break;\n        bool improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            if (groups[i].empty() || groups[i+1].empty()) continue;\n            \n            int cost_before = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            swap(groups[i].back(), groups[i+1].front());\n            \n            int cost_after = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            if (cost_after < cost_before) {\n                improved = true;\n            } else {\n                swap(groups[i].back(), groups[i+1].front());\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Query Phase\n    vector<vector<pair<int, int>>> group_queried_edges(M);\n\n    // Query small groups first (3 <= size <= L)\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] >= 3 && G[i] <= L) {\n            perform_query(groups[i]);\n            group_queried_edges[i] = read_query_response(G[i]);\n        }\n    }\n\n    // Query large groups\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] > L) {\n            int step = max(2, L / 2);\n            for (int start = 0; start < G[i]; start += step) {\n                if (query_cnt >= Q) break;\n                int end = min(start + L, G[i]);\n                if (end - start < 2) continue;\n                \n                vector<int> subset;\n                for (int k = start; k < end; ++k) {\n                    subset.push_back(groups[i][k]);\n                }\n                \n                perform_query(subset);\n                vector<pair<int, int>> sub_edges = read_query_response(end - start);\n                \n                for (auto& e : sub_edges) {\n                    group_queried_edges[i].push_back(e);\n                }\n            }\n        }\n    }\n\n    // Final Output\n    cout << \"!\" << endl;\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            cout << groups[i][j] << (j == G[i] - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n\n        if (G[i] <= 1) continue;\n\n        vector<pair<int, int>> final_edges = build_mst(groups[i]);\n        \n        for (const auto& e : final_edges) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\n// Directions: U, D, L, R\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dirChar[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nclass SkatingSolver {\nprivate:\n    int n;\n    vector<Point> targets;\n    Point currentPos;\n    vector<vector<bool>> blocks;\n    vector<pair<char, char>> actions;\n    int actionCount = 0;\n    \n    bool isValid(int x, int y) const {\n        return x >= 0 && x < n && y >= 0 && y < n;\n    }\n    \n    bool hasBlock(int x, int y) const {\n        return isValid(x, y) && blocks[x][y];\n    }\n    \n    // Check if we can slide from currentPos in direction d and reach target\n    bool canSlideToPoint(Point target, int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny)) return false;\n            if (nx == target.x && ny == target.y) return true;\n            if (hasBlock(nx, ny)) return false;\n            \n            x = nx;\n            y = ny;\n        }\n    }\n    \n    // Find where we would stop if we slide in direction d\n    Point slideDestination(int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                break;\n            }\n            x = nx;\n            y = ny;\n        }\n        \n        return {x, y};\n    }\n    \n    // Safe action execution with validation\n    bool executeAction(char action, char dir) {\n        if (actionCount >= 2 * N * M) return false;\n        \n        int d = 0;\n        if (dir == 'U') d = 0;\n        else if (dir == 'D') d = 1;\n        else if (dir == 'L') d = 2;\n        else if (dir == 'R') d = 3;\n        \n        if (action == 'M') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                return false;  // Invalid move\n            }\n            currentPos = {nx, ny};\n        } else if (action == 'S') {\n            Point dest = slideDestination(d);\n            if (dest == currentPos) {\n                return false;  // No movement possible\n            }\n            currentPos = dest;\n        } else if (action == 'A') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny)) {\n                return false;  // Can't alter outside grid\n            }\n            blocks[nx][ny] = !blocks[nx][ny];\n        }\n        \n        actions.push_back({action, dir});\n        actionCount++;\n        return true;\n    }\n    \n    // BFS to find path using Move actions\n    vector<pair<char, char>> bfsPath(Point target) {\n        vector<pair<char, char>> path;\n        \n        using State = tuple<int, int, int>;\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<int>> parentDir(n, vector<int>(n, -1));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                // Reconstruct path\n                int cx = x, cy = y;\n                vector<int> dirs;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    dirs.push_back(parentDir[cx][cy]);\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                // Execute moves in correct order\n                for (int i = dirs.size() - 1; i >= 0; i--) {\n                    executeAction('M', dirChar[dirs[i]]);\n                }\n                \n                return path;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parentDir[nx][ny] = dir;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return path;\n    }\n    \n    // Try to reach target using sliding with block placement\n    bool trySlideToTarget(Point target) {\n        for (int d = 0; d < 4; d++) {\n            if (canSlideToPoint(target, d)) {\n                // Check if we need to place a block after target\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                // If there's already a block or we're at boundary, we can slide directly\n                if (!isValid(stopX, stopY) || hasBlock(stopX, stopY)) {\n                    executeAction('S', dirChar[d]);\n                    return true;\n                }\n                \n                // Need to place block after target to stop the slide\n                executeAction('A', dirChar[d]);\n                executeAction('S', dirChar[d]);\n                executeAction('A', dirChar[d]);  // Remove block\n                \n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // Find optimal path to target\n    void findPathToTarget(Point target) {\n        // First try sliding (most efficient)\n        if (trySlideToTarget(target)) {\n            return;\n        }\n        \n        // Fall back to BFS with Move actions\n        bfsPath(target);\n    }\n\npublic:\n    SkatingSolver(int n) : n(n) {\n        blocks.assign(n, vector<bool>(n, false));\n    }\n    \n    void setInitialPosition(int x, int y) {\n        currentPos = {x, y};\n    }\n    \n    void addTarget(int x, int y) {\n        targets.push_back({x, y});\n    }\n    \n    void solve() {\n        for (const auto& target : targets) {\n            if (actionCount >= 2 * N * M) break;\n            \n            findPathToTarget(target);\n        }\n    }\n    \n    void output() const {\n        for (const auto& action : actions) {\n            cout << action.first << \" \" << action.second << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    SkatingSolver solver(n);\n    \n    int x, y;\n    cin >> x >> y;\n    solver.setInitialPosition(x, y);\n    \n    for (int i = 0; i < m; i++) {\n        cin >> x >> y;\n        solver.addTarget(x, y);\n    }\n    \n    solver.solve();\n    solver.output();\n    \n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\ndouble calculate_p(int r, int s) {\n    if (s == 0) return 0.0;\n    double ratio = (double)min(r, s) / max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble calculate_total_p(const vector<Company>& companies) {\n    double total = 0;\n    for (auto& c : companies) {\n        int s = (c.c - c.a) * (c.d - c.b);\n        total += calculate_p(c.r, s);\n    }\n    return total;\n}\n\nbool can_place(const vector<tuple<int, int, int, int>>& placed, int a, int b, int c, int d) {\n    for (auto& [pa, pb, pc, pd] : placed) {\n        if (!(c <= pa || a >= pc || d <= pb || b >= pd)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid place_rectangles(vector<Company>& companies, const vector<int>& order) {\n    vector<tuple<int, int, int, int>> placed;\n    \n    for (int idx : order) {\n        int x = companies[idx].x;\n        int y = companies[idx].y;\n        int r = companies[idx].r;\n        \n        // Find all dimension pairs (w, h) such that w * h = r\n        vector<pair<int, int>> dims;\n        for (int w = 1; w * w <= r; w++) {\n            if (r % w == 0) {\n                dims.push_back({w, r / w});\n                if (w * w != r) {\n                    dims.push_back({r / w, w});\n                }\n            }\n        }\n        \n        // Prefer more square-like rectangles (better packing)\n        sort(dims.begin(), dims.end(), [](auto& p1, auto& p2) {\n            return abs(p1.first - p1.second) < abs(p2.first - p2.second);\n        });\n        \n        bool placed_rect = false;\n        for (auto [w, h] : dims) {\n            // Try all positions that contain (x, y)\n            for (int offset_x = 0; offset_x < w && !placed_rect; offset_x++) {\n                for (int offset_y = 0; offset_y < h && !placed_rect; offset_y++) {\n                    int a = x - offset_x;\n                    int b = y - offset_y;\n                    int c = a + w;\n                    int d = b + h;\n                    \n                    if (a >= 0 && c <= 10000 && b >= 0 && d <= 10000) {\n                        if (can_place(placed, a, b, c, d)) {\n                            companies[idx].a = a;\n                            companies[idx].b = b;\n                            companies[idx].c = c;\n                            companies[idx].d = d;\n                            placed.emplace_back(a, b, c, d);\n                            placed_rect = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        companies[i].a = 0;\n        companies[i].b = 0;\n        companies[i].c = 0;\n        companies[i].d = 0;\n    }\n    \n    vector<Company> best_companies = companies;\n    double best_p = -1;\n    \n    // Strategy 1: Sort by r (largest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r > current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 2: Sort by position (x then y)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].x != current[j].x) return current[i].x < current[j].x;\n            return current[i].y < current[j].y;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 3: Sort by position (y then x)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].y != current[j].y) return current[i].y < current[j].y;\n            return current[i].x < current[j].x;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 4: Random order (multiple times)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 100; trial++) {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 5: Sort by r (smallest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r < current[j].r;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 6: Sort by distance from center\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Strategy 7: Sort by r * distance from center (combined heuristic)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            long long d1 = 1LL * (current[i].x - 5000) * (current[i].x - 5000) + \n                           1LL * (current[i].y - 5000) * (current[i].y - 5000);\n            long long d2 = 1LL * (current[j].x - 5000) * (current[j].x - 5000) + \n                           1LL * (current[j].y - 5000) * (current[j].y - 5000);\n            if (current[i].r != current[j].r) return current[i].r > current[j].r;\n            return d1 < d2;\n        });\n        place_rectangles(current, order);\n        double p = calculate_total_p(current);\n        if (p > best_p) {\n            best_p = p;\n            best_companies = current;\n        }\n    }\n    \n    // Output best solution\n    for (int i = 0; i < n; i++) {\n        cout << best_companies[i].a << \" \" << best_companies[i].b << \" \" \n             << best_companies[i].c << \" \" << best_companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Global problem data\nint si, sj;\nint t[50][50];\nint p[50][50];\nint adj[50][50][4];\nint adj_count[50][50];\nchar move_char[4] = {'U', 'D', 'L', 'R'};\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\n// Global path state\nint path_r[2505];\nint path_c[2505];\nchar path_moves[2505];\nbool visited_tile[2505];\nint path_len;\nlong long current_score;\n\n// Tabu list\nint tabu_count[2505];\n\n// Best path\nlong long best_score;\nstring best_moves;\n\n// Tile region tracking (5x5 grid)\nint tile_region[2505];\nbool region_visited[25][25];\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < 50 && c >= 0 && c < 50;\n}\n\nvoid precompute_adj() {\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            adj_count[i][j] = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (is_valid(ni, nj)) {\n                    adj[i][j][adj_count[i][j]++] = k;\n                }\n            }\n        }\n    }\n}\n\nvoid save_best() {\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_moves.clear();\n        best_moves.reserve(path_len - 1);\n        for (int i = 0; i < path_len - 1; ++i) {\n            best_moves += path_moves[i];\n        }\n    }\n}\n\nvoid reset_state() {\n    memset(visited_tile, 0, sizeof(visited_tile));\n    memset(tabu_count, 0, sizeof(tabu_count));\n    memset(region_visited, 0, sizeof(region_visited));\n    path_len = 0;\n    current_score = 0;\n}\n\nvoid mark_region(int r, int c) {\n    region_visited[r / 5][c / 5] = true;\n}\n\nint get_region(int r, int c) {\n    return (r / 5) * 10 + (c / 5);\n}\n\n// Count available neighbors (not tabu)\nint count_available_neighbors(int r, int c) {\n    int count = 0;\n    for (int k = 0; k < adj_count[r][c]; ++k) {\n        int dir = adj[r][c][k];\n        int nr = r + di[dir];\n        int nc = c + dj[dir];\n        int tile = t[nr][nc];\n        if (!visited_tile[tile] && tabu_count[tile] == 0) {\n            count++;\n        }\n    }\n    return count;\n}\n\n// Count unvisited tiles reachable from position\nint count_reachable_tiles(int r, int c, int depth, int* visited_check, int check_id) {\n    if (depth <= 0) return 0;\n    if (visited_check[t[r][c]] == check_id) return 0;\n    visited_check[t[r][c]] = check_id;\n    \n    int count = 1;\n    for (int k = 0; k < adj_count[r][c]; ++k) {\n        int dir = adj[r][c][k];\n        int nr = r + di[dir];\n        int nc = c + dj[dir];\n        int tile = t[nr][nc];\n        if (!visited_tile[tile] && visited_check[tile] != check_id) {\n            count += count_reachable_tiles(nr, nc, depth - 1, visited_check, check_id);\n        }\n    }\n    return count;\n}\n\nint move_score(int nr, int nc, int tile, int phase, int reachable_check[2505], int check_id) {\n    int score = p[nr][nc];\n    \n    // Connectivity bonus\n    int neighbors = count_available_neighbors(nr, nc);\n    if (neighbors >= 3) score += 45;\n    else if (neighbors >= 2) score += 30;\n    else if (neighbors == 1) score += 15;\n    else score -= 300;\n    \n    // Tabu penalty\n    if (tabu_count[tile] > 0) score -= 40;\n    \n    // Distance from start bonus\n    int dist = abs(nr - si) + abs(nc - sj);\n    if (dist > 20) score += 20;\n    if (dist > 30) score += 20;\n    \n    // Region exploration bonus\n    if (phase < 150) {\n        int region = get_region(nr, nc);\n        if (!region_visited[region / 10][region % 10]) {\n            score += 35;\n        }\n    }\n    \n    // Reachability bonus (quick check)\n    if (phase < 200) {\n        int reachable = count_reachable_tiles(nr, nc, 3, reachable_check, check_id);\n        if (reachable > 10) score += 25;\n        else if (reachable > 5) score += 15;\n    }\n    \n    // Phase-based adjustment\n    if (phase > 250) {\n        score += p[nr][nc] * 2;\n    }\n    \n    return score;\n}\n\nvoid run_single_path(mt19937& rng, uniform_real_distribution<double>& prob_dist, uniform_real_distribution<double>& prob_dist2, int mode) {\n    reset_state();\n    \n    // Initialize tile regions\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            tile_region[t[i][j]] = get_region(i, j);\n        }\n    }\n\n    // Start from initial position\n    path_r[0] = si;\n    path_c[0] = sj;\n    visited_tile[t[si][sj]] = true;\n    mark_region(si, sj);\n    path_len = 1;\n    current_score = p[si][sj];\n\n    save_best();\n\n    int stuck_steps = 0;\n    int backtrack_count = 0;\n    int no_improve_count = 0;\n    int last_best_len = path_len;\n    int last_best_score = current_score;\n    int check_id = 1;\n    int reachable_check[2505] = {0};\n    \n    // SA temperature - higher for exploration mode\n    double temp = (mode == 0) ? 200.0 : 100.0;\n    int tabu_duration = (mode == 0) ? 35 : 55;\n\n    while (path_len > 0 && stuck_steps < 300) {\n        int r = path_r[path_len - 1];\n        int c = path_c[path_len - 1];\n        \n        // Decay tabu\n        for (int i = 0; i < 2500; ++i) {\n            if (tabu_count[i] > 0) tabu_count[i]--;\n        }\n        \n        // Find valid neighbors with scores\n        struct Candidate {\n            int dir;\n            int nr, nc;\n            int tile;\n            int score;\n        };\n        \n        vector<Candidate> candidates;\n        for (int k = 0; k < adj_count[r][c]; ++k) {\n            int dir = adj[r][c][k];\n            int nr = r + di[dir];\n            int nc = c + dj[dir];\n            int tile = t[nr][nc];\n            \n            if (!visited_tile[tile]) {\n                Candidate cand;\n                cand.dir = dir;\n                cand.nr = nr;\n                cand.nc = nc;\n                cand.tile = tile;\n                cand.score = move_score(nr, nc, tile, path_len, reachable_check, check_id++);\n                candidates.push_back(cand);\n            }\n        }\n\n        if (!candidates.empty()) {\n            // Sort by score\n            sort(candidates.begin(), candidates.end(), \n                [](const Candidate& a, const Candidate& b) {\n                    return a.score > b.score;\n                });\n\n            // Adaptive exploration rate\n            double exploration_rate = 0.05 + (stuck_steps * 0.003);\n            exploration_rate = min(mode == 0 ? 0.90 : 0.80, exploration_rate);\n            \n            int chosen_idx = 0;\n            if (candidates.size() > 1 && prob_dist(rng) < exploration_rate) {\n                // SA-based weighted selection\n                double total_weight = 0;\n                vector<double> weights;\n                for (size_t i = 0; i < candidates.size(); ++i) {\n                    double weight = max(1.0, (double)(candidates[i].score + 250));\n                    weight = exp(weight / temp);\n                    total_weight += weight;\n                    weights.push_back(total_weight);\n                }\n                \n                double r_val = prob_dist2(rng) * total_weight;\n                for (size_t i = 0; i < weights.size(); ++i) {\n                    if (r_val <= weights[i]) {\n                        chosen_idx = i;\n                        break;\n                    }\n                }\n            }\n\n            // Extend path\n            Candidate& chosen = candidates[chosen_idx];\n            path_r[path_len] = chosen.nr;\n            path_c[path_len] = chosen.nc;\n            path_moves[path_len - 1] = move_char[chosen.dir];\n            visited_tile[chosen.tile] = true;\n            tabu_count[chosen.tile] = tabu_duration;\n            mark_region(chosen.nr, chosen.nc);\n            path_len++;\n            current_score += p[chosen.nr][chosen.nc];\n            \n            stuck_steps = 0;\n            \n            // Track improvement\n            if (path_len > last_best_len || current_score > last_best_score) {\n                last_best_len = path_len;\n                last_best_score = current_score;\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n            }\n            \n            save_best();\n            \n            // Adaptive temperature cooling\n            if (no_improve_count > 100) {\n                temp *= 0.90;\n            } else if (no_improve_count > 50) {\n                temp *= 0.95;\n            } else {\n                temp *= 0.992;\n            }\n            if (temp < 0.5) temp = 0.5;\n        } else {\n            // No valid moves - backtrack\n            stuck_steps++;\n            no_improve_count++;\n            \n            if (path_len <= 1) break;\n            \n            // Multi-depth backtracking when stuck\n            int backtrack_depth = min(5, stuck_steps / 20);\n            if (backtrack_depth < 1) backtrack_depth = 1;\n            \n            for (int bd = 0; bd < backtrack_depth && path_len > 1; bd++) {\n                int last_r = path_r[path_len - 1];\n                int last_c = path_c[path_len - 1];\n                int last_tile = t[last_r][last_c];\n                \n                path_len--;\n                current_score -= p[last_r][last_c];\n                visited_tile[last_tile] = false;\n                \n                backtrack_count++;\n            }\n            \n            // If we've backtracked too much or no improvement, restart\n            if (backtrack_count > 150 || no_improve_count > 350) {\n                break;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> t[i][j];\n        }\n    }\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    precompute_adj();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_real_distribution<double> prob_dist2(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1995);\n\n    best_score = -1;\n    best_moves.clear();\n\n    // Multiple restarts with two modes\n    int restart = 0;\n    int mode = 0;\n    while (chrono::steady_clock::now() < end_time && restart < 5000) {\n        restart++;\n        // Alternate between exploration and exploitation modes\n        mode = (restart % 2 == 0) ? 1 : 0;\n        run_single_path(rng, prob_dist, prob_dist2, mode);\n    }\n\n    cout << best_moves << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nconst int N = 30;\nconst double INIT_W = 5000.0;\nconst double K_INIT = 15.0; // Initial blending factor\nconst double K_FINAL = 3.0; // Final blending factor\nconst double K_DECAY = 0.001; // Decay rate per query\n\nstruct Stats {\n    double log_sum = 0.0;\n    int cnt = 0;\n};\n\nStats h_stats[N][N];\nStats v_stats[N][N];\nStats h_avg_stats[N];\nStats v_avg_stats[N];\n\ndouble get_weight(const Stats& s) {\n    if (s.cnt == 0) return INIT_W;\n    return INIT_W * exp(s.log_sum / s.cnt);\n}\n\ndouble get_h_weight(int i, int j, double k) {\n    double w_edge = get_weight(h_stats[i][j]);\n    double w_avg = get_weight(h_avg_stats[i]);\n    double edge_weight = h_stats[i][j].cnt;\n    return (edge_weight * w_edge + k * w_avg) / (edge_weight + k);\n}\n\ndouble get_v_weight(int i, int j, double k) {\n    double w_edge = get_weight(v_stats[i][j]);\n    double w_avg = get_weight(v_avg_stats[j]);\n    double edge_weight = v_stats[i][j].cnt;\n    return (edge_weight * w_edge + k * w_avg) / (edge_weight + k);\n}\n\nvoid update_h(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    h_stats[i][j].log_sum += log(ratio);\n    h_stats[i][j].cnt++;\n    h_avg_stats[i].log_sum += log(ratio);\n    h_avg_stats[i].cnt++;\n}\n\nvoid update_v(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    v_stats[i][j].log_sum += log(ratio);\n    v_stats[i][j].cnt++;\n    v_avg_stats[j].log_sum += log(ratio);\n    v_avg_stats[j].cnt++;\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int queries = 1000;\n    double k = K_INIT;\n    \n    for (int q = 0; q < queries; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // Dijkstra\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n        vector<vector<char>> move_dir(N, vector<char>(N, 0));\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[si][sj] = 0.0;\n        pq.push({0.0, si, sj});\n\n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        char dirs[] = {'U', 'D', 'L', 'R'};\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n\n            if (current.dist > dist[r][c]) continue;\n            if (r == ti && c == tj) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    double w = 0.0;\n                    if (d == 0) { // U\n                        w = get_v_weight(nr, nc, k);\n                    } else if (d == 1) { // D\n                        w = get_v_weight(r, c, k);\n                    } else if (d == 2) { // L\n                        w = get_h_weight(r, nc, k);\n                    } else if (d == 3) { // R\n                        w = get_h_weight(r, c, k);\n                    }\n\n                    if (dist[r][c] + w < dist[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + w;\n                        parent[nr][nc] = {r, c};\n                        move_dir[nr][nc] = dirs[d];\n                        pq.push({dist[nr][nc], nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path\n        string path = \"\";\n        int curr_r = ti, curr_c = tj;\n        double path_est = 0.0;\n        vector<pair<int, int>> path_edges_h;\n        vector<pair<int, int>> path_edges_v;\n\n        while (curr_r != si || curr_c != sj) {\n            int pr = parent[curr_r][curr_c].first;\n            int pc = parent[curr_r][curr_c].second;\n            char d = move_dir[curr_r][curr_c];\n            path += d;\n\n            if (d == 'U') {\n                path_edges_v.push_back({curr_r, curr_c});\n                path_est += get_v_weight(curr_r, curr_c, k);\n            } else if (d == 'D') {\n                path_edges_v.push_back({pr, pc});\n                path_est += get_v_weight(pr, pc, k);\n            } else if (d == 'L') {\n                path_edges_h.push_back({pr, curr_c});\n                path_est += get_h_weight(pr, curr_c, k);\n            } else if (d == 'R') {\n                path_edges_h.push_back({pr, pc});\n                path_est += get_h_weight(pr, pc, k);\n            }\n\n            curr_r = pr;\n            curr_c = pc;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << endl;\n\n        int result;\n        cin >> result;\n\n        if (path_est > 0) {\n            double ratio = (double)result / path_est;\n            if (ratio <= 0) ratio = 1.0;\n\n            for (auto& e : path_edges_h) {\n                update_h(e.first, e.second, ratio);\n            }\n            for (auto& e : path_edges_v) {\n                update_v(e.first, e.second, ratio);\n            }\n        }\n        \n        // Decay K over time\n        k = max(K_FINAL, k - K_DECAY * 1000);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\nconst int NUM_CHARS = 8;\n\nint matrix[N][N];\nint string_counts[MAX_M];\nint total_matched = 0;\nint M;\n\nbitset<10000> valid_placements[MAX_M];\n\nstruct PlacementInfo {\n    int s;\n    int id;\n};\nvector<PlacementInfo> cell_active[N * N];\nvector<PlacementInfo> potential_lists[NUM_CHARS][N * N];\n\ninline int encode_id(int r, int c, int dir, int offset) {\n    return dir * N * N * MAX_LEN + r * N * MAX_LEN + c * MAX_LEN + offset;\n}\n\ninline void decode_id(int id, int &r, int &c, int &dir, int &offset) {\n    offset = id % MAX_LEN;\n    id /= MAX_LEN;\n    c = id % N;\n    id /= N;\n    r = id % N;\n    dir = id / N;\n}\n\nvector<string> strings;\nvector<int> string_lens;\n\nmt19937 rng;\nuniform_int_distribution<int> dist_char(0, NUM_CHARS - 1);\nuniform_int_distribution<int> dist_cell(0, N * N - 1);\n\nbool is_placement_valid(int s, int r, int c, int dir) {\n    int len = string_lens[s];\n    const string &str = strings[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        if (matrix[cr][cc] != (str[k] - 'A')) return false;\n    }\n    return true;\n}\n\nvoid add_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (valid_placements[s].test(id)) return;\n\n    valid_placements[s].set(id);\n    string_counts[s]++;\n    if (string_counts[s] == 1) total_matched++;\n\n    int len = string_lens[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        cell_active[cr * N + cc].push_back({s, id});\n    }\n}\n\nvoid remove_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (!valid_placements[s].test(id)) return;\n\n    valid_placements[s].reset(id);\n    string_counts[s]--;\n    if (string_counts[s] == 0) total_matched--;\n}\n\nvoid init_potential_lists() {\n    for (int ch = 0; ch < NUM_CHARS; ++ch) {\n        for (int c = 0; c < N * N; ++c) {\n            potential_lists[ch][c].clear();\n        }\n    }\n    \n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        const string &str = strings[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_c = (c - k);\n                    if (start_c < 0) start_c += N;\n                    int id = encode_id(r, start_c, 0, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_r = (r - k);\n                    if (start_r < 0) start_r += N;\n                    int id = encode_id(start_r, c, 1, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n            }\n        }\n    }\n}\n\nvoid clear_state() {\n    for (int s = 0; s < M; ++s) {\n        valid_placements[s].reset();\n        string_counts[s] = 0;\n    }\n    total_matched = 0;\n    \n    for (int c = 0; c < N * N; ++c) {\n        cell_active[c].clear();\n    }\n}\n\nvoid init_state() {\n    clear_state();\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            matrix[i][j] = dist_char(rng);\n        }\n    }\n\n    for (int s = 0; s < M; ++s) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (is_placement_valid(s, r, c, 0)) {\n                    add_placement(s, r, c, 0);\n                }\n                if (is_placement_valid(s, r, c, 1)) {\n                    add_placement(s, r, c, 1);\n                }\n            }\n        }\n    }\n}\n\nbool update_cell(int r, int c, int new_char) {\n    int old_char = matrix[r][c];\n    if (old_char == new_char) return true;\n\n    int cell_idx = r * N + c;\n\n    for (auto &p : cell_active[cell_idx]) {\n        if (valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            \n            int k = -1;\n            if (tdir == 0) {\n                k = (c - tc);\n                if (k < 0) k += N;\n            } else {\n                k = (r - tr);\n                if (k < 0) k += N;\n            }\n            \n            if (k >= string_lens[p.s]) continue;\n\n            int required_char = strings[p.s][k] - 'A';\n            if (required_char != new_char) {\n                remove_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    for (auto &p : potential_lists[new_char][cell_idx]) {\n        if (!valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            if (is_placement_valid(p.s, tr, tc, tdir)) {\n                add_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    matrix[r][c] = new_char;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_input;\n    cin >> N_input >> M;\n    \n    strings.resize(M);\n    string_lens.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        string_lens[i] = strings[i].length();\n    }\n\n    init_potential_lists();\n\n    // Fast SA with limited iterations\n    rng.seed(1337);\n    init_state();\n    \n    double temperature = 80.0;\n    double cooling_rate = 0.998;\n    int max_iter = 8000; // Reduced for speed\n    \n    for (int iter = 0; iter < max_iter && temperature > 0.001; ++iter) {\n        int cell = dist_cell(rng);\n        int r = cell / N;\n        int c = cell % N;\n        \n        int old_char = matrix[r][c];\n        int new_char = dist_char(rng);\n        \n        int old_total_matched = total_matched;\n        \n        update_cell(r, c, new_char);\n        \n        double delta_score = total_matched - old_total_matched;\n        \n        double prob = 1.0;\n        if (delta_score < 0) {\n            prob = exp(delta_score / temperature);\n        }\n        \n        double rand_val = (double)dist_char(rng) / (double)NUM_CHARS;\n        if (rand_val >= prob) {\n            update_cell(r, c, old_char);\n        }\n\n        temperature *= cooling_rate;\n    }\n\n    // Output solution\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int ch = matrix[i][j];\n            if (ch < 0) ch = 0;\n            if (ch >= NUM_CHARS) ch = NUM_CHARS - 1;\n            cout << (char)('A' + ch);\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> roads;\nint total_roads = 0;\n\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && grid[i][j] != '#';\n}\n\nbool isVisible(int ci, int cj, int ti, int tj) {\n    if (ci == ti) {\n        for (int j = min(cj, tj); j <= max(cj, tj); j++) {\n            if (grid[ci][j] == '#') return false;\n        }\n        return true;\n    }\n    if (cj == tj) {\n        for (int i = min(ci, ti); i <= max(ci, ti); i++) {\n            if (grid[i][cj] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\nint getCost(int i, int j) {\n    return grid[i][j] - '0';\n}\n\n// BFS for shortest path\nvector<pair<int,int>> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {{si, sj}};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    queue<pair<int,int>> q;\n    \n    dist[si][sj] = 0;\n    q.push({si, sj});\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) {\n            vector<pair<int,int>> path;\n            int i = ti, j = tj;\n            while (!(i == si && j == sj)) {\n                path.push_back({i, j});\n                auto [pi, pj] = parent[i][j];\n                i = pi; j = pj;\n            }\n            path.push_back({si, sj});\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (isValid(ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                parent[ni][nj] = {ci, cj};\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    return {{si, sj}, {ti, tj}};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                roads.push_back({i, j});\n            }\n        }\n    }\n    total_roads = roads.size();\n    \n    // Precompute visibility for each road square\n    vector<vector<vector<int>>> visible(N, vector<vector<int>>(N));\n    vector<vector<int>> roadIndex(N, vector<int>(N, -1));\n    \n    int idx = 0;\n    for (const auto& [i, j] : roads) {\n        roadIndex[i][j] = idx++;\n    }\n    \n    for (const auto& [i, j] : roads) {\n        for (const auto& [ti, tj] : roads) {\n            if (isVisible(i, j, ti, tj)) {\n                visible[i][j].push_back(roadIndex[ti][tj]);\n            }\n        }\n    }\n    \n    // Track covered squares using boolean array\n    vector<bool> covered(total_roads, false);\n    int covered_count = 0;\n    for (int k : visible[si][sj]) {\n        if (!covered[k]) {\n            covered[k] = true;\n            covered_count++;\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    path.push_back({si, sj});\n    int ci = si, cj = sj;\n    \n    // Greedy coverage with more iterations\n    int max_iter = 8000;\n    int iter = 0;\n    int stuck_count = 0;\n    \n    while (covered_count < total_roads && iter < max_iter) {\n        iter++;\n        \n        int best_d = -1;\n        int max_new = -1;\n        \n        // Check all 4 adjacent directions\n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (!isValid(ni, nj)) continue;\n            \n            int new_count = 0;\n            for (int k : visible[ni][nj]) {\n                if (!covered[k]) {\n                    new_count++;\n                }\n            }\n            \n            if (new_count > max_new) {\n                max_new = new_count;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1 || max_new == 0) {\n            // No new coverage from adjacent, try BFS to find best position\n            stuck_count++;\n            \n            // Only do long-range search every few times to save time\n            if (stuck_count % 3 == 0) {\n                int best_target_i = -1, best_target_j = -1;\n                int best_new = -1;\n                \n                // Check all road squares for potential targets\n                for (const auto& [ti, tj] : roads) {\n                    if (!covered[roadIndex[ti][tj]]) {\n                        int new_vis = 0;\n                        for (int k : visible[ti][tj]) {\n                            if (!covered[k]) {\n                                new_vis++;\n                            }\n                        }\n                        if (new_vis > best_new) {\n                            best_new = new_vis;\n                            best_target_i = ti;\n                            best_target_j = tj;\n                        }\n                    }\n                }\n                \n                if (best_target_i != -1 && best_new > 0) {\n                    auto subPath = bfsPath(ci, cj, best_target_i, best_target_j);\n                    for (size_t k = 1; k < subPath.size(); k++) {\n                        path.push_back(subPath[k]);\n                        ci = subPath[k].first;\n                        cj = subPath[k].second;\n                        for (int idx : visible[ci][cj]) {\n                            if (!covered[idx]) {\n                                covered[idx] = true;\n                                covered_count++;\n                            }\n                        }\n                    }\n                    stuck_count = 0;\n                    continue;\n                }\n            }\n            \n            // Random move if still stuck\n            best_d = rand() % 4;\n            while (!isValid(ci + di[best_d], cj + dj[best_d])) {\n                best_d = (best_d + 1) % 4;\n            }\n        }\n        \n        // Move in best direction\n        ci += di[best_d];\n        cj += dj[best_d];\n        path.push_back({ci, cj});\n        \n        // Update coverage\n        for (int k : visible[ci][cj]) {\n            if (!covered[k]) {\n                covered[k] = true;\n                covered_count++;\n            }\n        }\n    }\n    \n    // Return to start\n    auto returnPath = bfsPath(ci, cj, si, sj);\n    for (size_t i = 1; i < returnPath.size(); i++) {\n        path.push_back(returnPath[i]);\n    }\n    \n    // Ensure ends at start\n    if (path.back().first != si || path.back().second != sj) {\n        path.push_back({si, sj});\n    }\n    \n    // Remove consecutive duplicates\n    vector<pair<int,int>> cleanedPath;\n    for (size_t i = 0; i < path.size(); i++) {\n        if (i == 0 || path[i] != path[i-1]) {\n            cleanedPath.push_back(path[i]);\n        }\n    }\n    \n    // Ensure still ends at start\n    if (cleanedPath.back().first != si || cleanedPath.back().second != sj) {\n        cleanedPath.push_back({si, sj});\n    }\n    \n    // Convert to movement string\n    string result;\n    for (size_t i = 1; i < cleanedPath.size(); i++) {\n        int di_val = cleanedPath[i].first - cleanedPath[i-1].first;\n        int dj_val = cleanedPath[i].second - cleanedPath[i-1].second;\n        \n        if (di_val == -1) result += 'U';\n        else if (di_val == 1) result += 'D';\n        else if (dj_val == -1) result += 'L';\n        else if (dj_val == 1) result += 'R';\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int status; // 0: available, 1: assigned, 2: done\n    int start_day;\n    int indegree;\n    int outdegree;\n};\n\nstruct Member {\n    int id;\n    vector<double> estimate;\n    vector<double> confidence;\n    int current_task;\n    int tasks_completed;\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<vector<int>> adj;\nint day = 0;\n\ndouble calculate_work(int task_idx, int member_idx) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            work += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n        }\n    }\n    return work;\n}\n\ndouble calculate_cost(int task_idx, int member_idx) {\n    double work = calculate_work(task_idx, member_idx);\n    \n    // Add small uncertainty penalty for low confidence\n    double uncertainty = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            uncertainty += (1.0 / (1.0 + members[member_idx].confidence[k]));\n        }\n    }\n    \n    double expected_time = max(1.0, work);\n    expected_time += uncertainty * 0.5; // Smaller penalty\n    \n    return expected_time;\n}\n\nvoid update_skills(int member_idx, int task_idx, int t) {\n    int& completed = members[member_idx].tasks_completed;\n    completed++;\n    \n    // If completed in 1 day, we know w=0, so s >= d for all skills\n    if (t == 1) {\n        for (int k = 0; k < K; ++k) {\n            if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n                members[member_idx].estimate[k] = tasks[task_idx].d[k];\n            }\n        }\n    }\n    \n    // Calculate predicted work\n    double work_pred = 0;\n    vector<int> contributing_skills;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            work_pred += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n            contributing_skills.push_back(k);\n        }\n    }\n    \n    // Observed work\n    double work_obs = 0;\n    if (t > 1) {\n        work_obs = t;\n    }\n    \n    // Update estimates with moderate learning rate\n    if (contributing_skills.size() > 0) {\n        double diff = work_pred - work_obs;\n        // Learning rate: moderate, not too aggressive\n        double learning_rate = 0.5 / (1.0 + completed * 0.2);\n        \n        for (int k : contributing_skills) {\n            double adjust = diff / contributing_skills.size() * learning_rate;\n            members[member_idx].estimate[k] -= adjust;\n            members[member_idx].estimate[k] = max(0.0, members[member_idx].estimate[k]);\n        }\n    }\n    \n    // Increase confidence for all skills\n    for (int k = 0; k < K; ++k) {\n        members[member_idx].confidence[k] += 0.8;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n        }\n        tasks[i].status = 0;\n        tasks[i].start_day = 0;\n        tasks[i].indegree = 0;\n        tasks[i].outdegree = 0;\n    }\n\n    adj.resize(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        tasks[v].indegree++;\n        tasks[u].outdegree++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].estimate.assign(K, 0.0);\n        members[i].confidence.assign(K, 0.0);\n        members[i].current_task = -1;\n        members[i].tasks_completed = 0;\n    }\n\n    while (true) {\n        day++;\n        if (day > 2000) break;\n\n        // Identify free members\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (members[j].current_task == -1) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Identify available tasks (status == 0 AND indegree == 0)\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (tasks[i].status == 0 && tasks[i].indegree == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // If no available tasks, output nothing\n        if (available_tasks.empty()) {\n            cout << \"0\\n\" << flush;\n            \n            int n_completions;\n            cin >> n_completions;\n            if (n_completions == -1) break;\n\n            vector<int> completed_members(n_completions);\n            for (int i = 0; i < n_completions; ++i) {\n                cin >> completed_members[i];\n                --completed_members[i];\n            }\n\n            for (int j : completed_members) {\n                int task_idx = members[j].current_task;\n                if (task_idx != -1) {\n                    int t = day - tasks[task_idx].start_day + 1;\n                    update_skills(j, task_idx, t);\n                    tasks[task_idx].status = 2;\n                    members[j].current_task = -1;\n                    \n                    for (int v : adj[task_idx]) {\n                        tasks[v].indegree--;\n                    }\n                }\n            }\n            continue;\n        }\n\n        // Create assignment candidates\n        struct Assignment {\n            double cost;\n            int task_idx;\n            int member_idx;\n            int outdegree;\n            int member_tasks;\n            bool operator<(const Assignment& other) const {\n                // Primary: minimize cost\n                if (abs(cost - other.cost) > 1e-6) return cost < other.cost;\n                // Secondary: maximize outdegree (unlock more tasks)\n                if (outdegree != other.outdegree) return outdegree > other.outdegree;\n                // Tertiary: prefer members with fewer completed tasks (exploration)\n                return member_tasks < other.member_tasks;\n            }\n        };\n\n        vector<Assignment> candidates;\n        candidates.reserve(free_members.size() * available_tasks.size());\n\n        for (int j : free_members) {\n            for (int i : available_tasks) {\n                candidates.push_back({\n                    calculate_cost(i, j),\n                    i,\n                    j,\n                    tasks[i].outdegree,\n                    members[j].tasks_completed\n                });\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n\n        // Greedy assignment\n        vector<pair<int, int>> output_assignments;\n        vector<int> assigned_task(N, -1);\n        vector<int> assigned_member(M, -1);\n\n        for (const auto& cand : candidates) {\n            if (assigned_task[cand.task_idx] == -1 && assigned_member[cand.member_idx] == -1) {\n                assigned_task[cand.task_idx] = cand.task_idx;\n                assigned_member[cand.member_idx] = cand.member_idx;\n                output_assignments.push_back({cand.member_idx, cand.task_idx});\n                \n                tasks[cand.task_idx].status = 1;\n                tasks[cand.task_idx].start_day = day;\n                members[cand.member_idx].current_task = cand.task_idx;\n            }\n        }\n\n        // Output\n        cout << output_assignments.size();\n        for (const auto& p : output_assignments) {\n            cout << \" \" << (p.first + 1) << \" \" << (p.second + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completions\n        int n_completions;\n        cin >> n_completions;\n        if (n_completions == -1) break;\n\n        vector<int> completed_members(n_completions);\n        for (int i = 0; i < n_completions; ++i) {\n            cin >> completed_members[i];\n            --completed_members[i];\n        }\n\n        for (int j : completed_members) {\n            int task_idx = members[j].current_task;\n            if (task_idx != -1) {\n                int t = day - tasks[task_idx].start_day + 1;\n                update_skills(j, task_idx, t);\n                tasks[task_idx].status = 2;\n                members[j].current_task = -1;\n                \n                for (int v : adj[task_idx]) {\n                    tasks[v].indegree--;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <vector>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n    int orderId; // -1 for office\n    int type; // 0 for pickup, 1 for dropoff, 2 for office\n};\n\nint dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nclass Solver {\nprivate:\n    vector<Order> orders;\n    int ox = 400, oy = 400;\n    vector<int> selected;\n    vector<bool> isSelected;\n    vector<int> notSelected;\n    vector<Point> route;\n    int currentCost;\n    int bestCost;\n    vector<Point> bestRoute;\n    vector<int> bestSelected;\n    \n    mt19937 gen;\n    uniform_real_distribution<double> randDist;\n    \npublic:\n    Solver() {\n        gen.seed(chrono::steady_clock::now().time_since_epoch().count());\n        randDist = uniform_real_distribution<double>(0.0, 1.0);\n    }\n    \n    void readInput() {\n        orders.resize(1000);\n        for (int i = 0; i < 1000; i++) {\n            orders[i].id = i + 1;\n            cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n        }\n    }\n    \n    void init() {\n        selected.clear();\n        isSelected.assign(1000, false);\n        notSelected.clear();\n        \n        // Better initial selection: prioritize orders with short total travel\n        vector<pair<int, int>> scoreList;\n        for (int i = 0; i < 1000; i++) {\n            int pickupDist = dist(orders[i].a, orders[i].b, ox, oy);\n            int dropoffDist = dist(orders[i].c, orders[i].d, ox, oy);\n            int internalDist = dist(orders[i].a, orders[i].b, orders[i].c, orders[i].d);\n            scoreList.push_back({pickupDist + dropoffDist + internalDist, i});\n        }\n        sort(scoreList.begin(), scoreList.end());\n        \n        for (int i = 0; i < 50; i++) {\n            int idx = scoreList[i].second;\n            selected.push_back(idx);\n            isSelected[idx] = true;\n        }\n        for (int i = 50; i < 1000; i++) {\n            notSelected.push_back(scoreList[i].second);\n        }\n        \n        buildRoute();\n        currentCost = calcCost();\n        bestCost = currentCost;\n        bestRoute = route;\n        bestSelected = selected;\n    }\n    \n    void buildRoute() {\n        route.clear();\n        route.reserve(2 * selected.size() + 2);\n        route.push_back({ox, oy, -1, 2});\n        for (int idx : selected) {\n            route.push_back({orders[idx].a, orders[idx].b, idx, 0});\n        }\n        for (int idx : selected) {\n            route.push_back({orders[idx].c, orders[idx].d, idx, 1});\n        }\n        route.push_back({ox, oy, -1, 2});\n    }\n    \n    int calcCost() {\n        int cost = 0;\n        for (size_t i = 0; i + 1 < route.size(); i++) {\n            cost += dist(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n        }\n        return cost;\n    }\n    \n    bool isValidRoute() {\n        vector<int> pickupPos(1000, -1), dropoffPos(1000, -1);\n        for (size_t k = 0; k < route.size(); k++) {\n            if (route[k].orderId >= 0) {\n                if (route[k].type == 0) pickupPos[route[k].orderId] = k;\n                else dropoffPos[route[k].orderId] = k;\n            }\n        }\n        for (int idx : selected) {\n            if (pickupPos[idx] >= dropoffPos[idx]) return false;\n        }\n        return true;\n    }\n    \n    void optimize(double timeLimit) {\n        double temperature = 5000.0;\n        double coolingRate = 0.99995;\n        \n        auto startTime = chrono::high_resolution_clock::now();\n        \n        while (true) {\n            auto currentTime = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed >= timeLimit) break;\n            \n            // Move type selection\n            int moveType = randDist(gen) < 0.35 ? 0 : (randDist(gen) < 0.7 ? 1 : 2);\n            \n            if (moveType == 0) {\n                // Swap: exchange an order in/out of selected set\n                int inIdx = (int)(randDist(gen) * selected.size());\n                int outIdx = (int)(randDist(gen) * notSelected.size());\n                \n                int inOrder = selected[inIdx];\n                int outOrder = notSelected[outIdx];\n                \n                // Save state\n                auto oldSelected = selected;\n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                // Apply swap\n                selected[inIdx] = outOrder;\n                isSelected[inOrder] = false;\n                isSelected[outOrder] = true;\n                notSelected[outIdx] = inOrder;\n                \n                buildRoute();\n                \n                // Check validity\n                if (!isValidRoute()) {\n                    // Revert\n                    selected = oldSelected;\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    isSelected[inOrder] = true;\n                    isSelected[outOrder] = false;\n                    notSelected[outIdx] = outOrder;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                        bestSelected = selected;\n                    }\n                } else {\n                    // Revert\n                    selected = oldSelected;\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    isSelected[inOrder] = true;\n                    isSelected[outOrder] = false;\n                    notSelected[outIdx] = outOrder;\n                }\n            } else if (moveType == 1) {\n                // 2-opt: reverse a segment of the route (excluding first and last)\n                int i = 1 + (int)(randDist(gen) * (route.size() - 4));\n                int j = i + 1 + (int)(randDist(gen) * (route.size() - i - 3));\n                \n                // Ensure we don't include first or last point\n                i = max(1, i);\n                j = min((int)route.size() - 2, j);\n                \n                if (i >= j) continue;\n                \n                // Save state\n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                // Apply 2-opt\n                reverse(route.begin() + i, route.begin() + j + 1);\n                \n                // Check validity\n                if (!isValidRoute()) {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                    }\n                } else {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                }\n            } else {\n                // Insert: move a non-office point to different position\n                int pos1 = 1 + (int)(randDist(gen) * (route.size() - 3));\n                int pos2 = 1 + (int)(randDist(gen) * (route.size() - 3));\n                \n                if (pos1 == pos2) continue;\n                \n                // Save state\n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                // Apply insert\n                Point p = route[pos1];\n                route.erase(route.begin() + pos1);\n                route.insert(route.begin() + pos2, p);\n                \n                // Check validity\n                if (!isValidRoute()) {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                        bestSelected = selected;\n                    }\n                } else {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                }\n            }\n            \n            temperature *= coolingRate;\n            \n            // Periodically output for visualization\n            if (elapsed > 0.5 && elapsed < 0.6) {\n                cout << bestSelected.size();\n                for (int idx : bestSelected) {\n                    cout << \" \" << orders[idx].id;\n                }\n                cout << \"\\n\";\n                cout << bestRoute.size();\n                for (auto& p : bestRoute) {\n                    cout << \" \" << p.x << \" \" << p.y;\n                }\n                cout << \"\\n\";\n            }\n        }\n    }\n    \n    void output() {\n        cout << bestSelected.size();\n        for (int idx : bestSelected) {\n            cout << \" \" << orders[idx].id;\n        }\n        cout << \"\\n\";\n        cout << bestRoute.size();\n        for (auto& p : bestRoute) {\n            cout << \" \" << p.x << \" \" << p.y;\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.readInput();\n    \n    // Multi-start optimization with 3 restarts\n    int numRestarts = 3;\n    double totalTimeLimit = 1.95;\n    double timePerRestart = totalTimeLimit / numRestarts;\n    \n    for (int r = 0; r < numRestarts; r++) {\n        solver.init();\n        solver.optimize(timePerRestart);\n    }\n    \n    solver.output();\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<pair<int, int>> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        long long dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = (int)round(sqrt(dx * dx + dy * dy));\n    }\n\n    DSU dsu(N);\n    int accepted_edges = 0;\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int root_u = dsu.find(u);\n        int root_v = dsu.find(v);\n\n        if (root_u == root_v) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Count remaining edges for each component\n        vector<int> edge_count(N, 0);\n        long long min_d_direct = 1e18;\n        long long min_d_any = 1e18;\n        int remaining_edges = 0;\n        bool has_direct = false;\n\n        for (int j = i + 1; j < M; ++j) {\n            int u_j = edges[j].u;\n            int v_j = edges[j].v;\n            int ru = dsu.find(u_j);\n            int rv = dsu.find(v_j);\n\n            if (ru != rv) {\n                remaining_edges++;\n                edge_count[ru]++;\n                edge_count[rv]++;\n                min_d_any = min(min_d_any, (long long)edges[j].d);\n                \n                if ((ru == root_u && rv == root_v) || (ru == root_v && rv == root_u)) {\n                    min_d_direct = min(min_d_direct, (long long)edges[j].d);\n                    has_direct = true;\n                }\n            }\n        }\n\n        bool accept = true;\n\n        // CRITICAL SAFETY: If either component has very few remaining edges, ALWAYS accept\n        if (edge_count[root_u] <= 3 || edge_count[root_v] <= 3) {\n            accept = true;\n        }\n        // SAFETY: If remaining edges are close to what we need, accept\n        else if (remaining_edges <= (N - 1 - accepted_edges) + 5) {\n            accept = true;\n        }\n        // SAFETY: If we're behind on progress, accept\n        else if (accepted_edges < i * 0.15) {\n            accept = true;\n        }\n        // Cost optimization (only when safe)\n        else {\n            if (has_direct) {\n                // Use 2.8x threshold (expected value is 2x, add buffer)\n                if (l_i > 2.8 * min_d_direct) {\n                    accept = false;\n                }\n            }\n            else if (min_d_any != 1e18) {\n                // For indirect path, use 3.2x threshold\n                if (l_i > 3.2 * min_d_any) {\n                    accept = false;\n                }\n            }\n        }\n\n        cout << (accept ? \"1\" : \"0\") << \"\\n\";\n        cout.flush();\n\n        if (accept) {\n            dsu.unite(u, v);\n            accepted_edges++;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Pet {\n    int x, y, type;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct State {\n    int turn;\n    vector<Pet> pets;\n    vector<Human> humans;\n    vector<vector<bool>> wall;\n};\n\nState state;\nmt19937 rng;\n\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char moveChars[] = {'U', 'D', 'L', 'R'};\nconst char wallChars[] = {'u', 'd', 'l', 'r'};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;\n}\n\nbool hasPetAt(int x, int y) {\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].x == x && state.pets[i].y == y) return true;\n    }\n    return false;\n}\n\nbool hasHumanAt(int x, int y) {\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        if (state.humans[i].x == x && state.humans[i].y == y) return true;\n    }\n    return false;\n}\n\nbool hasPetAdjacent(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (hasPetAt(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canPlaceWall(int x, int y) {\n    if (!isValid(x, y)) return false;\n    if (state.wall[x][y]) return false;\n    if (hasPetAt(x, y)) return false;\n    if (hasHumanAt(x, y)) return false;\n    if (hasPetAdjacent(x, y)) return false;\n    return true;\n}\n\nint bfsReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    if (state.wall[startX][startY]) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint countPetsInReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    if (state.wall[startX][startY]) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (hasPetAt(x, y)) count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint bfsDistance(int x1, int y1, int x2, int y2) {\n    if (!isValid(x1, y1) || !isValid(x2, y2)) return 1e9;\n    if (x1 == x2 && y1 == y2) return 0;\n    \n    vector<vector<int>> dist(GRID_SIZE, vector<int>(GRID_SIZE, 1e9));\n    queue<pair<int, int>> q;\n    \n    dist[x1][y1] = 0;\n    q.push({x1, y1});\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == x2 && y == y2) return dist[x][y];\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny] && dist[nx][ny] == 1e9) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return 1e9;\n}\n\nint countDangerousPets(int x, int y) {\n    int count = 0;\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].type == 4 || state.pets[i].type == 5) { // Dog or Cat\n            int dist = bfsDistance(x, y, state.pets[i].x, state.pets[i].y);\n            if (dist < 20) count++;\n        }\n    }\n    return count;\n}\n\n// Find nearest dangerous pet\npair<int, int> findNearestDangerousPet(int hx, int hy) {\n    int minDist = 1e9;\n    pair<int, int> nearest = {-1, -1};\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].type == 4 || state.pets[i].type == 5) {\n            int dist = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n            if (dist < minDist) {\n                minDist = dist;\n                nearest = {state.pets[i].x, state.pets[i].y};\n            }\n        }\n    }\n    \n    return nearest;\n}\n\ndouble evaluatePosition(int x, int y) {\n    if (!isValid(x, y) || state.wall[x][y]) return -1e9;\n    \n    int reachable = bfsReachable(x, y);\n    int petsInArea = countPetsInReachable(x, y);\n    int dangerousPets = countDangerousPets(x, y);\n    \n    double score = (double)reachable / 900.0 * pow(0.5, petsInArea);\n    score -= dangerousPets * 0.5;\n    \n    return score;\n}\n\ndouble evaluateWallPlacement(int hx, int hy, int wx, int wy, int turn) {\n    if (!canPlaceWall(wx, wy)) return -1e9;\n    \n    bool originalWall = state.wall[wx][wy];\n    state.wall[wx][wy] = true;\n    \n    double score = evaluatePosition(hx, hy);\n    \n    // Bonus for blocking dangerous pets\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].type == 4 || state.pets[i].type == 5) {\n            int distBefore = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n            state.wall[wx][wy] = false;\n            int distAfter = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n            state.wall[wx][wy] = true;\n            \n            if (distAfter > distBefore) {\n                score += 0.3 * (distAfter - distBefore);\n            }\n        }\n    }\n    \n    // Phase-based bonuses\n    if (turn < 50) {\n        // Early game: bonus for creating perimeter\n        score += 0.1;\n    } else if (turn < 200) {\n        // Middle game: bonus for expanding\n        score += 0.05;\n    }\n    \n    state.wall[wx][wy] = originalWall;\n    \n    return score;\n}\n\n// Find center of all humans for clustering\npair<int, int> findHumanCenter() {\n    int sumX = 0, sumY = 0;\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        sumX += state.humans[i].x;\n        sumY += state.humans[i].y;\n    }\n    return {sumX / (int)state.humans.size(), sumY / (int)state.humans.size()};\n}\n\n// Check if moving to (nx, ny) is safe from all other humans\nbool isMoveSafe(int nx, int ny, int humanIdx) {\n    if (!isValid(nx, ny)) return false;\n    if (state.wall[nx][ny]) return false;\n    \n    // Check if ANY other human is adjacent to destination (could place wall there)\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        if (i == (size_t)humanIdx) continue;\n        \n        int dist = abs(state.humans[i].x - nx) + abs(state.humans[i].y - ny);\n        if (dist == 1) {\n            return false;\n        }\n    }\n    \n    return true;\n}\n\nchar decideAction(int humanIdx) {\n    int hx = state.humans[humanIdx].x;\n    int hy = state.humans[humanIdx].y;\n    int turn = state.turn;\n    \n    // Find nearest dangerous pet\n    pair<int, int> nearestDangerous = findNearestDangerousPet(hx, hy);\n    int distToDangerous = (nearestDangerous.first >= 0) ? \n                          bfsDistance(hx, hy, nearestDangerous.first, nearestDangerous.second) : 1e9;\n    \n    // Find human center for clustering\n    pair<int, int> center = findHumanCenter();\n    \n    char bestAction = '.';\n    double bestScore = evaluatePosition(hx, hy);\n    \n    // Phase 1: Early game (0-50) - Build defensive perimeter\n    if (turn < 50) {\n        // Prioritize wall placement around humans\n        for (int d = 0; d < 4; d++) {\n            int wx = hx + dx[d];\n            int wy = hy + dy[d];\n            char wallChar = wallChars[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n            \n            // Bonus for blocking dangerous pets\n            if (nearestDangerous.first >= 0) {\n                int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                if (distToWall <= 3) {\n                    score += 0.5;\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = wallChar;\n            }\n        }\n        \n        // Consider moving towards center for clustering\n        if (turn < 20) {\n            int cx = center.first;\n            int cy = center.second;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = hx + dx[d];\n                int ny = hy + dy[d];\n                char moveChar = moveChars[d];\n                \n                if (!isMoveSafe(nx, ny, humanIdx)) continue;\n                \n                int distToCenterBefore = abs(hx - cx) + abs(hy - cy);\n                int distToCenterAfter = abs(nx - cx) + abs(ny - cy);\n                \n                if (distToCenterAfter < distToCenterBefore) {\n                    double score = evaluatePosition(nx, ny);\n                    score += 0.3; // Bonus for clustering\n                    \n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestAction = moveChar;\n                    }\n                }\n            }\n        }\n    }\n    // Phase 2: Middle game (51-200) - Expand and defend\n    else if (turn < 200) {\n        // If dangerous pet is close, prioritize blocking\n        if (distToDangerous < 15) {\n            for (int d = 0; d < 4; d++) {\n                int wx = hx + dx[d];\n                int wy = hy + dy[d];\n                char wallChar = wallChars[d];\n                \n                if (!canPlaceWall(wx, wy)) continue;\n                \n                double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n                \n                // Check if this wall is between human and dangerous pet\n                if (nearestDangerous.first >= 0) {\n                    int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                    if (distToWall <= 5) {\n                        score += 0.8;\n                    }\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = wallChar;\n                }\n            }\n        }\n        \n        // Try moves for expansion\n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            \n            double score = evaluatePosition(nx, ny);\n            int dangerous = countDangerousPets(nx, ny);\n            score -= dangerous * 0.3;\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = moveChar;\n            }\n        }\n    }\n    // Phase 3: Late game (201-300) - Fine-tune\n    else {\n        // Focus on blocking any remaining dangerous pets\n        for (int d = 0; d < 4; d++) {\n            int wx = hx + dx[d];\n            int wy = hy + dy[d];\n            char wallChar = wallChars[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n            \n            if (nearestDangerous.first >= 0) {\n                int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                if (distToWall <= 8) {\n                    score += 1.0;\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = wallChar;\n            }\n        }\n    }\n    \n    return bestAction;\n}\n\nvoid updateState(const vector<string>& petMoves, const string& actions) {\n    // Update human positions and walls based on actions\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        char action = actions[i];\n        \n        if (action >= 'A' && action <= 'Z') {\n            int d = 0;\n            if (action == 'U') d = 0;\n            else if (action == 'D') d = 1;\n            else if (action == 'L') d = 2;\n            else if (action == 'R') d = 3;\n            \n            int nx = state.humans[i].x + dx[d];\n            int ny = state.humans[i].y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                state.humans[i].x = nx;\n                state.humans[i].y = ny;\n            }\n        } else if (action >= 'a' && action <= 'z') {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[i].x + dx[d];\n            int wy = state.humans[i].y + dy[d];\n            \n            if (canPlaceWall(wx, wy)) {\n                state.wall[wx][wy] = true;\n            }\n        }\n    }\n    \n    // Update pet positions\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        const string& move = petMoves[i];\n        int x = state.pets[i].x;\n        int y = state.pets[i].y;\n        \n        for (char c : move) {\n            int d = 0;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            \n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                x = nx;\n                y = ny;\n            }\n        }\n        \n        state.pets[i].x = x;\n        state.pets[i].y = y;\n    }\n    \n    state.turn++;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    int N;\n    cin >> N;\n    \n    state.pets.resize(N);\n    for (size_t i = 0; i < (size_t)N; i++) {\n        cin >> state.pets[i].x >> state.pets[i].y >> state.pets[i].type;\n        state.pets[i].x--;\n        state.pets[i].y--;\n    }\n    \n    int M;\n    cin >> M;\n    \n    state.humans.resize(M);\n    for (size_t i = 0; i < (size_t)M; i++) {\n        cin >> state.humans[i].x >> state.humans[i].y;\n        state.humans[i].x--;\n        state.humans[i].y--;\n    }\n    \n    state.turn = 0;\n    state.wall.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (int turn = 0; turn < MAX_TURNS; turn++) {\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2900) {\n            for (size_t i = 0; i < state.humans.size(); i++) {\n                cout << '.';\n            }\n            cout << endl;\n            flush(cout);\n            \n            vector<string> petMoves(N);\n            for (size_t i = 0; i < (size_t)N; i++) {\n                cin >> petMoves[i];\n            }\n            updateState(petMoves, string(state.humans.size(), '.'));\n            continue;\n        }\n        \n        string actions = \"\";\n        for (size_t i = 0; i < state.humans.size(); i++) {\n            char action = decideAction((int)i);\n            \n            // Final safety check for moves\n            if (action >= 'A' && action <= 'Z') {\n                int d = 0;\n                if (action == 'U') d = 0;\n                else if (action == 'D') d = 1;\n                else if (action == 'L') d = 2;\n                else if (action == 'R') d = 3;\n                \n                int nx = state.humans[i].x + dx[d];\n                int ny = state.humans[i].y + dy[d];\n                \n                if (!isValid(nx, ny) || state.wall[nx][ny]) {\n                    action = '.';\n                } else {\n                    bool safe = true;\n                    for (size_t j = 0; j < state.humans.size(); j++) {\n                        if (j == i) continue;\n                        int dist = abs(state.humans[j].x - nx) + abs(state.humans[j].y - ny);\n                        if (dist == 1) {\n                            safe = false;\n                            break;\n                        }\n                    }\n                    if (!safe) action = '.';\n                }\n            }\n            \n            actions += action;\n        }\n        \n        cout << actions << endl;\n        flush(cout);\n        \n        vector<string> petMoves(N);\n        for (size_t i = 0; i < (size_t)N; i++) {\n            cin >> petMoves[i];\n        }\n        \n        updateState(petMoves, actions);\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int INF = 1e9;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    if (!(cin >> si >> sj >> ti >> tj >> p)) return 0;\n\n    vector<string> h(MAX_N);\n    for (int i = 0; i < MAX_N; ++i) {\n        cin >> h[i];\n    }\n\n    vector<string> v(MAX_N - 1);\n    for (int i = 0; i < MAX_N - 1; ++i) {\n        cin >> v[i];\n    }\n\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    char moves[] = {'R', 'L', 'D', 'U'};\n\n    // BFS from target to compute distances\n    vector<vector<int>> dist(MAX_N, vector<int>(MAX_N, INF));\n    queue<pair<int, int>> q;\n\n    dist[ti][tj] = 0;\n    q.push({ti, tj});\n\n    auto can_move = [&](int i, int j, int k) -> bool {\n        int ni = i + di[k];\n        int nj = j + dj[k];\n        if (ni < 0 || ni >= MAX_N || nj < 0 || nj >= MAX_N) return false;\n        if (k == 0) { if (h[i][j] == '1') return false; }\n        else if (k == 1) { if (h[i][j-1] == '1') return false; }\n        else if (k == 2) { if (v[i][j] == '1') return false; }\n        else if (k == 3) { if (v[i-1][j] == '1') return false; }\n        return true;\n    };\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k];\n            int nj = j + dj[k];\n\n            if (can_move(i, j, k) && dist[ni][nj] == INF) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n\n    // Probability distribution\n    vector<vector<double>> prob(MAX_N, vector<double>(MAX_N, 0.0));\n    prob[si][sj] = 1.0;\n    double move_prob = 1.0 - p;\n\n    // Helper function to simulate one move\n    auto simulate_move = [&](const vector<vector<double>>& current_prob, int k) {\n        vector<vector<double>> next_prob(MAX_N, vector<double>(MAX_N, 0.0));\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (current_prob[i][j] < 1e-15) continue;\n                if (i == ti && j == tj) {\n                    next_prob[i][j] += current_prob[i][j];\n                    continue;\n                }\n                if (can_move(i, j, k)) {\n                    int ni = i + di[k];\n                    int nj = j + dj[k];\n                    next_prob[ni][nj] += current_prob[i][j] * move_prob;\n                    next_prob[i][j] += current_prob[i][j] * p;\n                } else {\n                    next_prob[i][j] += current_prob[i][j];\n                }\n            }\n        }\n        return next_prob;\n    };\n\n    // Helper to calculate metrics\n    auto calc_metrics = [&](const vector<vector<double>>& current_prob) -> pair<double, double> {\n        double expected_dist = 0.0;\n        double reach_prob = 0.0;\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (i == ti && j == tj) {\n                    reach_prob += current_prob[i][j];\n                } else if (dist[i][j] != INF) {\n                    expected_dist += current_prob[i][j] * dist[i][j];\n                }\n            }\n        }\n        return {expected_dist, reach_prob};\n    };\n\n    string result = \"\";\n    int last_move = -1;\n    int repeat_count = 0;\n\n    for (int step = 0; step < 200; ++step) {\n        int remaining = 200 - step;\n        int best_move = 0;\n        double best_score = -1e18;\n        vector<vector<double>> best_next_prob;\n\n        // Calculate probability concentration\n        double max_prob = 0.0;\n        vector<pair<double, pair<int, int>>> top_probs;\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (prob[i][j] > max_prob) max_prob = prob[i][j];\n                if (prob[i][j] > 1e-10) {\n                    top_probs.push_back({prob[i][j], {i, j}});\n                }\n            }\n        }\n        sort(top_probs.rbegin(), top_probs.rend());\n        double prob_sum_top3 = 0.0;\n        for (int i = 0; i < min(3, (int)top_probs.size()); ++i) {\n            prob_sum_top3 += top_probs[i].first;\n        }\n\n        // Dynamic weight based on remaining steps and concentration\n        double weight;\n        if (remaining <= 50) {\n            // End-game: be more aggressive about reaching target\n            weight = 150.0 + (50.0 - remaining) * 3.0;\n        } else {\n            weight = 80.0 + (200.0 - remaining) * 0.5;\n        }\n\n        // 3-step lookahead for critical decisions\n        for (int k1 = 0; k1 < 4; ++k1) {\n            auto prob_after_1 = simulate_move(prob, k1);\n            auto metrics1 = calc_metrics(prob_after_1);\n            double score1_val = -metrics1.first + weight * metrics1.second;\n\n            // 2-step lookahead\n            double max_score2 = -1e18;\n            for (int k2 = 0; k2 < 4; ++k2) {\n                auto prob_after_2 = simulate_move(prob_after_1, k2);\n                auto metrics2 = calc_metrics(prob_after_2);\n                double score2_val = -metrics2.first + weight * metrics2.second;\n                max_score2 = max(max_score2, score2_val);\n            }\n\n            // 3-step lookahead for concentrated probability\n            double max_score3 = -1e18;\n            if (prob_sum_top3 > 0.5 || remaining <= 70) {\n                for (int k2 = 0; k2 < 4; ++k2) {\n                    auto prob_after_2 = simulate_move(prob_after_1, k2);\n                    for (int k3 = 0; k3 < 4; ++k3) {\n                        auto prob_after_3 = simulate_move(prob_after_2, k3);\n                        auto metrics3 = calc_metrics(prob_after_3);\n                        double score3_val = -metrics3.first + weight * metrics3.second;\n                        max_score3 = max(max_score3, score3_val);\n                    }\n                }\n            }\n\n            // Combined score with adaptive lookahead weight\n            double lookahead_weight = 0.4 + (200.0 - remaining) * 0.002;\n            lookahead_weight = min(lookahead_weight, 0.6);\n            double combined_score = (1.0 - lookahead_weight) * score1_val + lookahead_weight * max_score2;\n            if (max_score3 > -1e17) {\n                combined_score += 0.2 * max_score3;\n            }\n\n            // Bonus for moves that reduce distance from high-probability cells\n            double distance_bonus = 0.0;\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (prob[i][j] > 0.05 && dist[i][j] != INF) {\n                        if (can_move(i, j, k1)) {\n                            int ni = i + di[k1];\n                            int nj = j + dj[k1];\n                            if (dist[ni][nj] < dist[i][j]) {\n                                distance_bonus += prob[i][j] * (dist[i][j] - dist[ni][nj]);\n                            }\n                        }\n                    }\n                }\n            }\n            combined_score += 3.0 * distance_bonus;\n\n            // Move repetition bonus when beneficial\n            if (last_move == k1 && repeat_count > 0) {\n                // Check if repeating this move is beneficial\n                double repeat_benefit = 0.0;\n                for (const auto& tp : top_probs) {\n                    if (tp.first < 0.1) break;\n                    int i = tp.second.first;\n                    int j = tp.second.second;\n                    if (dist[i][j] != INF && can_move(i, j, k1)) {\n                        int ni = i + di[k1];\n                        int nj = j + dj[k1];\n                        if (dist[ni][nj] < dist[i][j]) {\n                            repeat_benefit += tp.first * 2.0;\n                        }\n                    }\n                }\n                if (repeat_benefit > 0.5) {\n                    combined_score += repeat_benefit;\n                }\n            }\n\n            // End-game bonus: prioritize moves that increase reach probability\n            if (remaining <= 50) {\n                double reach_increase = metrics1.second - calc_metrics(prob).second;\n                if (reach_increase > 0) {\n                    combined_score += reach_increase * 100.0;\n                }\n            }\n\n            // Penalty for moves that don't progress when probability is concentrated\n            if (max_prob > 0.4 && prob_sum_top3 > 0.7) {\n                bool progresses = false;\n                for (const auto& tp : top_probs) {\n                    if (tp.first < 0.15) break;\n                    int i = tp.second.first;\n                    int j = tp.second.second;\n                    if (dist[i][j] != INF && can_move(i, j, k1)) {\n                        int ni = i + di[k1];\n                        int nj = j + dj[k1];\n                        if (dist[ni][nj] < dist[i][j]) {\n                            progresses = true;\n                            break;\n                        }\n                    }\n                }\n                if (!progresses) {\n                    combined_score -= 8.0;\n                }\n            }\n\n            if (combined_score > best_score + 1e-9) {\n                best_score = combined_score;\n                best_move = k1;\n                best_next_prob = prob_after_1;\n            }\n        }\n\n        // Track move repetition\n        if (best_move == last_move) {\n            repeat_count++;\n        } else {\n            repeat_count = 1;\n        }\n        last_move = best_move;\n\n        result += moves[best_move];\n        prob = best_next_prob;\n    }\n\n    cout << result << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to table from problem statement\nconst int to[8][4] = {\n    {1, 0, -1, -1}, // 0\n    {3, -1, -1, 0}, // 1\n    {-1, -1, 3, 2}, // 2\n    {-1, 2, 1, -1}, // 3\n    {1, 0, 3, 2},   // 4\n    {3, 2, 1, 0},   // 5\n    {2, -1, 0, -1}, // 6\n    {-1, 3, -1, 1}  // 7\n};\n\nint grid_type[30][30];\nint rot[30][30];\nint best_rot[30][30];\n\n// Visited generation array to avoid memset every time\nint vis_gen[30][30][4];\nint dist[30][30][4];\nint trace_id = 0;\n\nint get_effective_type(int base, int r) {\n    if (base < 4) return (base + r) % 4;\n    if (base == 4) return 4 + (r % 2);\n    if (base == 5) return 5 - (r % 2);\n    if (base == 6) return 6 + (r % 2);\n    if (base == 7) return 7 - (r % 2);\n    return 0;\n}\n\nlong long calc_score(vector<int>& lengths) {\n    lengths.clear();\n    lengths.reserve(900);\n\n    trace_id++;\n    if (trace_id == 0) {\n        memset(vis_gen, 0, sizeof(vis_gen));\n        trace_id = 1;\n    }\n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (vis_gen[i][j][d] == trace_id) continue;\n\n                int cur_i = i, cur_j = j, cur_d = d;\n                int steps = 0;\n                bool cycle_found = false;\n                int cycle_len = 0;\n\n                while (true) {\n                    if (vis_gen[cur_i][cur_j][cur_d] == trace_id) {\n                        cycle_len = steps - dist[cur_i][cur_j][cur_d];\n                        cycle_found = true;\n                        break;\n                    }\n                    if (vis_gen[cur_i][cur_j][cur_d] != 0) {\n                        break;\n                    }\n\n                    vis_gen[cur_i][cur_j][cur_d] = trace_id;\n                    dist[cur_i][cur_j][cur_d] = steps;\n\n                    int t = get_effective_type(grid_type[cur_i][cur_j], rot[cur_i][cur_j]);\n                    int next_d = to[t][cur_d];\n                    if (next_d == -1) break;\n\n                    int next_i = cur_i + di[next_d];\n                    int next_j = cur_j + dj[next_d];\n\n                    if (next_i < 0 || next_i >= 30 || next_j < 0 || next_j >= 30) break;\n\n                    cur_i = next_i;\n                    cur_j = next_j;\n                    cur_d = (next_d + 2) % 4;\n                    steps++;\n                }\n\n                if (cycle_found) {\n                    lengths.push_back(cycle_len);\n                }\n            }\n        }\n    }\n\n    if (lengths.size() < 2) return 0;\n    sort(lengths.rbegin(), lengths.rend());\n    return (long long)lengths[0] * lengths[1];\n}\n\nvoid copy_rot(int src[30][30], int dst[30][30]) {\n    for (int i = 0; i < 30; ++i)\n        for (int j = 0; j < 30; ++j)\n            dst[i][j] = src[i][j];\n}\n\nvoid randomize_rot(mt19937& rng, int rot[30][30]) {\n    uniform_int_distribution<int> dist_rot(0, 3);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            rot[i][j] = dist_rot(rng);\n        }\n    }\n}\n\nvoid solve() {\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            grid_type[i][j] = s[j] - '0';\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_rot(0, 3);\n    uniform_int_distribution<int> dist_idx(0, 29);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    long long best_score = 0;\n    vector<int> lengths;\n\n    auto start_time = chrono::steady_clock::now();\n    auto limit_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    // Multi-start with different strategies\n    int num_starts = 0;\n    int max_starts = 20;\n\n    while (chrono::steady_clock::now() < limit_time && num_starts < max_starts) {\n        num_starts++;\n\n        // Randomize rotations\n        randomize_rot(rng, rot);\n\n        // Initial score\n        long long current_score = calc_score(lengths);\n\n        // Local search with simulated annealing\n        double T = 5000.0;\n        int no_improve_count = 0;\n        int max_no_improve = 100000;\n\n        while (chrono::steady_clock::now() < limit_time && no_improve_count < max_no_improve) {\n            // Try single tile flip\n            int r = dist_idx(rng);\n            int c = dist_idx(rng);\n\n            int old_rot = rot[r][c];\n            rot[r][c] = (rot[r][c] + 1) % 4;\n\n            long long new_score = calc_score(lengths);\n\n            // Acceptance criteria\n            bool accept = false;\n            if (new_score > current_score) {\n                accept = true;\n                no_improve_count = 0;\n            } else if (new_score == current_score) {\n                accept = true;\n            } else {\n                double prob = exp((new_score - current_score) / T);\n                if (dist_prob(rng) < prob) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    copy_rot(rot, best_rot);\n                }\n            } else {\n                rot[r][c] = old_rot;\n                no_improve_count++;\n            }\n\n            // Occasionally try larger moves (flip 2-3 tiles)\n            if (no_improve_count % 100 == 0 && dist_prob(rng) < 0.1) {\n                int num_tiles = 2 + (dist_idx(rng) % 2);\n                vector<pair<int,int>> flipped;\n                \n                for (int k = 0; k < num_tiles; ++k) {\n                    int rr = dist_idx(rng);\n                    int cc = dist_idx(rng);\n                    flipped.push_back({rr, cc});\n                }\n                \n                // Apply flips\n                for (auto& p : flipped) {\n                    rot[p.first][p.second] = (rot[p.first][p.second] + 1) % 4;\n                }\n                \n                long long new_score2 = calc_score(lengths);\n                \n                if (new_score2 > current_score) {\n                    current_score = new_score2;\n                    no_improve_count = 0;\n                    if (new_score2 > best_score) {\n                        best_score = new_score2;\n                        copy_rot(rot, best_rot);\n                    }\n                } else {\n                    // Revert\n                    for (auto& p : flipped) {\n                        rot[p.first][p.second] = (rot[p.first][p.second] + 3) % 4;\n                    }\n                }\n            }\n\n            T *= 0.9995;\n            if (T < 1.0) T = 1.0;\n        }\n    }\n\n    // Final output\n    string out = \"\";\n    out.reserve(900);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            out += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << out << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n\nusing namespace std;\n\nint N, T;\nint board[12][12];\nstring moves;\nint empty_r, empty_c;\nbool solved[12][12];\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dchar[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return 0;\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nvoid apply_move(char move) {\n    int dir = -1;\n    if (move == 'U') dir = 0;\n    else if (move == 'D') dir = 1;\n    else if (move == 'L') dir = 2;\n    else if (move == 'R') dir = 3;\n    \n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    \n    if (!is_valid(nr, nc)) return;\n    \n    int tile = board[nr][nc];\n    board[empty_r][empty_c] = tile;\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    moves += move;\n}\n\n// Simple BFS for empty square movement\nstring bfs_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return \"\";\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\n    \n    char parent_move[12][12];\n    bool visited[12][12];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        visited[i][j] = false;\n        parent_move[i][j] = 0;\n    }\n    \n    visited[empty_r][empty_c] = true;\n    \n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            string path = \"\";\n            int cr = tr, cc = tc;\n            while(cr != empty_r || cc != empty_c) {\n                char m = parent_move[cr][cc];\n                path += m;\n                int dir = -1;\n                if (m == 'U') dir = 0;\n                else if (m == 'D') dir = 1;\n                else if (m == 'L') dir = 2;\n                else if (m == 'R') dir = 3;\n                int rev_dr = -dr[dir];\n                int rev_dc = -dc[dir];\n                cr += rev_dr;\n                cc += rev_dc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (is_valid(nr, nc) && !visited[nr][nc] && !solved[nr][nc]) {\n                visited[nr][nc] = true;\n                parent_move[nr][nc] = dchar[i];\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\";\n}\n\n// Find position of a tile value\npair<int, int> find_tile(int val) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == val) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Place a tile at target position\nvoid place_tile_at(int tr, int tc, int target_val) {\n    // Skip if already correct\n    if (board[tr][tc] == target_val) {\n        solved[tr][tc] = true;\n        return;\n    }\n    \n    // Find where the target tile is\n    auto pos = find_tile(target_val);\n    int fr = pos.first, fc = pos.second;\n    \n    if (fr == -1) return; // Should not happen\n    \n    // Move tile from (fr, fc) to (tr, tc)\n    while (fr != tr || fc != tc) {\n        // Find best direction to move tile towards target\n        int best_dir = -1;\n        int best_dist = 1e9;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = fr + dr[i];\n            int nc = fc + dc[i];\n            if (is_valid(nr, nc) && !solved[nr][nc]) {\n                int dist = abs(nr - tr) + abs(nc - tc);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_dir = i;\n                }\n            }\n        }\n        \n        if (best_dir == -1) {\n            // Try any unsolved neighbor\n            for (int i = 0; i < 4; ++i) {\n                int nr = fr + dr[i];\n                int nc = fc + dc[i];\n                if (is_valid(nr, nc) && !solved[nr][nc]) {\n                    best_dir = i;\n                    break;\n                }\n            }\n        }\n        \n        if (best_dir == -1) break;\n        \n        int nr = fr + dr[best_dir];\n        int nc = fc + dc[best_dir];\n        \n        // Move empty square to (nr, nc)\n        string path = bfs_to(nr, nc);\n        for (char m : path) apply_move(m);\n        \n        // Move tile to (nr, nc)\n        int reverse_dir = (best_dir + 2) % 4;\n        apply_move(dchar[reverse_dir]);\n        \n        // Update tile position\n        fr = nr;\n        fc = nc;\n        \n        // Check move limit\n        if (moves.size() > T) {\n            cout << moves << endl;\n            exit(0);\n        }\n    }\n    solved[tr][tc] = true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T)) return 0;\n    \n    vector<string> input_board(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> input_board[i];\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(input_board[i][j]);\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    // Initialize solved array\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            solved[i][j] = false;\n    \n    // Strategy: Place tiles in order, but skip the last cell (empty square)\n    // We'll create a simple pattern that should work\n    \n    // Count available tiles\n    int counts[16] = {0};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] != 0) {\n                counts[board[i][j]]++;\n            }\n        }\n    }\n    \n    // Create target configuration (simple row-by-row placement)\n    int target[12][12];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            target[i][j] = -1;\n        }\n    }\n    \n    // Fill target with available tiles (skip last cell for empty square)\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) {\n                target[i][j] = 0; // Empty square\n            } else {\n                // Find next available tile\n                for (int t = 1; t <= 15; ++t) {\n                    if (counts[t] > 0) {\n                        target[i][j] = t;\n                        counts[t]--;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Solve puzzle\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) continue; // Skip empty square\n            \n            int target_val = target[i][j];\n            if (target_val == -1) continue;\n            \n            place_tile_at(i, j, target_val);\n            \n            if (moves.size() > T) {\n                cout << moves << endl;\n                return 0;\n            }\n        }\n    }\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <unordered_map>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\n// Cross product to determine which side of line a point is on\nint point_side(const Line& line, const Point& p) {\n    long long dx = line.qx - line.px;\n    long long dy = line.qy - line.py;\n    long long px = p.x - line.px;\n    long long py = p.y - line.py;\n    long long cp = dx * py - dy * px;\n    if (cp > 0) return 1;\n    if (cp < 0) return -1;\n    return 0;\n}\n\n// Calculate score - optimized version\nint calculate_score(const vector<Point>& strawberries, \n                    const vector<Line>& cuts, \n                    const vector<int>& a) {\n    int n = strawberries.size();\n    int k = cuts.size();\n    \n    if (k == 0) {\n        int count = n;\n        if (count >= 1 && count <= 10) {\n            int total_attendees = 0;\n            for (int d = 1; d <= 10; d++) total_attendees += a[d];\n            if (total_attendees == 0) return 0;\n            int distributed = min(a[count], 1);\n            return round(1e6 * distributed / total_attendees);\n        }\n        return 0;\n    }\n    \n    // For each strawberry, determine its region (bitmask of which side of each cut)\n    vector<int> region(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < k; j++) {\n            int side = point_side(cuts[j], strawberries[i]);\n            if (side == 1) {\n                region[i] |= (1 << j);\n            }\n        }\n    }\n    \n    // Count strawberries in each region\n    unordered_map<int, int> region_count;\n    region_count.reserve(1 << min(k, 20));\n    for (int i = 0; i < n; i++) {\n        region_count[region[i]]++;\n    }\n    \n    // Calculate score\n    int total_attendees = 0;\n    for (int d = 1; d <= 10; d++) {\n        total_attendees += a[d];\n    }\n    \n    if (total_attendees == 0) return 0;\n    \n    // Count pieces with each number of strawberries\n    vector<int> b(11, 0);\n    for (const auto& [region_id, count] : region_count) {\n        if (count >= 1 && count <= 10) {\n            b[count]++;\n        }\n    }\n    \n    int distributed = 0;\n    for (int d = 1; d <= 10; d++) {\n        distributed += min(a[d], b[d]);\n    }\n    \n    return round(1e6 * distributed / total_attendees);\n}\n\n// Generate a random line\nLine generate_random_line(mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    line.px = dist(gen);\n    line.py = dist(gen);\n    line.qx = dist(gen);\n    line.qy = dist(gen);\n    \n    while (line.px == line.qx && line.py == line.qy) {\n        line.qx = dist(gen);\n        line.qy = dist(gen);\n    }\n    \n    return line;\n}\n\n// Generate a line that passes between two strawberries\nLine generate_separating_line(const Point& p1, const Point& p2, \n                              mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    \n    long long dx = p2.x - p1.x;\n    long long dy = p2.y - p1.y;\n    \n    long long mx = (p1.x + p2.x) / 2;\n    long long my = (p1.y + p2.y) / 2;\n    \n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    long long offset_x = dist(gen) % 100000 - 50000;\n    long long offset_y = dist(gen) % 100000 - 50000;\n    \n    line.px = mx + pdx + offset_x;\n    line.py = my + pdy + offset_y;\n    line.qx = mx - pdx + offset_x;\n    line.qy = my - pdy + offset_y;\n    \n    return line;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(11);\n    for (int i = 1; i <= 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<long long> dist(-1000000000, 1000000000);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = start_time + chrono::milliseconds(2800);\n    \n    vector<Line> best_cuts;\n    int best_score = 0;\n    \n    // Multiple restart strategy\n    int num_restarts = 12;\n    int restarts_done = 0;\n    \n    while (restarts_done < num_restarts && chrono::steady_clock::now() < time_limit) {\n        restarts_done++;\n        vector<Line> cuts;\n        \n        // Phase 1: Generate initial cuts\n        int initial_cuts = min(K, 6);\n        for (int i = 0; i < initial_cuts; i++) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            cuts.push_back(generate_random_line(gen, dist));\n        }\n        \n        // Phase 2: Iterative improvement (reduced iterations)\n        int max_iterations = 400;\n        int iteration = 0;\n        int no_improve_count = 0;\n        \n        while (iteration < max_iterations && \n               chrono::steady_clock::now() < time_limit && \n               no_improve_count < 150) {\n            iteration++;\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            Line best_new_cut;\n            int best_new_score = old_score;\n            int best_idx = -1;\n            bool should_add = false;\n            \n            // Try adding a cut (only if we haven't reached K)\n            if ((int)cuts.size() < K) {\n                for (int trial = 0; trial < 15; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    Line new_cut;\n                    if (gen() % 2 == 0 && N >= 2) {\n                        int i1 = gen() % N;\n                        int i2 = gen() % N;\n                        while (i2 == i1) i2 = gen() % N;\n                        new_cut = generate_separating_line(strawberries[i1], strawberries[i2], gen, dist);\n                    } else {\n                        new_cut = generate_random_line(gen, dist);\n                    }\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts.push_back(new_cut);\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = -1;\n                        should_add = true;\n                    }\n                }\n            }\n            \n            // Try replacing a cut\n            if ((int)cuts.size() >= 1) {\n                for (int trial = 0; trial < 10; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    int idx = gen() % cuts.size();\n                    Line new_cut = generate_random_line(gen, dist);\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts[idx] = new_cut;\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = idx;\n                        should_add = false;\n                    }\n                }\n            }\n            \n            // Apply best improvement\n            if (best_new_score > old_score) {\n                no_improve_count = 0;\n                if (should_add) {\n                    cuts.push_back(best_new_cut);\n                } else if (best_idx >= 0) {\n                    cuts[best_idx] = best_new_cut;\n                }\n            } else {\n                no_improve_count++;\n            }\n        }\n        \n        // Phase 3: Remove unnecessary cuts\n        for (int i = (int)cuts.size() - 1; i >= 0; i--) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.erase(test_cuts.begin() + i);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n        \n        // Ensure we never exceed K cuts\n        while ((int)cuts.size() > K) {\n            cuts.pop_back();\n        }\n        \n        // Update best solution\n        int current_score = calculate_score(strawberries, cuts, a);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_cuts = cuts;\n        }\n    }\n    \n    // Final safety check\n    while ((int)best_cuts.size() > K) {\n        best_cuts.pop_back();\n    }\n    \n    // Output\n    cout << best_cuts.size() << endl;\n    for (const auto& cut : best_cuts) {\n        cout << cut.px << \" \" << cut.py << \" \" << cut.qx << \" \" << cut.qy << endl;\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <unordered_set>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct Edge {\n    int x1, y1, x2, y2;\n    int type; // 0: horizontal, 1: vertical, 2: diagonal +1, 3: diagonal -1\n    \n    bool operator<(const Edge& other) const {\n        if (type != other.type) return type < other.type;\n        if (x1 != other.x1) return x1 < other.x1;\n        if (y1 != other.y1) return y1 < other.y1;\n        if (x2 != other.x2) return x2 < other.x2;\n        return y2 < other.y2;\n    }\n};\n\nstruct Operation {\n    Point p1, p2, p3, p4;\n    double score;\n};\n\nclass RectJoinSolver {\nprivate:\n    int N, M;\n    unordered_set<long long> dots;\n    vector<Edge> drawnEdges;\n    vector<Operation> operations;\n    vector<Point> dotList;\n    int cx, cy;\n    \n    double weight(int x, int y) const {\n        return (double)(x - cx) * (x - cx) + (double)(y - cy) * (y - cy) + 1.0;\n    }\n    \n    bool inGrid(int x, int y) const {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    }\n    \n    bool hasDot(int x, int y) const {\n        return dots.count(((long long)x << 32) | (unsigned int)y) > 0;\n    }\n    \n    Edge normalizeEdge(int x1, int y1, int x2, int y2) const {\n        int dx = x2 - x1, dy = y2 - y1;\n        int type = -1;\n        \n        if (dx == 0) type = 1;\n        else if (dy == 0) type = 0;\n        else if (abs(dx) == abs(dy)) {\n            type = (dx == dy) ? 2 : 3;\n        }\n        \n        if (x1 < x2 || (x1 == x2 && y1 < y2)) {\n            return {x1, y1, x2, y2, type};\n        }\n        return {x2, y2, x1, y1, type};\n    }\n    \n    void addEdge(int x1, int y1, int x2, int y2) {\n        drawnEdges.push_back(normalizeEdge(x1, y1, x2, y2));\n    }\n    \n    bool edgesOverlap(const Edge& e1, const Edge& e2) const {\n        if (e1.type != e2.type || e1.type == -1) return false;\n        \n        if (e1.type == 0) { // horizontal\n            if (e1.y1 != e2.y1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        if (e1.type == 1) { // vertical\n            if (e1.x1 != e2.x1) return false;\n            int yMin1 = min(e1.y1, e1.y2), yMax1 = max(e1.y1, e1.y2);\n            int yMin2 = min(e2.y1, e2.y2), yMax2 = max(e2.y1, e2.y2);\n            return max(yMin1, yMin2) < min(yMax1, yMax2);\n        }\n        if (e1.type == 2) { // diagonal +1\n            if (e1.y1 - e1.x1 != e2.y1 - e2.x1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        if (e1.type == 3) { // diagonal -1\n            if (e1.y1 + e1.x1 != e2.y1 + e2.x1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        return false;\n    }\n    \n    bool rectangleOverlaps(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const {\n        Edge edges[4] = {\n            normalizeEdge(x1, y1, x2, y2),\n            normalizeEdge(x2, y2, x3, y3),\n            normalizeEdge(x3, y3, x4, y4),\n            normalizeEdge(x4, y4, x1, y1)\n        };\n        \n        for (int i = 0; i < 4; i++) {\n            if (edges[i].type == -1) return true;\n            for (const auto& existing : drawnEdges) {\n                if (edgesOverlap(edges[i], existing)) return true;\n            }\n        }\n        return false;\n    }\n    \n    bool hasDotsOnPerimeter(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,\n                           const Point& p2, const Point& p3, const Point& p4) const {\n        auto checkEdge = [&](int x1, int y1, int x2, int y2) {\n            int dx = x2 - x1, dy = y2 - y1;\n            int steps = max(abs(dx), abs(dy));\n            for (int i = 1; i < steps; i++) {\n                int x = x1 + dx * i / steps;\n                int y = y1 + dy * i / steps;\n                if ((x == p2.x && y == p2.y) || (x == p3.x && y == p3.y) || \n                    (x == p4.x && y == p4.y)) continue;\n                if (hasDot(x, y)) return true;\n            }\n            return false;\n        };\n        \n        return checkEdge(x1, y1, x2, y2) ||\n               checkEdge(x2, y2, x3, y3) ||\n               checkEdge(x3, y3, x4, y4) ||\n               checkEdge(x4, y4, x1, y1);\n    }\n    \n    bool isValidRectangle(const Point& p1, const Point& p2, const Point& p3, const Point& p4) const {\n        int dx23 = p3.x - p2.x, dy23 = p3.y - p2.y;\n        int dx34 = p4.x - p3.x, dy34 = p4.y - p3.y;\n        int dx41 = p1.x - p4.x, dy41 = p1.y - p4.y;\n        int dx12 = p2.x - p1.x, dy12 = p2.y - p1.y;\n        \n        if (dx23 * dx34 + dy23 * dy34 != 0) return false;\n        if (dx23 != -dx41 || dy23 != -dy41) return false;\n        if (dx34 != -dx12 || dy34 != -dy12) return false;\n        \n        bool axisAligned = (dx23 == 0 || dy23 == 0) && (dx34 == 0 || dy34 == 0);\n        bool diagonal45 = (abs(dx23) == abs(dy23) && abs(dx34) == abs(dy34));\n        \n        if (axisAligned) {\n            if (!((dx23 == 0 || dy23 == 0) && (dx34 == 0 || dy34 == 0) &&\n                  (dx41 == 0 || dy41 == 0) && (dx12 == 0 || dy12 == 0))) {\n                return false;\n            }\n        } else if (diagonal45) {\n            if (!((abs(dx23) == abs(dy23)) && (abs(dx34) == abs(dy34)) &&\n                  (abs(dx41) == abs(dy41)) && (abs(dx12) == abs(dy12)))) {\n                return false;\n            }\n        } else {\n            return false;\n        }\n        \n        return true;\n    }\n    \n    vector<Operation> findValidMoves() {\n        vector<Operation> validMoves;\n        int nDots = dotList.size();\n        \n        for (int i = 0; i < nDots; i++) {\n            for (int j = i + 1; j < nDots; j++) {\n                Point p2 = dotList[i];\n                Point p3 = dotList[j];\n                \n                int dx = p3.x - p2.x, dy = p3.y - p2.y;\n                \n                for (int dir = -1; dir <= 1; dir += 2) {\n                    int perpDx = -dir * dy;\n                    int perpDy = dir * dx;\n                    \n                    for (int len = 1; len <= N; len++) {\n                        int p4x = p3.x + perpDx * len;\n                        int p4y = p3.y + perpDy * len;\n                        \n                        if (!inGrid(p4x, p4y)) break;\n                        if (!hasDot(p4x, p4y)) continue;\n                        \n                        int p1x = p2.x + perpDx * len;\n                        int p1y = p2.y + perpDy * len;\n                        \n                        if (!inGrid(p1x, p1y)) continue;\n                        if (hasDot(p1x, p1y)) continue;\n                        \n                        Point p1 = {p1x, p1y};\n                        Point p4 = {p4x, p4y};\n                        \n                        if (!isValidRectangle(p1, p2, p3, p4)) continue;\n                        \n                        if (rectangleOverlaps(p1x, p1y, p2.x, p2.y, p3.x, p3.y, p4x, p4y)) continue;\n                        \n                        if (hasDotsOnPerimeter(p1x, p1y, p2.x, p2.y, p3.x, p3.y, p4x, p4y,\n                                             p2, p3, p4)) continue;\n                        \n                        Operation op;\n                        op.p1 = p1;\n                        op.p2 = p2;\n                        op.p3 = p3;\n                        op.p4 = p4;\n                        op.score = weight(p1x, p1y);\n                        \n                        validMoves.push_back(op);\n                    }\n                }\n            }\n        }\n        \n        return validMoves;\n    }\n    \n    void executeMove(const Operation& op) {\n        dots.insert(((long long)op.p1.x << 32) | (unsigned int)op.p1.y);\n        dotList.push_back(op.p1);\n        addEdge(op.p1.x, op.p1.y, op.p2.x, op.p2.y);\n        addEdge(op.p2.x, op.p2.y, op.p3.x, op.p3.y);\n        addEdge(op.p3.x, op.p3.y, op.p4.x, op.p4.y);\n        addEdge(op.p4.x, op.p4.y, op.p1.x, op.p1.y);\n        operations.push_back(op);\n    }\n    \npublic:\n    RectJoinSolver(int n, int m, const vector<pair<int,int>>& initial) {\n        N = n; M = m;\n        cx = (N - 1) / 2;\n        cy = (N - 1) / 2;\n        \n        for (const auto& p : initial) {\n            dots.insert(((long long)p.first << 32) | (unsigned int)p.second);\n            dotList.push_back({p.first, p.second});\n        }\n    }\n    \n    void solve() {\n        auto startTime = chrono::steady_clock::now();\n        \n        int iteration = 0;\n        const int maxIterations = 6000;\n        \n        while (iteration < maxIterations) {\n            auto currentTime = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n            if (elapsed >= 4850) break;\n            \n            vector<Operation> moves = findValidMoves();\n            \n            if (moves.empty()) break;\n            \n            sort(moves.begin(), moves.end(), [](const Operation& a, const Operation& b) {\n                return a.score > b.score;\n            });\n            \n            executeMove(moves[0]);\n            iteration++;\n        }\n    }\n    \n    void output() const {\n        cout << operations.size() << endl;\n        for (const auto& op : operations) {\n            cout << op.p1.x << \" \" << op.p1.y << \" \"\n                 << op.p2.x << \" \" << op.p2.y << \" \"\n                 << op.p3.x << \" \" << op.p3.y << \" \"\n                 << op.p4.x << \" \" << op.p4.y << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    \n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initial[i].first >> initial[i].second;\n    }\n    \n    RectJoinSolver solver(N, M, initial);\n    solver.solve();\n    solver.output();\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Board representation: 10x10 grid, 0=empty, 1-3=flavors\nstruct Board {\n    int grid[10][10];\n    \n    Board() {\n        for(int i = 0; i < 10; i++)\n            for(int j = 0; j < 10; j++)\n                grid[i][j] = 0;\n    }\n};\n\n// Count connected components and calculate score\nlong long calculateScore(const Board& b) {\n    int visited[10][10];\n    for(int i = 0; i < 10; i++)\n        for(int j = 0; j < 10; j++)\n            visited[i][j] = 0;\n    \n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n    \n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] != 0 && !visited[i][j]) {\n                // BFS for connected component\n                int flavor = b.grid[i][j];\n                int size = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = 1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    size++;\n                    \n                    for(int d = 0; d < 4; d++) {\n                        int nr = r + dr[d];\n                        int nc = c + dc[d];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10) {\n                            if(!visited[nr][nc] && b.grid[nr][nc] == flavor) {\n                                visited[nr][nc] = 1;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Tilt board in given direction\nvoid tilt(Board& b, char dir) {\n    Board newb = b;\n    \n    if(dir == 'F') { // Forward (up)\n        for(int j = 0; j < 10; j++) {\n            int write = 0;\n            for(int i = 0; i < 10; i++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int i = write; i < 10; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'B') { // Backward (down)\n        for(int j = 0; j < 10; j++) {\n            int write = 9;\n            for(int i = 9; i >= 0; i--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int i = 0; i < write; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'L') { // Left\n        for(int i = 0; i < 10; i++) {\n            int write = 0;\n            for(int j = 0; j < 10; j++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int j = write; j < 10; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'R') { // Right\n        for(int i = 0; i < 10; i++) {\n            int write = 9;\n            for(int j = 9; j >= 0; j--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int j = 0; j < write; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    }\n    \n    b = newb;\n}\n\n// Count candies of each flavor\nvoid countFlavors(const Board& b, int& f1, int& f2, int& f3) {\n    f1 = f2 = f3 = 0;\n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] == 1) f1++;\n            else if(b.grid[i][j] == 2) f2++;\n            else if(b.grid[i][j] == 3) f3++;\n        }\n    }\n}\n\n// Calculate normalized score\ndouble getNormalizedScore(const Board& b) {\n    int f1, f2, f3;\n    countFlavors(b, f1, f2, f3);\n    long long numerator = calculateScore(b);\n    long long denominator = (long long)f1*f1 + (long long)f2*f2 + (long long)f3*f3;\n    if(denominator == 0) return 0;\n    return (double)numerator / denominator;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read all flavors in advance\n    vector<int> flavors(100);\n    for(int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    Board board;\n    char directions[] = {'F', 'B', 'L', 'R'};\n    \n    // Process each candy placement\n    for(int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Place candy in p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int count = 0;\n        for(int i = 0; i < 10; i++) {\n            for(int j = 0; j < 10; j++) {\n                if(board.grid[i][j] == 0) {\n                    count++;\n                    if(count == p) {\n                        board.grid[i][j] = flavors[t];\n                        break;\n                    }\n                }\n                if(count == p) break;\n            }\n            if(count == p) break;\n        }\n        \n        // Skip output for last step (nothing happens)\n        if(t == 99) {\n            cout << \"F\" << endl;\n            continue;\n        }\n        \n        // Try all 4 directions and pick the best\n        double bestScore = -1;\n        char bestDir = 'F';\n        \n        for(char dir : directions) {\n            Board temp = board;\n            tilt(temp, dir);\n            double score = getNormalizedScore(temp);\n            \n            if(score > bestScore) {\n                bestScore = score;\n                bestDir = dir;\n            }\n        }\n        \n        // Apply the best direction\n        tilt(board, bestDir);\n        cout << bestDir << endl;\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <bitset>\n\nusing namespace std;\n\nconst int MAX_N = 100;\n\nstruct Graph {\n    int n;\n    vector<bitset<MAX_N>> adj;\n\n    Graph(int n = 0) : n(n), adj(n) {}\n\n    static Graph from_string(int n, const string& s) {\n        Graph g(n);\n        size_t idx = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (idx < s.size()) {\n                    if (s[idx] == '1') {\n                        g.adj[i][j] = 1;\n                        g.adj[j][i] = 1;\n                    }\n                }\n                idx++;\n            }\n        }\n        return g;\n    }\n\n    string to_string() const {\n        string s;\n        s.reserve(n * (n - 1) / 2);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                s += (adj[i][j] ? '1' : '0');\n            }\n        }\n        return s;\n    }\n\n    int edge_count() const {\n        int cnt = 0;\n        for (int i = 0; i < n; ++i) cnt += adj[i].count();\n        return cnt / 2;\n    }\n\n    static Graph random(int n, double p, mt19937& gen) {\n        Graph g(n);\n        uniform_real_distribution<double> dist(0.0, 1.0);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (dist(gen) < p) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                }\n            }\n        }\n        return g;\n    }\n\n    static Graph complete(int n) {\n        Graph g(n);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                g.adj[i][j] = 1;\n                g.adj[j][i] = 1;\n            }\n        }\n        return g;\n    }\n\n    static Graph empty(int n) {\n        return Graph(n);\n    }\n\n    static Graph path(int n) {\n        Graph g(n);\n        for (int i = 0; i < n - 1; ++i) {\n            g.adj[i][i + 1] = 1;\n            g.adj[i + 1][i] = 1;\n        }\n        return g;\n    }\n\n    static Graph cycle(int n) {\n        Graph g(n);\n        for (int i = 0; i < n - 1; ++i) {\n            g.adj[i][i + 1] = 1;\n            g.adj[i + 1][i] = 1;\n        }\n        if (n > 2) {\n            g.adj[0][n - 1] = 1;\n            g.adj[n - 1][0] = 1;\n        }\n        return g;\n    }\n\n    static Graph star(int n) {\n        Graph g(n);\n        for (int i = 1; i < n; ++i) {\n            g.adj[0][i] = 1;\n            g.adj[i][0] = 1;\n        }\n        return g;\n    }\n};\n\nstruct Features {\n    double edge_count;\n    vector<double> sorted_degrees;\n    double sum_sq_deg;\n    double triangle_count;\n\n    Features() : edge_count(0), sum_sq_deg(0), triangle_count(0) {}\n    \n    Features(int n) : edge_count(0), sum_sq_deg(0), triangle_count(0) {\n        sorted_degrees.resize(n);\n    }\n};\n\nFeatures compute_features(const Graph& g) {\n    Features f;\n    f.sorted_degrees.resize(g.n);\n    \n    for (int i = 0; i < g.n; ++i) {\n        f.sorted_degrees[i] = (double)g.adj[i].count();\n        f.sum_sq_deg += f.sorted_degrees[i] * f.sorted_degrees[i];\n    }\n    f.edge_count = g.edge_count();\n    \n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Count triangles\n    for (int i = 0; i < g.n; ++i) {\n        for (int j = i + 1; j < g.n; ++j) {\n            if (g.adj[i][j]) {\n                for (int k = j + 1; k < g.n; ++k) {\n                    if (g.adj[i][k] && g.adj[j][k]) {\n                        f.triangle_count++;\n                    }\n                }\n            }\n        }\n    }\n    return f;\n}\n\n// Use theoretical expected features (much faster than simulation)\nFeatures compute_expected_features(const Graph& g, double eps) {\n    Features f;\n    int n = g.n;\n    int total_edges = n * (n - 1) / 2;\n    f.sorted_degrees.resize(n);\n\n    long long e_g = 0;\n    for(int i=0; i<n; ++i) e_g += g.adj[i].count();\n    e_g /= 2;\n    f.edge_count = e_g * (1.0 - 2.0 * eps) + total_edges * eps;\n\n    for (int i = 0; i < n; ++i) {\n        double d_i = (double)g.adj[i].count();\n        f.sorted_degrees[i] = d_i * (1.0 - 2.0 * eps) + (n - 1) * eps;\n    }\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    double var_deg = (n - 1) * eps * (1.0 - eps);\n    for (int i = 0; i < n; ++i) {\n        double mean_d = f.sorted_degrees[i];\n        f.sum_sq_deg += var_deg + mean_d * mean_d;\n    }\n\n    double p0 = pow(eps, 3);\n    double p1 = pow(eps, 2) * (1.0 - eps);\n    double p2 = eps * pow(1.0 - eps, 2);\n    double p3 = pow(1.0 - eps, 3);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            for (int k = j + 1; k < n; ++k) {\n                int edges = 0;\n                if (g.adj[i][j]) edges++;\n                if (g.adj[i][k]) edges++;\n                if (g.adj[j][k]) edges++;\n                if (edges == 0) f.triangle_count += p0;\n                else if (edges == 1) f.triangle_count += p1;\n                else if (edges == 2) f.triangle_count += p2;\n                else f.triangle_count += p3;\n            }\n        }\n    }\n\n    return f;\n}\n\ndouble feature_distance(const Features& f1, const Features& f2, double eps) {\n    double dist = 0.0;\n    \n    double s_ec = 1.0 / (eps * 100.0 + 1.0);\n    double s_sq = 1.0 / (eps * 1000.0 + 10.0);\n    double s_tc = 1.0 / (eps * 500.0 + 10.0);\n    double s_deg = 1.0 / (eps * 50.0 + 10.0);\n\n    dist += s_ec * (f1.edge_count - f2.edge_count) * (f1.edge_count - f2.edge_count);\n    dist += s_sq * (f1.sum_sq_deg - f2.sum_sq_deg) * (f1.sum_sq_deg - f2.sum_sq_deg);\n    dist += s_tc * (f1.triangle_count - f2.triangle_count) * (f1.triangle_count - f2.triangle_count);\n    \n    for (size_t i = 0; i < f1.sorted_degrees.size(); ++i) {\n        dist += s_deg * (f1.sorted_degrees[i] - f2.sorted_degrees[i]) * \n                (f1.sorted_degrees[i] - f2.sorted_degrees[i]);\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n    int best_N = 40;\n    vector<Graph> best_Gs;\n    vector<Features> best_ExpectedFeatures;\n    double best_score = -1.0;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 4.0;\n\n    // Adaptive N selection based on M\n    vector<int> N_candidates;\n    if (M <= 15) {\n        N_candidates = {20, 30};\n    } else if (M <= 30) {\n        N_candidates = {30, 40};\n    } else if (M <= 50) {\n        N_candidates = {40, 50, 60};\n    } else {\n        N_candidates = {50, 60, 70};\n    }\n\n    for (int N : N_candidates) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        int pool_size = min(100, M * 2);\n        vector<Graph> candidates;\n        candidates.reserve(pool_size + 10);\n        \n        // Add structured graphs\n        candidates.push_back(Graph::empty(N));\n        candidates.push_back(Graph::complete(N));\n        candidates.push_back(Graph::path(N));\n        candidates.push_back(Graph::cycle(N));\n        candidates.push_back(Graph::star(N));\n\n        // Add graphs with different edge counts\n        int total_edges = N * (N - 1) / 2;\n        for (int i = 1; i < M * 2 && i < total_edges; i += max(1, total_edges / (M * 2))) {\n            Graph g(N);\n            int edges_added = 0;\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            for (int u = 0; u < N && edges_added < i; ++u) {\n                for (int v = u + 1; v < N && edges_added < i; ++v) {\n                    if (dist(gen) < 0.5) {\n                        g.adj[u][v] = 1;\n                        g.adj[v][u] = 1;\n                        edges_added++;\n                    }\n                }\n            }\n            candidates.push_back(g);\n        }\n\n        // Add random graphs\n        for (int i = 0; i < pool_size; ++i) {\n            double p = (double)rand() / RAND_MAX;\n            candidates.push_back(Graph::random(N, p, gen));\n        }\n\n        // Compute expected features (theoretical, fast!)\n        vector<Features> cand_expected;\n        cand_expected.reserve(candidates.size());\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            cand_expected.push_back(compute_expected_features(candidates[i], eps));\n        }\n\n        // Greedy selection to maximize minimum distance\n        vector<int> selected_indices;\n        selected_indices.reserve(M);\n        selected_indices.push_back(0);\n        \n        for (int i = 1; i < M; ++i) {\n            int best_idx = -1;\n            double max_min_dist = -1.0;\n            \n            for (size_t j = 0; j < candidates.size(); ++j) {\n                bool found = false;\n                for (int k : selected_indices) {\n                    if (k == (int)j) { found = true; break; }\n                }\n                if (found) continue;\n                \n                double min_d = 1e18;\n                for (int k : selected_indices) {\n                    double d = feature_distance(cand_expected[j], cand_expected[k], eps);\n                    if (d < min_d) min_d = d;\n                }\n                \n                if (min_d > max_min_dist) {\n                    max_min_dist = min_d;\n                    best_idx = (int)j;\n                }\n            }\n            \n            if (best_idx != -1) {\n                selected_indices.push_back(best_idx);\n            } else {\n                int r = rand() % candidates.size();\n                while (true) {\n                    bool found = false;\n                    for (int k : selected_indices) {\n                        if (k == r) { found = true; break; }\n                    }\n                    if (!found) break;\n                    r = rand() % candidates.size();\n                }\n                selected_indices.push_back(r);\n            }\n        }\n\n        // Calculate minimum pairwise distance\n        double min_pair_dist = 1e18;\n        for (size_t i = 0; i < selected_indices.size(); ++i) {\n            for (size_t j = i + 1; j < selected_indices.size(); ++j) {\n                double d = feature_distance(cand_expected[selected_indices[i]], cand_expected[selected_indices[j]], eps);\n                if (d < min_pair_dist) min_pair_dist = d;\n            }\n        }\n\n        // Estimate error rate\n        double E_est = 100.0 * exp(-min_pair_dist / 5000.0);\n        if (E_est < 0.0) E_est = 0.0;\n        if (E_est > 100.0) E_est = 100.0;\n\n        double score = pow(0.9, E_est) / N;\n        \n        if (score > best_score || (abs(score - best_score) < 1e-9 && N < best_N)) {\n            best_score = score;\n            best_N = N;\n            best_Gs.clear();\n            best_ExpectedFeatures.clear();\n            for (int idx : selected_indices) {\n                best_Gs.push_back(candidates[idx]);\n                best_ExpectedFeatures.push_back(cand_expected[idx]);\n            }\n        }\n    }\n\n    // Output\n    cout << best_N << endl;\n    for (const auto& g : best_Gs) {\n        cout << g.to_string() << endl;\n    }\n    cout.flush();\n\n    // Query processing\n    string H_str;\n    for (int q = 0; q < 100; ++q) {\n        cin >> H_str;\n        Graph H = Graph::from_string(best_N, H_str);\n        Features h_feat = compute_features(H);\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double d = feature_distance(h_feat, best_ExpectedFeatures[k], eps);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint N, M, D, K;\nstruct Edge {\n    int u, v, w, id;\n};\nvector<Edge> edges;\nvector<int> edge_day;\nvector<vector<long long>> dist_original;\nvector<vector<pair<int, int>>> adj;\nvector<pair<int, int>> sampled_pairs;\nvector<long long> day_frustration;\nlong long total_frustration;\nmt19937 rng;\nchrono::steady_clock::time_point start_time;\n\nvoid init_rng() {\n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n}\n\nvoid build_adjacency() {\n    adj.assign(N + 1, vector<pair<int, int>>());\n    for (int i = 0; i < M; i++) {\n        adj[edges[i].u].push_back({edges[i].v, i});\n        adj[edges[i].v].push_back({edges[i].u, i});\n    }\n}\n\nvoid calc_original_distances() {\n    dist_original.assign(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int start = 1; start <= N; start++) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        dist_original[start][start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist_original[start][u]) continue;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (dist_original[start][v] > dist_original[start][u] + edges[eid].w) {\n                    dist_original[start][v] = dist_original[start][u] + edges[eid].w;\n                    pq.push({dist_original[start][v], v});\n                }\n            }\n        }\n    }\n}\n\nvoid sample_pairs() {\n    sampled_pairs.clear();\n    int num_samples = min(N * N, 1200);\n    \n    vector<pair<int, int>> all_pairs;\n    for (int i = 1; i <= N; i++) {\n        for (int j = 1; j <= N; j++) {\n            if (i != j) all_pairs.push_back({i, j});\n        }\n    }\n    \n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    for (int i = 0; i < min((int)all_pairs.size(), num_samples); i++) {\n        sampled_pairs.push_back(all_pairs[i]);\n    }\n}\n\nlong long calc_frustration_day(int k) {\n    long long total_increase = 0;\n    \n    for (auto& [start, end] : sampled_pairs) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, 1e18);\n        dist[start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == end) break;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (edge_day[eid] == k) continue;\n                \n                if (dist[v] > dist[u] + edges[eid].w) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        if (dist[end] >= 1e9) {\n            total_increase += 1e9;\n        } else {\n            total_increase += max(0LL, dist[end] - dist_original[start][end]);\n        }\n    }\n    \n    return total_increase;\n}\n\nvoid calc_all_frustrations() {\n    day_frustration.assign(D + 1, 0);\n    total_frustration = 0;\n    for (int k = 1; k <= D; k++) {\n        day_frustration[k] = calc_frustration_day(k);\n        total_frustration += day_frustration[k];\n    }\n}\n\nbool check_time() {\n    auto now = chrono::steady_clock::now();\n    auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed < 5500;\n}\n\nvoid init_solution() {\n    edge_day.assign(M, 0);\n    vector<int> day_count(D + 1, 0);\n    \n    // Sort edges by weight (heuristic: heavier edges might be more important)\n    vector<pair<int, int>> edge_order(M);\n    for (int i = 0; i < M; i++) {\n        edge_order[i] = {edges[i].w, i};\n    }\n    sort(edge_order.begin(), edge_order.end());\n    \n    for (auto& p : edge_order) {\n        int i = p.second;\n        int best_day = 1;\n        for (int d = 2; d <= D; d++) {\n            if (day_count[d] < day_count[best_day]) {\n                best_day = d;\n            }\n        }\n        edge_day[i] = best_day;\n        day_count[best_day]++;\n    }\n}\n\nvoid simulated_annealing() {\n    calc_all_frustrations();\n    long long best_frustration = total_frustration;\n    vector<int> best_day = edge_day;\n    vector<long long> best_day_frustration = day_frustration;\n    \n    double temp = 1e12;\n    double cooling_rate = 0.995;\n    \n    int iterations = 0;\n    \n    while (check_time()) {\n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) {\n            iterations++;\n            continue;\n        }\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        // Swap edges\n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        // Only recalculate affected days\n        long long old_frustration = total_frustration - day_frustration[d1] - day_frustration[d2];\n        day_frustration[d1] = calc_frustration_day(d1);\n        day_frustration[d2] = calc_frustration_day(d2);\n        long long new_frustration = old_frustration + day_frustration[d1] + day_frustration[d2];\n        \n        long long delta = new_frustration - total_frustration;\n        \n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if ((double)uniform_int_distribution<int>(0, 1000000)(rng) / 1000000.0 < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            total_frustration = new_frustration;\n            if (new_frustration < best_frustration) {\n                best_frustration = new_frustration;\n                best_day = edge_day;\n                best_day_frustration = day_frustration;\n            }\n        } else {\n            // Undo swap\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            day_frustration[d1] = best_day_frustration[d1];\n            day_frustration[d2] = best_day_frustration[d2];\n            total_frustration = best_frustration;\n        }\n        \n        temp *= cooling_rate;\n        iterations++;\n        \n        if (temp < 1) break;\n    }\n    \n    edge_day = best_day;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> D >> K;\n    \n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i;\n    }\n    \n    vector<int> x(N + 1), y(N + 1);\n    for (int i = 1; i <= N; i++) {\n        cin >> x[i] >> y[i];\n    }\n    \n    init_rng();\n    build_adjacency();\n    calc_original_distances();\n    sample_pairs();\n    init_solution();\n    \n    if (check_time()) {\n        simulated_annealing();\n    }\n    \n    for (int i = 0; i < M; i++) {\n        cout << edge_day[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int MAXD = 15;\n\nint D;\nvector<string> f[2], r[2];\nint b[2][MAXD][MAXD][MAXD];\n\n// Normalize a shape for comparison (translate to origin, sort)\nvector<tuple<int,int,int>> normalize_shape(const vector<tuple<int,int,int>>& shape) {\n    if (shape.empty()) return shape;\n    \n    vector<tuple<int,int,int>> s = shape;\n    int min_x = 0, min_y = 0, min_z = 0;\n    \n    for (const auto& cell : s) {\n        min_x = min(min_x, get<0>(cell));\n        min_y = min(min_y, get<1>(cell));\n        min_z = min(min_z, get<2>(cell));\n    }\n    \n    for (auto& cell : s) {\n        get<0>(cell) -= min_x;\n        get<1>(cell) -= min_y;\n        get<2>(cell) -= min_z;\n    }\n    \n    sort(s.begin(), s.end());\n    return s;\n}\n\n// Rotate shape around x-axis\nvector<tuple<int,int,int>> rotate_x(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({x, z, -y});\n    }\n    return normalize_shape(result);\n}\n\n// Rotate shape around y-axis\nvector<tuple<int,int,int>> rotate_y(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({-z, y, x});\n    }\n    return normalize_shape(result);\n}\n\n// Rotate shape around z-axis\nvector<tuple<int,int,int>> rotate_z(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({-y, x, z});\n    }\n    return normalize_shape(result);\n}\n\n// Get all 24 rotations of a shape\nvector<vector<tuple<int,int,int>>> get_all_rotations(const vector<tuple<int,int,int>>& shape) {\n    set<vector<tuple<int,int,int>>> seen;\n    queue<vector<tuple<int,int,int>>> q;\n    vector<vector<tuple<int,int,int>>> rotations;\n    \n    vector<tuple<int,int,int>> current = normalize_shape(shape);\n    seen.insert(current);\n    q.push(current);\n    rotations.push_back(current);\n    \n    while (!q.empty()) {\n        auto cur = q.front();\n        q.pop();\n        \n        vector<vector<tuple<int,int,int>>> next_shapes = {\n            rotate_x(cur),\n            rotate_y(cur),\n            rotate_z(cur)\n        };\n        \n        for (const auto& next : next_shapes) {\n            if (seen.find(next) == seen.end()) {\n                seen.insert(next);\n                q.push(next);\n                rotations.push_back(next);\n            }\n        }\n    }\n    \n    return rotations;\n}\n\n// Get canonical form of a shape (minimum among all rotations)\nvector<tuple<int,int,int>> get_canonical_shape(const vector<tuple<int,int,int>>& shape) {\n    auto rotations = get_all_rotations(shape);\n    vector<tuple<int,int,int>> canonical = rotations[0];\n    for (size_t i = 1; i < rotations.size(); i++) {\n        if (rotations[i] < canonical) {\n            canonical = rotations[i];\n        }\n    }\n    return canonical;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        r[i].resize(D);\n        for (int z = 0; z < D; z++) {\n            cin >> f[i][z];\n        }\n        for (int z = 0; z < D; z++) {\n            cin >> r[i][z];\n        }\n    }\n    \n    // Initialize block arrays\n    memset(b, 0, sizeof(b));\n    \n    // Phase 1: Initial placement - place unit blocks at all valid positions\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = 1; // Temporary marker\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Merge adjacent cells into connected components (larger blocks)\n    int temp_b[2][MAXD][MAXD][MAXD];\n    memset(temp_b, 0, sizeof(temp_b));\n    \n    for (int i = 0; i < 2; i++) {\n        bool visited[MAXD][MAXD][MAXD] = {0};\n        int component_counter = 0;\n        \n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0 && !visited[x][y][z]) {\n                        // BFS to find connected component\n                        vector<tuple<int,int,int>> component;\n                        queue<tuple<int,int,int>> q;\n                        \n                        visited[x][y][z] = true;\n                        q.push({x, y, z});\n                        component.push_back({x, y, z});\n                        \n                        int dx[] = {1, -1, 0, 0, 0, 0};\n                        int dy[] = {0, 0, 1, -1, 0, 0};\n                        int dz[] = {0, 0, 0, 0, 1, -1};\n                        \n                        while (!q.empty()) {\n                            auto [cx, cy, cz] = q.front();\n                            q.pop();\n                            \n                            for (int d = 0; d < 6; d++) {\n                                int nx = cx + dx[d];\n                                int ny = cy + dy[d];\n                                int nz = cz + dz[d];\n                                \n                                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                    !visited[nx][ny][nz] && b[i][nx][ny][nz] > 0) {\n                                    visited[nx][ny][nz] = true;\n                                    q.push({nx, ny, nz});\n                                    component.push_back({nx, ny, nz});\n                                }\n                            }\n                        }\n                        \n                        // Assign component ID to all cells in component\n                        component_counter++;\n                        for (auto& [cx, cy, cz] : component) {\n                            temp_b[i][cx][cy][cz] = component_counter;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Copy back to b[i]\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    b[i][x][y][z] = temp_b[i][x][y][z];\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Extract blocks and compute canonical shapes\n    // blocks[i][component_id] = list of cells\n    map<int, vector<tuple<int,int,int>>> blocks[2];\n    \n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        blocks[i][b[i][x][y][z]].push_back({x, y, z});\n                    }\n                }\n            }\n        }\n    }\n    \n    // Compute canonical shape for each component\n    map<int, vector<tuple<int,int,int>>> canonical_shapes[2];\n    for (int i = 0; i < 2; i++) {\n        for (auto& [id, cells] : blocks[i]) {\n            canonical_shapes[i][id] = get_canonical_shape(cells);\n        }\n    }\n    \n    // Phase 4: Assign new IDs\n    // Key rule: Each component within a construction gets a UNIQUE ID\n    // We can reuse IDs BETWEEN constructions when shapes match (but only once per shape)\n    \n    map<int, int> old_to_new_id[2];\n    int new_block_counter = 0;\n    \n    // Track: canonical_shape -> new_id used for this shape in construction 0\n    map<vector<tuple<int,int,int>>, int> shape_to_id_construction_0;\n    \n    // Track: canonical_shape -> whether we've already reused this shape in construction 1\n    map<vector<tuple<int,int,int>>, bool> shape_reused_in_construction_1;\n    \n    // Process construction 0 - each component gets a unique new ID\n    for (auto& [id, canonical] : canonical_shapes[0]) {\n        new_block_counter++;\n        old_to_new_id[0][id] = new_block_counter;\n        \n        // Track the ID for this shape (for potential reuse in construction 1)\n        if (shape_to_id_construction_0.find(canonical) == shape_to_id_construction_0.end()) {\n            shape_to_id_construction_0[canonical] = new_block_counter;\n        }\n    }\n    \n    // Process construction 1 - reuse IDs from construction 0 when shapes match (only once per shape)\n    for (auto& [id, canonical] : canonical_shapes[1]) {\n        if (shape_to_id_construction_0.find(canonical) != shape_to_id_construction_0.end() &&\n            !shape_reused_in_construction_1[canonical]) {\n            // Shape exists in construction 0 and hasn't been reused yet in construction 1\n            old_to_new_id[1][id] = shape_to_id_construction_0[canonical];\n            shape_reused_in_construction_1[canonical] = true;\n        } else {\n            // New shape or already reused, assign new ID\n            new_block_counter++;\n            old_to_new_id[1][id] = new_block_counter;\n            \n            // Track this new ID for this shape\n            if (shape_to_id_construction_0.find(canonical) == shape_to_id_construction_0.end()) {\n                shape_to_id_construction_0[canonical] = new_block_counter;\n            }\n        }\n    }\n    \n    // Phase 5: Apply the remapping\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (b[i][x][y][z] > 0) {\n                        b[i][x][y][z] = old_to_new_id[i][b[i][x][y][z]];\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << new_block_counter << \"\\n\";\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    cout << b[i][x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \");\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst long long INF_COST = 1e18;\nconst int MAX_P = 5000;\n\nstruct Point {\n    int x, y;\n    long long distSq(const Point& other) const {\n        return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y);\n    }\n};\n\nstruct Resident : public Point {\n    int id;\n};\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nint N, M, K;\nvector<Point> stations;\nvector<Edge> edges;\nvector<Resident> residents;\nvector<int> P, B;\nvector<vector<pair<int, int>>> adj;\nvector<bool> reachable;\n\n// Precomputed distances: station[i].distSq[resident[k]]\nvector<vector<long long>> stationResidentDist;\n\n// Precomputed edge list sorted by weight\nvector<int> sortedEdges;\n\n// Fast reachability check\nvoid computeReachable() {\n    reachable.assign(N, false);\n    static vector<int> q;\n    q.clear();\n    \n    reachable[0] = true;\n    q.push_back(0);\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int edgeIdx = edge.second;\n            if (B[edgeIdx] && !reachable[v]) {\n                reachable[v] = true;\n                q.push_back(v);\n            }\n        }\n    }\n}\n\n// Build MST using Union-Find\nvoid buildNetwork() {\n    fill(B.begin(), B.end(), 0);\n    \n    // Union-Find\n    static vector<int> parent;\n    parent.resize(N);\n    iota(parent.begin(), parent.end(), 0);\n    \n    function<int(int)> find = [&](int x) {\n        int root = x;\n        while (parent[root] != root) root = parent[root];\n        int curr = x;\n        while (curr != root) {\n            int next = parent[curr];\n            parent[curr] = root;\n            curr = next;\n        }\n        return root;\n    };\n    \n    // Connect all vertices (MST)\n    for (int idx : sortedEdges) {\n        int u = edges[idx].u;\n        int v = edges[idx].v;\n        int pu = find(u);\n        int pv = find(v);\n        if (pu != pv) {\n            parent[pu] = pv;\n            B[idx] = 1;\n        }\n    }\n}\n\n// Calculate cost (fast version)\nlong long calculateCost() {\n    long long cost = 0;\n    for (int j = 0; j < M; j++) {\n        if (B[j]) cost += edges[j].w;\n    }\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    return cost;\n}\n\n// Count covered residents (only call when needed)\nint countCovered() {\n    int count = 0;\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (reachable[i] && P[i] > 0) {\n                if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                    count++;\n                    break;\n                }\n            }\n        }\n    }\n    return count;\n}\n\n// Optimize P values\nvoid optimizeP() {\n    for (int i = 0; i < N; i++) {\n        if (!reachable[i]) {\n            P[i] = 0;\n            continue;\n        }\n        \n        long long maxDist = 0;\n        for (int k = 0; k < K; k++) {\n            if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                maxDist = max(maxDist, stationResidentDist[i][k]);\n            }\n        }\n        \n        if (maxDist == 0) {\n            P[i] = 0;\n        } else {\n            P[i] = (int)ceil(sqrt((double)maxDist));\n            if (P[i] > MAX_P) P[i] = MAX_P;\n        }\n    }\n}\n\n// Ensure all residents are covered\nvoid ensureCoverage() {\n    for (int k = 0; k < K; k++) {\n        bool covered = false;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i] && P[i] > 0) {\n                if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n        }\n        \n        if (!covered) {\n            int bestStation = -1;\n            long long minDist = INF_COST;\n            \n            for (int i = 0; i < N; i++) {\n                if (reachable[i]) {\n                    if (stationResidentDist[i][k] < minDist) {\n                        minDist = stationResidentDist[i][k];\n                        bestStation = i;\n                    }\n                }\n            }\n            \n            if (bestStation >= 0) {\n                int neededP = (int)ceil(sqrt((double)minDist));\n                if (neededP > MAX_P) neededP = MAX_P;\n                P[bestStation] = max(P[bestStation], neededP);\n            }\n        }\n    }\n}\n\n// Local search with minimal overhead\nvoid localSearch() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int iterations = 5000;\n    double temperature = 3000000.0;\n    double coolingRate = 0.998;\n    \n    computeReachable();\n    long long bestCost = calculateCost();\n    vector<int> bestP = P;\n    vector<int> bestB = B;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int action = (int)(rng() % 4);\n        \n        if (action == 0) {\n            // Activate new station\n            int station = (int)(rng() % N);\n            if (station != 0 && P[station] == 0) {\n                P[station] = 1;\n            }\n        } else if (action == 1) {\n            // Deactivate station\n            int station = (int)(rng() % N);\n            if (station != 0 && P[station] > 0) {\n                P[station] = 0;\n            }\n        } else if (action == 2) {\n            // Increase P\n            int station = (int)(rng() % N);\n            if (P[station] < MAX_P) {\n                P[station] = min(MAX_P, P[station] + (int)(rng() % 150) + 1);\n            }\n        } else {\n            // Decrease P\n            int station = (int)(rng() % N);\n            if (P[station] > 0 && station != 0) {\n                P[station] = max(0, P[station] - (int)(rng() % 150) - 1);\n            }\n        }\n        \n        // Only rebuild network occasionally\n        if (iter % 10 == 0) {\n            buildNetwork();\n            computeReachable();\n        }\n        \n        // Only optimize P occasionally\n        if (iter % 5 == 0) {\n            optimizeP();\n        }\n        \n        // Calculate cost (fast)\n        long long newCost = calculateCost();\n        \n        if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n            bestCost = newCost;\n            bestP = P;\n            bestB = B;\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    P = bestP;\n    B = bestB;\n}\n\n// Initial solution with cluster awareness\nvoid initSolution() {\n    P.assign(N, 0);\n    B.assign(M, 0);\n    \n    // Greedy: assign each resident to nearest station\n    for (int k = 0; k < K; k++) {\n        int bestStation = 0;\n        long long minDist = stationResidentDist[0][k];\n        \n        for (int i = 1; i < N; i++) {\n            if (stationResidentDist[i][k] < minDist) {\n                minDist = stationResidentDist[i][k];\n                bestStation = i;\n            }\n        }\n        \n        int neededP = (int)ceil(sqrt((double)minDist));\n        if (neededP > MAX_P) neededP = MAX_P;\n        P[bestStation] = max(P[bestStation], neededP);\n    }\n    \n    if (P[0] == 0) P[0] = 1;\n    \n    buildNetwork();\n    computeReachable();\n    optimizeP();\n    ensureCoverage();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    stations.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    \n    for (int j = 0; j < M; j++) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n        edges[j].u--;\n        edges[j].v--;\n        edges[j].id = j;\n        adj[edges[j].u].push_back({edges[j].v, j});\n        adj[edges[j].v].push_back({edges[j].u, j});\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n    \n    // Precompute all station-resident distances\n    stationResidentDist.resize(N, vector<long long>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            stationResidentDist[i][k] = stations[i].distSq(residents[k]);\n        }\n    }\n    \n    // Precompute sorted edges\n    sortedEdges.resize(M);\n    iota(sortedEdges.begin(), sortedEdges.end(), 0);\n    sort(sortedEdges.begin(), sortedEdges.end(), [&](int a, int b) {\n        return edges[a].w < edges[b].w;\n    });\n    \n    initSolution();\n    localSearch();\n    \n    // Final validation and repair\n    buildNetwork();\n    computeReachable();\n    optimizeP();\n    ensureCoverage();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\n\nint N = 30;\nvector<vector<int>> grid;\nvector<tuple<int, int, int, int>> operations;\n\n// Get all 6 adjacent positions\nvector<pair<int, int>> get_adj(int x, int y) {\n    vector<pair<int, int>> adj;\n    int dx[] = {-1, -1, 0, 0, 1, 1};\n    int dy[] = {-1, 0, -1, 1, 0, 1};\n    \n    for (int i = 0; i < 6; i++) {\n        int nx = x + dx[i];\n        int ny = y + dy[i];\n        if (nx >= 0 && nx < N && ny >= 0 && ny <= nx) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\n// BFS to find shortest path from (sx, sy) to (tx, ty)\nvector<pair<int, int>> bfs_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {};\n    \n    queue<pair<int, int>> q;\n    map<pair<int, int>, pair<int, int>> parent;\n    \n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == tx && y == ty) {\n            vector<pair<int, int>> path;\n            auto curr = make_pair(tx, ty);\n            while (curr.first != -1 && curr.second != -1) {\n                path.push_back(curr);\n                curr = parent[curr];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto [nx, ny] : get_adj(x, y)) {\n            if (parent.find({nx, ny}) == parent.end()) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    return {};\n}\n\n// Swap balls at two positions and record operation\nvoid swap_positions(int x1, int y1, int x2, int y2) {\n    int temp = grid[x1][y1];\n    grid[x1][y1] = grid[x2][y2];\n    grid[x2][y2] = temp;\n    operations.emplace_back(x1, y1, x2, y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    grid.resize(N);\n    for (int x = 0; x < N; x++) {\n        grid[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n        }\n    }\n    \n    // Track which positions are already filled\n    vector<vector<bool>> filled(N);\n    for (int x = 0; x < N; x++) {\n        filled[x].assign(x + 1, false);\n    }\n    \n    // Process positions from top to bottom\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (filled[x][y]) continue;\n            \n            // Find smallest ball among all unfilled positions\n            int best_val = 1e9;\n            int best_x = -1, best_y = -1;\n            \n            for (int px = x; px < N; px++) {\n                for (int py = 0; py <= px; py++) {\n                    if (!filled[px][py] && grid[px][py] < best_val) {\n                        best_val = grid[px][py];\n                        best_x = px;\n                        best_y = py;\n                    }\n                }\n            }\n            \n            // Move the best ball to current position\n            if (best_x != -1 && (best_x != x || best_y != y)) {\n                vector<pair<int, int>> path = bfs_path(best_x, best_y, x, y);\n                \n                // Perform swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); i++) {\n                    auto [x1, y1] = path[i];\n                    auto [x2, y2] = path[i + 1];\n                    swap_positions(x1, y1, x2, y2);\n                }\n            }\n            \n            filled[x][y] = true;\n        }\n    }\n    \n    // Output results\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <tuple>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\n// Grid dimensions\nconst int D = 9;\nint N;\nvector<pair<int, int>> obstacles;\nvector<vector<int>> grid; // 0: empty, 1: obstacle, 2: container\nvector<vector<int>> container_id; // ID of container at (i, j), -1 if empty\nvector<pair<int, int>> used_coords; // To track placed containers\n\n// Directions\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\n// BFS to find reachable empty squares and distances\n// Returns a map of (i, j) -> distance\nmap<pair<int, int>, int> get_distances(int start_i, int start_j) {\n    map<pair<int, int>, int> dist;\n    queue<pair<int, int>> q;\n    q.push({start_i, start_j});\n    dist[{start_i, start_j}] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n            if (nr >= 0 && nr < D && nc >= 0 && nc < D) {\n                if (grid[nr][nc] == 0 && dist.find({nr, nc}) == dist.end()) {\n                    dist[{nr, nc}] = dist[{r, c}] + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return dist;\n}\n\n// Check if a square is \"Safe\" to place a container\n// Safe means removing it (making it occupied) does not disconnect any other empty squares from entrance\nbool is_safe(int r, int c, int entrance_r, int entrance_c) {\n    // Temporarily mark as occupied\n    int original = grid[r][c];\n    grid[r][c] = 2; // Mark as occupied\n    \n    // Count reachable empty squares\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    int reachable_count = 0;\n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            reachable_count++;\n        }\n    }\n    \n    // Restore\n    grid[r][c] = original;\n    \n    // Calculate total empty squares\n    int total_empty = 0;\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (grid[i][j] == 0) total_empty++;\n        }\n    }\n    \n    // If we placed at (r, c), one less empty square.\n    // So we expect reachable_count == total_empty - 1\n    // Note: (r, c) is now occupied, so it's not counted in total_empty in the check above?\n    // Wait, total_empty is calculated with (r, c) as empty (restored).\n    // So if (r, c) is occupied, total empty is total_empty - 1.\n    // We need all other empty squares to be reachable.\n    // So reachable_count should be total_empty - 1.\n    \n    return reachable_count == total_empty - 1;\n}\n\n// Sort empty squares by accessibility for placement\n// We want to fill Leaves (Far) first, then Closer.\n// So sort by Distance Descending.\n// Safe squares are prioritized.\nvector<pair<int, int>> get_sorted_candidates(int entrance_r, int entrance_c) {\n    map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n    vector<pair<int, int>> candidates;\n    \n    for (auto const& [pos, d] : dist) {\n        if (grid[pos.first][pos.second] == 0) {\n            candidates.push_back(pos);\n        }\n    }\n    \n    // Sort by Distance Descending (Far first)\n    // Tie-breaker: Coordinate order for stability\n    sort(candidates.begin(), candidates.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {\n        if (dist[a] != dist[b]) return dist[a] > dist[b];\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    \n    // Filter Safe squares\n    vector<pair<int, int>> safe_candidates;\n    for (auto p : candidates) {\n        if (is_safe(p.first, p.second, entrance_r, entrance_c)) {\n            safe_candidates.push_back(p);\n        }\n    }\n    \n    // If no safe candidates (should not happen unless 1 square left), return all reachable\n    if (safe_candidates.empty() && !candidates.empty()) {\n        return candidates;\n    }\n    \n    return safe_candidates;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int entrance_r = 0;\n    int entrance_c = (D - 1) / 2;\n    \n    if (!(cin >> D >> N)) return 0;\n    \n    obstacles.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    // Initialize grid\n    grid.assign(D, vector<int>(D, 0));\n    container_id.assign(D, vector<int>(D, -1));\n    \n    for (auto obs : obstacles) {\n        grid[obs.first][obs.second] = 1;\n    }\n    // Entrance is (0, (D-1)/2)\n    // It is not an obstacle.\n    // We treat entrance as empty for placement logic, but we cannot place container there.\n    // Actually problem says \"It is neither the entrance nor an obstacle square\".\n    // So entrance is effectively blocked for placement.\n    grid[entrance_r][entrance_c] = 1; // Mark as obstacle for placement logic\n    \n    set<int> used_ids;\n    int total_containers = D * D - 1 - N;\n    \n    // Placement Phase\n    for (int d = 0; d < total_containers; ++d) {\n        int t;\n        cin >> t;\n        used_ids.insert(t);\n        \n        // Calculate rank r among remaining IDs\n        // r = number of unused IDs smaller than t\n        // Since used_ids contains all IDs placed so far,\n        // unused IDs are those not in used_ids.\n        // But we know t is the current ID.\n        // We can count how many IDs < t are already used.\n        int smaller_used = 0;\n        for (int u : used_ids) {\n            if (u < t) smaller_used++;\n        }\n        // Total IDs < t is t.\n        // So unused IDs < t is t - smaller_used.\n        int r = t - smaller_used;\n        \n        // Get sorted candidates\n        vector<pair<int, int>> candidates = get_sorted_candidates(entrance_r, entrance_c);\n        \n        int U = candidates.size();\n        // We want to place Large IDs at Far (Index 0), Small IDs at Close (Index U-1).\n        // Index k = U - 1 - r.\n        // Clamp k to [0, U-1]\n        int k = U - 1 - r;\n        if (k < 0) k = 0;\n        if (k >= U) k = U - 1;\n        \n        pair<int, int> chosen = candidates[k];\n        grid[chosen.first][chosen.second] = 2;\n        container_id[chosen.first][chosen.second] = t;\n        used_coords.push_back(chosen);\n        \n        cout << chosen.first << \" \" << chosen.second << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval Phase\n    // Greedy: Pick reachable container with min ID\n    vector<pair<int, int>> retrieval_order;\n    // Reset entrance to empty for retrieval logic?\n    // Entrance is (0, 4). It is marked as obstacle (1).\n    // For retrieval, we need to find reachable containers.\n    // Path must be through empty squares.\n    // Entrance is empty (conceptually).\n    // Let's mark entrance as 0 for BFS.\n    grid[entrance_r][entrance_c] = 0;\n    \n    int remaining = total_containers;\n    while (remaining > 0) {\n        // Find all reachable containers\n        // BFS from entrance\n        map<pair<int, int>, int> dist = get_distances(entrance_r, entrance_c);\n        \n        int min_id = 1e9;\n        pair<int, int> best_pos = {-1, -1};\n        \n        for (auto const& [pos, d] : dist) {\n            if (grid[pos.first][pos.second] == 2) {\n                int id = container_id[pos.first][pos.second];\n                if (id < min_id) {\n                    min_id = id;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if (best_pos.first != -1) {\n            retrieval_order.push_back(best_pos);\n            grid[best_pos.first][best_pos.second] = 0; // Becomes empty\n            container_id[best_pos.first][best_pos.second] = -1;\n            remaining--;\n        } else {\n            // Should not happen\n            break;\n        }\n    }\n    \n    for (auto p : retrieval_order) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 101;\n\nint n, m;\nint grid[MAXN][MAXN];\nint adj_count[MAXM][MAXM];\nbool required_adj[MAXM][MAXM];\nint num_tiles[MAXM];\nvector<pair<int, int>> tiles[MAXM];\nint pos[MAXN][MAXN];\nvector<pair<int, int>> all_nonzero;\n\nint visited[MAXN][MAXN];\nint visited_cookie = 0;\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < n && c >= 0 && c < n;\n}\n\n// Check connectivity of a specific color\nbool check_connectivity(int color) {\n    if (num_tiles[color] <= 1) return true;\n    \n    visited_cookie++;\n    int start_r = tiles[color][0].first;\n    int start_c = tiles[color][0].second;\n    \n    int count = 0;\n    vector<pair<int, int>> q;\n    q.reserve(num_tiles[color]);\n    q.push_back({start_r, start_c});\n    visited[start_r][start_c] = visited_cookie;\n    count++;\n    \n    int head = 0;\n    while(head < q.size()){\n        auto [r, c] = q[head++];\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_cookie){\n                visited[nr][nc] = visited_cookie;\n                q.push_back({nr, nc});\n                count++;\n            }\n        }\n    }\n    return count == num_tiles[color];\n}\n\n// Try to remove tile at (r, c)\nbool try_remove(int r, int c) {\n    int color = grid[r][c];\n    if(color == 0) return false;\n    \n    // Check adjacency impact\n    bool adj_ok = true;\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != color){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                // If this is the last edge between c1 and c2, and they are required to be adjacent\n                if(adj_count[c1][c2] == 1 && required_adj[c1][c2]){\n                    adj_ok = false;\n                    break;\n                }\n            }\n        }\n    }\n    if(!adj_ok) return false;\n    \n    // Temporarily remove\n    int idx = pos[r][c];\n    tiles[color].erase(tiles[color].begin() + idx);\n    num_tiles[color]--;\n    grid[r][c] = 0;\n    \n    // Update adj_count\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != 0){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                adj_count[c1][c2]--;\n            }\n        }\n    }\n    \n    bool conn_ok = check_connectivity(color);\n    \n    if(!conn_ok){\n        // Revert\n        grid[r][c] = color;\n        num_tiles[color]++;\n        tiles[color].push_back({r, c});\n        pos[r][c] = tiles[color].size() - 1;\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc)){\n                int ncolor = grid[nr][nc];\n                if(ncolor != 0){\n                    int c1 = min(color, ncolor);\n                    int c2 = max(color, ncolor);\n                    adj_count[c1][c2]++;\n                }\n            }\n        }\n        return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> n >> m)) return 0;\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cin >> grid[i][j];\n            if(grid[i][j] != 0){\n                tiles[grid[i][j]].push_back({i, j});\n                pos[i][j] = tiles[grid[i][j]].size() - 1;\n                num_tiles[grid[i][j]]++;\n                all_nonzero.push_back({i, j});\n            }\n        }\n    }\n    \n    memset(required_adj, 0, sizeof(required_adj));\n    memset(adj_count, 0, sizeof(adj_count));\n    \n    // Compute required adjacencies and counts\n    // Count each edge once\n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            int c = grid[i][j];\n            for(int k=0; k<4; k++){\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if(is_valid(ni, nj)){\n                    int nc = grid[ni][nj];\n                    if(c != nc){\n                        int c1 = min(c, nc);\n                        int c2 = max(c, nc);\n                        // Count only once by checking coordinate order\n                        if((i < ni) || (i == ni && j < nj)){\n                             required_adj[c1][c2] = true;\n                             adj_count[c1][c2]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    mt19937 rng(1337);\n    uniform_int_distribution<int> dist_idx(0, (int)all_nonzero.size() - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int no_change = 0;\n    // Run greedy removal\n    while(true){\n        auto now = chrono::steady_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.9) break;\n        \n        if(all_nonzero.empty()) break;\n        \n        int idx = dist_idx((int)all_nonzero.size());\n        auto [r, c] = all_nonzero[idx];\n        \n        if(try_remove(r, c)){\n            // Remove from all_nonzero\n            int last_idx = all_nonzero.size() - 1;\n            all_nonzero[idx] = all_nonzero[last_idx];\n            all_nonzero.pop_back();\n            no_change = 0;\n        } else {\n            no_change++;\n            if(no_change > 5000) break;\n        }\n    }\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cout << grid[i][j] << (j == n-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <cmath>\n#include <numeric>\n#include <queue>\n\nusing namespace std;\n\n// Global variables for problem constraints\nint N, D, Q;\nvector<double> estimated_weights;\nvector<int> assignment;\nvector<vector<int>> sets;\nvector<double> set_sums;\n\n// Random number generator\nmt19937 rng(123456);\n\n// Function to output a query\nvoid output_query(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n}\n\n// Function to read query response\nstring read_response() {\n    string res;\n    cin >> res;\n    return res;\n}\n\n// Calculate variance of set sums\ndouble calculate_variance() {\n    double total_sum = 0.0;\n    for (double s : set_sums) total_sum += s;\n    double mean = total_sum / D;\n    double variance = 0.0;\n    for (double s : set_sums) {\n        variance += (s - mean) * (s - mean);\n    }\n    return variance / D;\n}\n\n// Initialize sets using LPT heuristic\nvoid initialize_sets() {\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({estimated_weights[i], i});\n    }\n    sort(items.begin(), items.end(), [](const pair<double, int>& a, const pair<double, int>& b) {\n        return a.first > b.first;\n    });\n\n    sets.assign(D, vector<int>());\n    set_sums.assign(D, 0.0);\n    assignment.assign(N, -1);\n\n    for (int i = 0; i < N; ++i) {\n        int item_idx = items[i].second;\n        double weight = items[i].first;\n        \n        int min_set = 0;\n        for (int j = 1; j < D; ++j) {\n            if (set_sums[j] < set_sums[min_set]) {\n                min_set = j;\n            }\n        }\n        \n        sets[min_set].push_back(item_idx);\n        set_sums[min_set] += weight;\n        assignment[item_idx] = min_set;\n    }\n}\n\n// Local search to improve solution\nvoid local_search(int max_iterations) {\n    bool improved = true;\n    int iterations = 0;\n    \n    while (improved && iterations < max_iterations) {\n        improved = false;\n        iterations++;\n        \n        // Try moving each item to a better set\n        for (int i = 0; i < N; ++i) {\n            int current_set = assignment[i];\n            double w = estimated_weights[i];\n            \n            if (current_set < 0 || current_set >= D) continue;\n            \n            // Find best set for this item\n            int best_set = current_set;\n            double best_variance = calculate_variance();\n            \n            // Temporarily remove item\n            set_sums[current_set] -= w;\n            \n            for (int s = 0; s < D; ++s) {\n                if (s == current_set) continue;\n                \n                // Try putting in set s\n                set_sums[s] += w;\n                double var = calculate_variance();\n                \n                if (var < best_variance) {\n                    best_variance = var;\n                    best_set = s;\n                }\n                \n                set_sums[s] -= w;\n            }\n            \n            // Put item back\n            set_sums[current_set] += w;\n            \n            // Move to best set if improved\n            if (best_set != current_set) {\n                // Remove from current set\n                for (auto it = sets[current_set].begin(); it != sets[current_set].end(); ++it) {\n                    if (*it == i) {\n                        sets[current_set].erase(it);\n                        break;\n                    }\n                }\n                // Add to new set\n                sets[best_set].push_back(i);\n                set_sums[current_set] -= w;\n                set_sums[best_set] += w;\n                assignment[i] = best_set;\n                improved = true;\n            }\n        }\n        \n        // Try swapping pairs\n        for (int s1 = 0; s1 < D; ++s1) {\n            for (int s2 = s1 + 1; s2 < D; ++s2) {\n                if (sets[s1].empty() || sets[s2].empty()) continue;\n                \n                for (int i = 0; i < (int)sets[s1].size(); ++i) {\n                    for (int j = 0; j < (int)sets[s2].size(); ++j) {\n                        int u = sets[s1][i];\n                        int v = sets[s2][j];\n                        \n                        double w_u = estimated_weights[u];\n                        double w_v = estimated_weights[v];\n                        \n                        double current_var = calculate_variance();\n                        \n                        // Try swap\n                        set_sums[s1] = set_sums[s1] - w_u + w_v;\n                        set_sums[s2] = set_sums[s2] - w_v + w_u;\n                        \n                        double new_var = calculate_variance();\n                        \n                        if (new_var < current_var - 1e-10) {\n                            sets[s1][i] = v;\n                            sets[s2][j] = u;\n                            assignment[u] = s2;\n                            assignment[v] = s1;\n                            improved = true;\n                        } else {\n                            set_sums[s1] = set_sums[s1] - w_v + w_u;\n                            set_sums[s2] = set_sums[s2] - w_u + w_v;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing for partitioning\nvoid simulate_annealing(int max_time_ms) {\n    initialize_sets();\n    \n    double best_variance = calculate_variance();\n    vector<int> best_assignment = assignment;\n\n    double temperature = 10.0;\n    double cooling_rate = 0.995;\n    int iterations = 0;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    auto end_time = start_time + chrono::milliseconds(max_time_ms);\n\n    while (chrono::high_resolution_clock::now() < end_time && iterations < 80000) {\n        iterations++;\n        \n        int move_type = uniform_int_distribution<int>(0, 1)(rng);\n        \n        if (move_type == 0) {\n            // Swap items between two different sets\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            if (sets[s1].empty() || sets[s2].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)sets[s2].size() - 1)(rng);\n            \n            int u = sets[s1][idx1];\n            int v = sets[s2][idx2];\n            \n            double w_u = estimated_weights[u];\n            double w_v = estimated_weights[v];\n            \n            double new_sum_s1 = set_sums[s1] - w_u + w_v;\n            double new_sum_s2 = set_sums[s2] - w_v + w_u;\n            \n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                sets[s1][idx1] = v;\n                sets[s2][idx2] = u;\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                assignment[v] = s1;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        } else {\n            // Move item from one set to another\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (sets[s1].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int u = sets[s1][idx1];\n            double w_u = estimated_weights[u];\n            \n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            \n            double new_sum_s1 = set_sums[s1] - w_u;\n            double new_sum_s2 = set_sums[s2] + w_u;\n            \n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < 1e-15) break;\n    }\n\n    assignment = best_assignment;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    estimated_weights.assign(N, 1.0);\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // Use exactly Q queries\n    // First ~25% for pairwise, rest for balanced groups\n    int pairwise_queries = max(10, min(Q / 4, N * (N - 1) / 2));\n    int queries_used = 0;\n    \n    // Phase 1: Pairwise comparisons\n    for (int i = 0; i < N && queries_used < pairwise_queries; ++i) {\n        for (int j = i + 1; j < N && queries_used < pairwise_queries; ++j) {\n            vector<int> L = {p[i]};\n            vector<int> R = {p[j]};\n            \n            output_query(L, R);\n            string res = read_response();\n            queries_used++;\n            \n            if (res == \"<\") {\n                estimated_weights[p[i]] *= 0.80;\n                estimated_weights[p[j]] *= 1.20;\n            } else if (res == \">\") {\n                estimated_weights[p[i]] *= 1.20;\n                estimated_weights[p[j]] *= 0.80;\n            }\n        }\n    }\n    \n    // Normalize weights\n    double sum_w = 0.0;\n    for (double w : estimated_weights) sum_w += w;\n    for (double &w : estimated_weights) w = w / sum_w * N;\n    \n    // Phase 2: Balanced group comparisons (use remaining queries)\n    int remaining_queries = Q - queries_used;\n    \n    for (int q = 0; q < remaining_queries; ++q) {\n        shuffle(p.begin(), p.end(), rng);\n        \n        vector<int> L, R;\n        double sum_L = 0.0;\n        double sum_R = 0.0;\n        \n        for (int i = 0; i < N; ++i) {\n            int item = p[i];\n            if (sum_L <= sum_R) {\n                L.push_back(item);\n                sum_L += estimated_weights[item];\n            } else {\n                R.push_back(item);\n                sum_R += estimated_weights[item];\n            }\n        }\n        \n        // Ensure both sides are non-empty\n        if (L.empty() && !R.empty()) {\n            L.push_back(R.back());\n            R.pop_back();\n        }\n        if (R.empty() && !L.empty()) {\n            R.push_back(L.back());\n            L.pop_back();\n        }\n        \n        output_query(L, R);\n        string res = read_response();\n        \n        double diff = sum_L - sum_R;\n        double eta = 0.15 * (1.0 - (double)queries_used / Q);\n        \n        if (res == \"<\") {\n            if (diff > -1e-9) {\n                double adjustment = eta * max(0.0, diff + 1e-9);\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        } else if (res == \">\") {\n            if (diff < 1e-9) {\n                double adjustment = eta * max(0.0, -diff + 1e-9);\n                for (int item : L) estimated_weights[item] += adjustment / L.size();\n                for (int item : R) estimated_weights[item] -= adjustment / R.size();\n            }\n        } else if (res == \"=\") {\n            if (abs(diff) > 1e-9) {\n                double adjustment = eta * diff;\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        }\n        \n        for (double &w : estimated_weights) {\n            if (w < 0.1) w = 0.1;\n        }\n        \n        queries_used++;\n    }\n\n    // Partitioning Phase with multiple restarts\n    int num_restarts = 5;\n    int time_per_restart = 300; // ms\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        // Add some noise to weights for diversity\n        if (restart > 0) {\n            for (double &w : estimated_weights) {\n                w *= (1.0 + uniform_real_distribution<double>(-0.08, 0.08)(rng));\n            }\n            double sum_w = 0.0;\n            for (double w : estimated_weights) sum_w += w;\n            for (double &w : estimated_weights) w = w / sum_w * N;\n        }\n        \n        simulate_annealing(time_per_restart);\n    }\n    \n    // Final local search refinement\n    initialize_sets();\n    local_search(800);\n\n    // Output final assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n\nusing namespace std;\n\n// Global variables to store state\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // pos[v] = {stack_idx, height} (0-indexed stack, 0-indexed height)\nvector<pair<int, int>> operations;\n\n// Function to calculate inversions between a block S and a stack Dest\n// S is a vector of box values in the block (from bottom to top)\n// Dest is the index of the destination stack\n// Returns the number of pairs (u, d) such that u in S, d in stacks[Dest], u > d\nint count_inversions(const vector<int>& S, int dest_idx) {\n    int count = 0;\n    const auto& dest_stack = stacks[dest_idx];\n    for (int u : S) {\n        for (int d : dest_stack) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to calculate inversions between a block S and boxes below v in Source stack\n// v is the box we want to expose (it is below S in the source stack)\n// S is the block above v\nint count_inversions_below(const vector<int>& S, int source_idx, int v) {\n    int count = 0;\n    const auto& source_stack = stacks[source_idx];\n    // Find position of v\n    int v_pos = -1;\n    for (int i = 0; i < source_stack.size(); ++i) {\n        if (source_stack[i] == v) {\n            v_pos = i;\n            break;\n        }\n    }\n    // Iterate boxes below v\n    for (int i = 0; i < v_pos; ++i) {\n        int d = source_stack[i];\n        for (int u : S) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to execute a move\n// Move block starting at box v (and all above it) to dest_stack_idx\n// Returns the number of boxes moved\nint move_block(int v, int dest_stack_idx) {\n    auto [src_idx, h] = pos[v];\n    if (src_idx == dest_stack_idx) return 0;\n    \n    const auto& src_stack = stacks[src_idx];\n    // Identify the block\n    // The block starts at h and goes to top\n    vector<int> block;\n    for (int i = h; i < src_stack.size(); ++i) {\n        block.push_back(src_stack[i]);\n    }\n    \n    // Move to dest\n    for (int u : block) {\n        stacks[dest_stack_idx].push_back(u);\n        pos[u] = {dest_stack_idx, (int)stacks[dest_stack_idx].size() - 1};\n    }\n    \n    // Remove from src\n    for (int i = 0; i < block.size(); ++i) {\n        stacks[src_idx].pop_back();\n    }\n    \n    operations.push_back({v, dest_stack_idx + 1}); // 1-indexed output\n    return block.size();\n}\n\n// Function to remove box v (Op 2)\nvoid remove_box(int v) {\n    auto [src_idx, h] = pos[v];\n    // It must be at the top\n    if (h != (int)stacks[src_idx].size() - 1) {\n        // Should not happen if logic is correct\n        return;\n    }\n    stacks[src_idx].pop_back();\n    operations.push_back({v, 0});\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    pos.resize(N + 1);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Main loop\n    for (int v = 1; v <= N; ++v) {\n        // Check if v is at the top\n        auto [src_idx, h] = pos[v];\n        while (h != (int)stacks[src_idx].size() - 1) {\n            // v is covered. Identify boxes above v.\n            const auto& src_stack = stacks[src_idx];\n            vector<int> boxes_above;\n            for (int i = h + 1; i < src_stack.size(); ++i) {\n                boxes_above.push_back(src_stack[i]);\n            }\n            \n            int k = boxes_above.size();\n            if (k == 0) break; // Should not happen\n\n            // Generate candidates\n            // We try moving suffixes of boxes_above\n            // Suffixes: top 1, top 2, ..., top k (whole block)\n            // To save time, if k is large, we limit suffixes.\n            \n            vector<int> suffix_lengths;\n            if (k <= 5) {\n                for (int len = 1; len <= k; ++len) suffix_lengths.push_back(len);\n            } else {\n                suffix_lengths.push_back(1);\n                suffix_lengths.push_back(2);\n                suffix_lengths.push_back(k);\n            }\n\n            int best_score = 1e9;\n            int best_move_v = -1;\n            int best_dest = -1;\n\n            // Random seed for tie-breaking\n            static mt19937 rng(1337);\n            vector<pair<int, int>> candidates;\n\n            for (int len : suffix_lengths) {\n                // The block to move is the top 'len' boxes of boxes_above\n                // boxes_above is from bottom to top.\n                // So top 'len' boxes are boxes_above[k-len ... k-1]\n                vector<int> S;\n                for (int i = k - len; i < k; ++i) {\n                    S.push_back(boxes_above[i]);\n                }\n                int v_to_move = S.back(); // The bottom-most box of the block being moved\n\n                for (int dest = 0; dest < M; ++dest) {\n                    if (dest == src_idx) continue;\n\n                    // Cost = len + 1\n                    int cost = len + 1;\n\n                    // Delta Potential = New Inversions - Removed Inversions\n                    // New Inversions: pairs (u, d) with u in S, d in stacks[dest], u > d\n                    int new_inv = count_inversions(S, dest);\n                    \n                    // Removed Inversions: pairs (u, d) with u in S, d in stacks[src_idx] below v, u > d\n                    int removed_inv = count_inversions_below(S, src_idx, v);\n\n                    int score = cost + (new_inv - removed_inv);\n\n                    if (score < best_score) {\n                        best_score = score;\n                        candidates.clear();\n                        candidates.push_back({v_to_move, dest});\n                    } else if (score == best_score) {\n                        candidates.push_back({v_to_move, dest});\n                    }\n                }\n            }\n\n            if (candidates.empty()) {\n                // Fallback: move top 1 box to random stack\n                int top_box = boxes_above.back();\n                int dest = src_idx;\n                while (dest == src_idx) dest = rng() % M;\n                move_block(top_box, dest);\n            } else {\n                int idx = rng() % candidates.size();\n                move_block(candidates[idx].first, candidates[idx].second);\n            }\n            \n            // Update pos[v] and h after move\n            // pos[v] is updated inside move_block\n            // But we need to re-check if v is at top\n            auto [new_src, new_h] = pos[v];\n            src_idx = new_src;\n            h = new_h;\n        }\n\n        // Now v should be at top\n        remove_box(v);\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring route;\nvector<pair<int, int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\nstring dir_chars = \"RDLU\";\n\nbool can_move(int i, int j, int di, int dj) {\n    int ni = i + di, nj = j + dj;\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // h has N-1 rows (0 to N-2), each with N characters\n    // v has N rows (0 to N-1), each with N-1 characters\n    if (di == 1) return h[i][j] == '0';      // moving down: check h[i][j]\n    if (di == -1) return h[ni][j] == '0';    // moving up: check h[i-1][j]\n    if (dj == 1) return v[i][j] == '0';      // moving right: check v[i][j]\n    if (dj == -1) return v[i][nj] == '0';    // moving left: check v[i][j-1]\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    // FIX: h has N-1 rows, v has N rows\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    d.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    visited.assign(N, vector<bool>(N, false));\n    \n    // Sort neighbors by dirtiness (descending) for prioritization\n    auto get_neighbors = [&](int i, int j) {\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !visited[ni][nj]) {\n                if (can_move(i, j, di, dj)) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        return neighbors;\n    };\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        auto neighbors = get_neighbors(i, j);\n        for (auto& [dirt, dir] : neighbors) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (!visited[ni][nj] && can_move(i, j, di, dj)) {\n                route += dir_chars[dir];\n                dfs(ni, nj);\n                route += dir_chars[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Validate the route\n    int cur_i = 0, cur_j = 0;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        \n        if (!can_move(cur_i, cur_j, di, dj)) {\n            cerr << \"Invalid move at position (\" << cur_i << \", \" << cur_j << \") with direction \" << c << endl;\n            return 1;\n        }\n        \n        cur_i += di;\n        cur_j += dj;\n    }\n    \n    // Verify we return to (0, 0)\n    if (cur_i != 0 || cur_j != 0) {\n        cerr << \"Route does not return to (0, 0)\" << endl;\n        return 1;\n    }\n    \n    // Verify all squares are visited\n    visited.assign(N, vector<bool>(N, false));\n    cur_i = 0, cur_j = 0;\n    visited[0][0] = true;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        cur_i += di;\n        cur_j += dj;\n        visited[cur_i][cur_j] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) {\n                cerr << \"Square (\" << i << \", \" << j << \") not visited\" << endl;\n                return 1;\n            }\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, M;\nint start_i, start_j;\nvector<string> grid(15);\nvector<string> targets;\nvector<pair<int, int>> char_pos[26];\nvector<pair<int, int>> path;\nint total_cost;\n\n// Precomputed costs\nint cost_from_start[200];\nint cost_between[200][200];\nint last_pos_i[200];\nint last_pos_j[200];\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nint move_cost(int i1, int j1, int i2, int j2) {\n    return manhattan(i1, j1, i2, j2) + 1;\n}\n\npair<int, int> find_nearest(char c, int curr_i, int curr_j) {\n    const vector<pair<int, int>>& positions = char_pos[c - 'A'];\n    if (positions.empty()) return {0, 0};\n    \n    int best_dist = 1e9;\n    pair<int, int> best_pos = {-1, -1};\n    for (auto& p : positions) {\n        int d = manhattan(curr_i, curr_j, p.first, p.second);\n        if (d < best_dist) {\n            best_dist = d;\n            best_pos = p;\n        }\n    }\n    return best_pos;\n}\n\nvoid precompute_costs() {\n    for (int i = 0; i < M; i++) {\n        int ci = start_i, cj = start_j;\n        int cost = 0;\n        for (char c : targets[i]) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            cost += move_cost(ci, cj, pos.first, pos.second);\n            ci = pos.first;\n            cj = pos.second;\n        }\n        cost_from_start[i] = cost;\n        last_pos_i[i] = ci;\n        last_pos_j[i] = cj;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int ci = last_pos_i[i], cj = last_pos_j[i];\n            int cost = 0;\n            for (char c : targets[j]) {\n                pair<int, int> pos = find_nearest(c, ci, cj);\n                cost += move_cost(ci, cj, pos.first, pos.second);\n                ci = pos.first;\n                cj = pos.second;\n            }\n            cost_between[i][j] = cost;\n        }\n    }\n}\n\nint calculate_cost(const vector<int>& order) {\n    int cost = cost_from_start[order[0]];\n    for (int i = 1; i < M; i++) {\n        cost += cost_between[order[i-1]][order[i]];\n    }\n    return cost;\n}\n\nvector<pair<int, int>> generate_path(const vector<int>& order) {\n    vector<pair<int, int>> result;\n    int ci = start_i, cj = start_j;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            result.push_back(pos);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return result;\n}\n\nint calc_swap_delta(const vector<int>& order, int i, int j) {\n    if (i == j) return 0;\n    \n    int delta = 0;\n    \n    if (i > 0) {\n        delta -= cost_between[order[i-1]][order[i]];\n        delta += cost_between[order[i-1]][order[j]];\n    }\n    if (i + 1 < M) {\n        delta -= cost_between[order[i]][order[i+1]];\n        delta += cost_between[order[j]][order[i+1]];\n    }\n    if (j > 0) {\n        delta -= cost_between[order[j-1]][order[j]];\n        delta += cost_between[order[j-1]][order[i]];\n    }\n    if (j + 1 < M) {\n        delta -= cost_between[order[j]][order[j+1]];\n        delta += cost_between[order[i]][order[j+1]];\n    }\n    \n    return delta;\n}\n\nvoid optimize() {\n    precompute_costs();\n    \n    vector<int> best_order(M);\n    int best_cost = 1e9;\n    \n    // More restarts with diverse strategies\n    int restarts = 12;\n    for (int r = 0; r < restarts; r++) {\n        vector<int> order(M);\n        \n        // Different initialization strategies\n        if (r == 0) {\n            // Sequential order\n            iota(order.begin(), order.end(), 0);\n        } else if (r % 4 == 1) {\n            // Random shuffle\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine(r * 1000 + 42));\n        } else if (r % 4 == 2) {\n            // Greedy nearest neighbor from random start\n            vector<bool> used(M, false);\n            int curr = rand() % M;\n            order[0] = curr;\n            used[curr] = true;\n            \n            for (int pos = 1; pos < M; pos++) {\n                int best_next = -1;\n                int best_cost = 1e9;\n                for (int next = 0; next < M; next++) {\n                    if (!used[next]) {\n                        int cost = cost_between[curr][next];\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_next = next;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    order[pos] = best_next;\n                    used[best_next] = true;\n                    curr = best_next;\n                }\n            }\n        } else {\n            // Reverse greedy\n            vector<bool> used(M, false);\n            int curr = rand() % M;\n            order[M-1] = curr;\n            used[curr] = true;\n            \n            for (int pos = M - 2; pos >= 0; pos--) {\n                int best_next = -1;\n                int best_cost = 1e9;\n                for (int next = 0; next < M; next++) {\n                    if (!used[next]) {\n                        int cost = cost_between[next][curr];\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_next = next;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    order[pos] = best_next;\n                    used[best_next] = true;\n                    curr = best_next;\n                }\n            }\n        }\n        \n        int current_cost = calculate_cost(order);\n        \n        // Extended greedy local search\n        int greedy_iters = 3000;\n        int no_improve = 0;\n        \n        while (greedy_iters-- > 0 && no_improve < 50) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            // Try more random swaps\n            for (int iter = 0; iter < 200; iter++) {\n                int i = rand() % M;\n                int j = rand() % M;\n                if (i == j) continue;\n                \n                int delta = calc_swap_delta(order, i, j);\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                current_cost += best_delta;\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        }\n        \n        // Extended simulated annealing\n        double temp = 120.0;\n        double decay = 0.9980;\n        int sa_iters = 20000;\n        \n        for (int iter = 0; iter < sa_iters; iter++) {\n            int i = rand() % M;\n            int j = rand() % M;\n            if (i == j) continue;\n            \n            int delta = calc_swap_delta(order, i, j);\n            \n            if (delta <= 0 || (double)rand() / RAND_MAX < exp(-delta / temp)) {\n                swap(order[i], order[j]);\n                current_cost += delta;\n            }\n            \n            temp *= decay;\n        }\n        \n        // Final exhaustive local search\n        for (int iter = 0; iter < 500; iter++) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    int delta = calc_swap_delta(order, i, j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                current_cost += best_delta;\n            } else {\n                break;\n            }\n        }\n        \n        if (current_cost < best_cost) {\n            best_cost = current_cost;\n            best_order = order;\n        }\n    }\n    \n    path = generate_path(best_order);\n    total_cost = calculate_cost(best_order);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> M >> start_i >> start_j;\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_pos[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    memset(cost_from_start, 0, sizeof(cost_from_start));\n    memset(cost_between, 0, sizeof(cost_between));\n    memset(last_pos_i, 0, sizeof(last_pos_i));\n    memset(last_pos_j, 0, sizeof(last_pos_j));\n    \n    optimize();\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint N, M;\ndouble epsilon;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read basic info\n    if (!(cin >> N >> M >> epsilon)) {\n        return 0;\n    }\n    \n    // Read shapes (we'll ignore them for this simple solution)\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n        }\n    }\n    \n    // Drill all cells and collect those with oil\n    vector<pair<int, int>> has_oil;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << \" \" << j << endl;\n            int v;\n            cin >> v;\n            if (v > 0) {\n                has_oil.push_back(make_pair(i, j));\n            }\n        }\n    }\n    \n    // Submit result\n    cout << \"a \" << has_oil.size();\n    for (size_t k = 0; k < has_oil.size(); ++k) {\n        cout << \" \" << has_oil[k].first << \" \" << has_oil[k].second;\n    }\n    cout << endl;\n    \n    int res;\n    cin >> res;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\n\nbool checkOverlap(const vector<Rect>& day_rects, const Rect& new_rect, int exclude_idx) {\n    for (int i = 0; i < (int)day_rects.size(); i++) {\n        if (i == exclude_idx) continue;\n        if (!(day_rects[i].i1 <= new_rect.i0 ||\n              day_rects[i].i0 >= new_rect.i1 ||\n              day_rects[i].j1 <= new_rect.j0 ||\n              day_rects[i].j0 >= new_rect.j1)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nbool isValidRect(const Rect& r) {\n    return r.i0 >= 0 && r.i1 <= W && r.j0 >= 0 && r.j1 <= W && \n           r.i0 < r.i1 && r.j0 < r.j1;\n}\n\nlong long calculateAreaCost(int d) {\n    long long cost = 0;\n    for (int k = 0; k < N; k++) {\n        int actual = rects[d][k].area();\n        if (actual < a[d][k]) {\n            cost += 100LL * (a[d][k] - actual);\n        }\n    }\n    return cost;\n}\n\n// Fast partition cost using bitsets for comparison\nlong long calculatePartitionCost(int d) {\n    if (d == 0) return 0;\n    \n    long long cost = 0;\n    \n    // Build segment sets for both days\n    vector<vector<bool>> H_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> H_curr(W, vector<bool>(W, false));\n    vector<vector<bool>> V_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> V_curr(W, vector<bool>(W, false));\n    \n    for (int k = 0; k < N; k++) {\n        // Previous day\n        int i0 = rects[d-1][k].i0, i1 = rects[d-1][k].i1;\n        int j0 = rects[d-1][k].j0, j1 = rects[d-1][k].j1;\n        \n        if (i0 > 0 && i0 < W)\n            for (int j = j0; j < j1; j++) H_prev[i0][j] = true;\n        if (i1 > 0 && i1 < W)\n            for (int j = j0; j < j1; j++) H_prev[i1][j] = true;\n        if (j0 > 0 && j0 < W)\n            for (int i = i0; i < i1; i++) V_prev[i][j0] = true;\n        if (j1 > 0 && j1 < W)\n            for (int i = i0; i < i1; i++) V_prev[i][j1] = true;\n        \n        // Current day\n        i0 = rects[d][k].i0; i1 = rects[d][k].i1;\n        j0 = rects[d][k].j0; j1 = rects[d][k].j1;\n        \n        if (i0 > 0 && i0 < W)\n            for (int j = j0; j < j1; j++) H_curr[i0][j] = true;\n        if (i1 > 0 && i1 < W)\n            for (int j = j0; j < j1; j++) H_curr[i1][j] = true;\n        if (j0 > 0 && j0 < W)\n            for (int i = i0; i < i1; i++) V_curr[i][j0] = true;\n        if (j1 > 0 && j1 < W)\n            for (int i = i0; i < i1; i++) V_curr[i][j1] = true;\n    }\n    \n    for (int i = 1; i < W; i++)\n        for (int j = 0; j < W; j++)\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n    for (int i = 0; i < W; i++)\n        for (int j = 1; j < W; j++)\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n    \n    return cost;\n}\n\nlong long calculateTotalCost() {\n    long long total = 0;\n    for (int d = 0; d < D; d++) {\n        total += calculateAreaCost(d);\n        total += calculatePartitionCost(d);\n    }\n    return total;\n}\n\nvoid initializeSolution() {\n    rects.resize(D);\n    \n    for (int d = 0; d < D; d++) {\n        rects[d].resize(N);\n        \n        // Divide grid into N vertical strips - guaranteed non-overlapping\n        for (int k = 0; k < N; k++) {\n            int desired = a[d][k];\n            \n            int j0 = k * W / N;\n            int j1 = (k + 1) * W / N;\n            if (k == N - 1) j1 = W;\n            \n            // Find best height for desired area\n            int best_h = 1;\n            for (int h = 1; h <= W; h++) {\n                int area = h * (j1 - j0);\n                if (area >= desired) {\n                    best_h = h;\n                    break;\n                }\n            }\n            \n            best_h = min(best_h, W);\n            if (best_h == 0) best_h = 1;\n            rects[d][k] = {0, j0, best_h, j1};\n        }\n    }\n}\n\nvoid optimizeSolution() {\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Very limited optimization - just a few passes\n    int max_iterations = 3000;\n    int iterations = 0;\n    \n    while (iterations < max_iterations) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > 2.6) break;\n        \n        int d = (int)(dist(gen) * D);\n        int k = (int)(dist(gen) * N);\n        \n        Rect original = rects[d][k];\n        int attempts = 0;\n        bool valid = false;\n        Rect new_rect = original;\n        \n        while (attempts < 30 && !valid) {\n            int di = (int)((dist(gen) * 6 - 3));\n            int dj = (int)((dist(gen) * 6 - 3));\n            int dh = (int)((dist(gen) * 3 - 1));\n            int dw = (int)((dist(gen) * 3 - 1));\n            \n            int ni0 = max(0, min(W - 1, original.i0 + di));\n            int nj0 = max(0, min(W - 1, original.j0 + dj));\n            int ni1 = max(ni0 + 1, min(W, original.i1 + dh));\n            int nj1 = max(nj0 + 1, min(W, original.j1 + dw));\n            \n            new_rect = {ni0, nj0, ni1, nj1};\n            \n            if (isValidRect(new_rect) && !checkOverlap(rects[d], new_rect, k)) {\n                valid = true;\n            } else {\n                attempts++;\n            }\n        }\n        \n        if (valid) {\n            // Only accept if area improves (partition cost is secondary)\n            long long old_area = calculateAreaCost(d);\n            rects[d][k] = new_rect;\n            long long new_area = calculateAreaCost(d);\n            \n            // Accept if area improves or stays same\n            if (new_area <= old_area || dist(gen) < 0.1) {\n                // Keep new\n            } else {\n                rects[d][k] = original;\n            }\n        }\n        \n        iterations++;\n    }\n}\n\nvoid improveAreaSatisfaction() {\n    // Priority: satisfy area requirements (100x penalty)\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int current_area = rects[d][k].area();\n            if (current_area < a[d][k]) {\n                // Try to expand in all directions\n                int dirs[8][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, \n                                  {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};\n                \n                for (int dir = 0; dir < 8; dir++) {\n                    int di = dirs[dir][0];\n                    int dj = dirs[dir][1];\n                    \n                    int ni0 = rects[d][k].i0 + di;\n                    int nj0 = rects[d][k].j0 + dj;\n                    int ni1 = rects[d][k].i1 + di;\n                    int nj1 = rects[d][k].j1 + dj;\n                    \n                    if (isValidRect({ni0, nj0, ni1, nj1})) {\n                        Rect test_rect = {ni0, nj0, ni1, nj1};\n                        if (!checkOverlap(rects[d], test_rect, k)) {\n                            rects[d][k] = test_rect;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n    \n    initializeSolution();\n    optimizeSolution();\n    improveAreaSatisfaction();\n    \n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[d][k].i0 << \" \" << rects[d][k].j0 << \" \"\n                 << rects[d][k].i1 << \" \" << rects[d][k].j1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst long long MOD = 998244353;\n\n// Structures\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\n// Global variables\nint initial_board[N][N];\nint board[N][N];\nint stamps[M][3][3];\nlong long best_score;\nvector<Op> best_ops;\n\n// Random number generator\nmt19937_64 rng;\n\n// Function to calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += (board[i][j] % MOD);\n        }\n    }\n    return score;\n}\n\n// Function to apply an operation\nvoid apply_op(const Op& op, int val) {\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            board[op.p + i][op.q + j] += val * stamps[op.m][i][j];\n        }\n    }\n}\n\n// Function to calculate delta score for an operation\nlong long get_delta_score(const Op& op, int val) {\n    long long delta = 0;\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            int r = op.p + i;\n            int c = op.q + j;\n            long long old_val = board[r][c] % MOD;\n            long long new_val = (board[r][c] + val * stamps[op.m][i][j]) % MOD;\n            delta += new_val - old_val;\n        }\n    }\n    return delta;\n}\n\n// Solver class to manage state for each restart\nstruct Solver {\n    vector<Op> ops;\n    long long score;\n    double temperature;\n    int iterations;\n    \n    Solver() : iterations(0), temperature(1e9) {}\n    \n    void init_random() {\n        ops.clear();\n        ops.reserve(K);\n        uniform_int_distribution<int> dist_m(0, M - 1);\n        uniform_int_distribution<int> dist_p(0, N - 3);\n        uniform_int_distribution<int> dist_q(0, N - 3);\n        \n        for (int i = 0; i < K; ++i) {\n            ops.push_back({dist_m(rng), dist_p(rng), dist_q(rng)});\n        }\n        \n        reset_board();\n        for (const auto& op : ops) {\n            apply_op(op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void init_greedy() {\n        ops.clear();\n        ops.reserve(K);\n        \n        reset_board();\n        \n        // Greedy initialization\n        for (int iter = 0; iter < K; ++iter) {\n            long long max_delta = -1e18;\n            Op best_op = {0, 0, 0};\n            \n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            \n            for (int sample = 0; sample < 400; ++sample) {\n                Op op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n                long long delta = get_delta_score(op, 1);\n                if (delta > max_delta) {\n                    max_delta = delta;\n                    best_op = op;\n                }\n            }\n            \n            ops.push_back(best_op);\n            apply_op(best_op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void reset_board() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                board[i][j] = initial_board[i][j];\n            }\n        }\n    }\n    \n    void step() {\n        iterations++;\n        \n        // Select a random operation index to change\n        uniform_int_distribution<int> dist_idx(0, K - 1);\n        int idx = dist_idx(rng);\n        Op old_op = ops[idx];\n        \n        // Decide move type\n        uniform_real_distribution<double> dist_type(0.0, 1.0);\n        double r = dist_type(rng);\n        \n        Op new_op = old_op;\n        \n        if (r < 0.05) {\n            // 5%: Full random replacement\n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            new_op.m = dist_m(rng);\n            new_op.p = dist_p(rng);\n            new_op.q = dist_q(rng);\n        } else if (r < 0.30) {\n            // 25%: Change stamp type\n            uniform_real_distribution<double> dist_m_change(0.0, 1.0);\n            if (dist_m_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_m(0, M - 1);\n                new_op.m = dist_m(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.m = (old_op.m + delta + M) % M;\n            }\n        } else if (r < 0.55) {\n            // 25%: Change p position\n            uniform_real_distribution<double> dist_p_change(0.0, 1.0);\n            if (dist_p_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                new_op.p = dist_p(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta));\n            }\n        } else if (r < 0.80) {\n            // 25%: Change q position\n            uniform_real_distribution<double> dist_q_change(0.0, 1.0);\n            if (dist_q_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.q = max(0, min(N - 3, old_op.q + delta));\n            }\n        } else {\n            // 20%: Change both p and q\n            uniform_real_distribution<double> dist_pq_change(0.0, 1.0);\n            if (dist_pq_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.p = dist_p(rng);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta_p = (rng() % 3) - 1;\n                int delta_q = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta_p));\n                new_op.q = max(0, min(N - 3, old_op.q + delta_q));\n            }\n        }\n        \n        // Calculate delta\n        long long delta = 0;\n        \n        // Remove old op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = old_op.p + i;\n                int c = old_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                if (temp_val < 0) temp_val += MOD;\n                delta += temp_val - old_val;\n            }\n        }\n        \n        // Add new op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = new_op.p + i;\n                int c = new_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Acceptance probability\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            uniform_real_distribution<double> dist_prob(0.0, 1.0);\n            double prob = exp(delta / temperature);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            ops[idx] = new_op;\n            // Apply the change to the board\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = old_op.p + i;\n                    int c = old_op.q + j;\n                    board[r][c] -= stamps[old_op.m][i][j];\n                }\n            }\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = new_op.p + i;\n                    int c = new_op.q + j;\n                    board[r][c] += stamps[new_op.m][i][j];\n                }\n            }\n            score += delta;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_ops = ops;\n            }\n        }\n        \n        // Cool down\n        temperature *= 0.9998;\n        if (temperature < 1e-9) temperature = 1e-9;\n    }\n    \n    void local_search(int max_iterations) {\n        // Efficient local search with sampling\n        int improved = 1;\n        int iter_count = 0;\n        \n        while (improved && iter_count < max_iterations) {\n            improved = 0;\n            iter_count++;\n            \n            // Sample random operations to modify\n            for (int sample = 0; sample < 30; ++sample) {\n                uniform_int_distribution<int> dist_idx(0, K - 1);\n                int idx = dist_idx(rng);\n                Op old_op = ops[idx];\n                \n                // Try limited number of changes\n                for (int try_count = 0; try_count < 15; ++try_count) {\n                    uniform_int_distribution<int> dist_m(0, M - 1);\n                    uniform_int_distribution<int> dist_p(0, N - 3);\n                    uniform_int_distribution<int> dist_q(0, N - 3);\n                    \n                    Op new_op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n                    \n                    // Calculate delta\n                    long long delta = 0;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            int r = old_op.p + i;\n                            int c = old_op.q + j;\n                            long long old_val = board[r][c] % MOD;\n                            long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                            if (temp_val < 0) temp_val += MOD;\n                            delta += temp_val - old_val;\n                        }\n                    }\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            int r = new_op.p + i;\n                            int c = new_op.q + j;\n                            long long old_val = board[r][c] % MOD;\n                            long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                            delta += new_val - old_val;\n                        }\n                    }\n                    \n                    if (delta > 0) {\n                        // Apply the change\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = old_op.p + i;\n                                int c = old_op.q + j;\n                                board[r][c] -= stamps[old_op.m][i][j];\n                            }\n                        }\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = new_op.p + i;\n                                int c = new_op.q + j;\n                                board[r][c] += stamps[new_op.m][i][j];\n                            }\n                        }\n                        ops[idx] = new_op;\n                        score += delta;\n                        improved = 1;\n                        iterations++;\n                        \n                        if (score > best_score) {\n                            best_score = score;\n                            best_ops = ops;\n                        }\n                        \n                        // Break and restart search after improvement\n                        goto next_sample;\n                    }\n                }\n                next_sample:;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    // Read board\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> board[i][j];\n            initial_board[i][j] = board[i][j];\n        }\n    }\n\n    // Read stamps\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            for (int l = 0; l < 3; ++l) {\n                cin >> stamps[i][j][l];\n            }\n        }\n    }\n\n    best_score = -1;\n    best_ops.clear();\n\n    // Time management\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1950); // Leave 50ms for output\n    \n    Solver solver;\n    int restart_count = 0;\n    \n    // Multiple restarts with mixed initialization\n    while (chrono::steady_clock::now() < end_time) {\n        restart_count++;\n        \n        // Alternate between random and greedy initialization\n        if (restart_count % 2 == 1) {\n            solver.init_greedy();\n        } else {\n            solver.init_random();\n        }\n        \n        // Run SA for shorter periods\n        int sa_iterations = 0;\n        while (chrono::steady_clock::now() < end_time && \n               solver.temperature > 1e-9 && \n               sa_iterations < 4000) {\n            solver.step();\n            sa_iterations++;\n            if (solver.temperature < 1e-9) break;\n        }\n        \n        // Final local search with limited iterations\n        solver.local_search(150);\n    }\n\n    // Output best solution\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int EMPTY = -1;\n\nstruct Crane {\n    int id;\n    int x, y; // x = row, y = column\n    int holding; // Container ID or EMPTY\n    bool is_large;\n    bool active;\n};\n\nstruct State {\n    int grid[N][N];\n    vector<Crane> cranes;\n    vector<vector<int>> input_queue;\n    vector<int> dispatch_count;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = EMPTY;\n            input_queue.push_back({});\n            dispatch_count.push_back(0);\n        }\n        cranes.resize(N);\n        for(int i=0; i<N; ++i) {\n            cranes[i] = {i, i, 0, EMPTY, (i == 0), true};\n        }\n    }\n};\n\n// Fast validity check for single crane action\nbool isActionValid(const Crane& c, char action, const State& s) {\n    if (!c.active) return false;\n    int nx = c.x, ny = c.y;\n    int holding = c.holding;\n\n    if (action == 'P') {\n        return holding == EMPTY && s.grid[c.x][c.y] != EMPTY;\n    }\n    if (action == 'Q') {\n        return holding != EMPTY && s.grid[c.x][c.y] == EMPTY;\n    }\n    if (action == 'B') {\n        return holding == EMPTY;\n    }\n    // x is row (down), y is column (right)\n    if (action == 'U') nx--;\n    else if (action == 'D') nx++;\n    else if (action == 'L') ny--;\n    else if (action == 'R') ny++;\n    else if (action == '.') return true;\n    else return false;\n\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    if (!c.is_large && holding != EMPTY && s.grid[nx][ny] != EMPTY) return false;\n    return true;\n}\n\n// Get next position after action\npair<int,int> getNextPos(const Crane& c, char action) {\n    int nx = c.x, ny = c.y;\n    if (action == 'U') nx--;\n    else if (action == 'D') nx++;\n    else if (action == 'L') ny--;\n    else if (action == 'R') ny++;\n    return {nx, ny};\n}\n\n// Check collision between two cranes\nbool hasCollision(const Crane& c1, char a1, const Crane& c2, char a2) {\n    if (!c1.active || !c2.active) return false;\n    \n    pair<int,int> p1 = getNextPos(c1, a1);\n    pair<int,int> p2 = getNextPos(c2, a2);\n    \n    // Overlap\n    if (p1 == p2) return true;\n    \n    // Swap\n    if (p1 == make_pair(c2.x, c2.y) && p2 == make_pair(c1.x, c1.y)) return true;\n    \n    return false;\n}\n\n// Get priority score for an action (higher is better)\nint getActionPriority(const Crane& c, char action, const State& s) {\n    if (!isActionValid(c, action, s)) return -1e9;\n    \n    int priority = 0;\n    int holding = c.holding;\n    \n    // Picking at receiving gate is very important\n    if (action == 'P' && c.y == 0 && s.grid[c.x][c.y] != EMPTY) {\n        priority += 1000;\n    }\n    \n    // Dropping at dispatch gate is very important\n    if (action == 'Q' && c.y == N-1 && holding != EMPTY) {\n        if (holding / N == c.x) {\n            priority += 1000;\n        } else {\n            priority += 100;\n        }\n    }\n    \n    // Moving towards target\n    if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n        int target_y = (holding != EMPTY) ? N-1 : 0;\n        int dist_before = abs(c.y - target_y);\n        int ny = c.y;\n        if (action == 'L') ny--;\n        else if (action == 'R') ny++;\n        int dist_after = abs(ny - target_y);\n        if (dist_after < dist_before) {\n            priority += 100;\n        }\n        \n        // Move away from receiving gate if blocking\n        if (c.y == 0 && s.input_queue[c.x].empty()) {\n            if (action == 'R') {\n                priority += 50;\n            }\n        }\n    }\n    \n    if (action != '.' && action != 'B') {\n        priority += 10;\n    }\n    \n    return priority;\n}\n\n// Simulate one turn\nvoid simulateTurn(State& s, const vector<char>& actions) {\n    // Step 1: Receiving Gates\n    for(int i=0; i<N; ++i) {\n        if (!s.input_queue[i].empty()) {\n            bool blocked = false;\n            if (s.grid[i][0] != EMPTY) blocked = true;\n            for(const auto& c : s.cranes) {\n                if (c.active && c.x == i && c.y == 0) blocked = true;\n            }\n            if (!blocked) {\n                s.grid[i][0] = s.input_queue[i].front();\n                s.input_queue[i].erase(s.input_queue[i].begin());\n            }\n        }\n    }\n    \n    // Step 2: Crane Actions\n    int next_grid[N][N];\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            next_grid[i][j] = s.grid[i][j];\n        }\n    }\n    \n    // Apply P\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        if (actions[i] == 'P') {\n            next_grid[s.cranes[i].x][s.cranes[i].y] = EMPTY;\n            s.cranes[i].holding = s.grid[s.cranes[i].x][s.cranes[i].y];\n        }\n    }\n    \n    // Apply Q\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        if (actions[i] == 'Q') {\n            next_grid[s.cranes[i].x][s.cranes[i].y] = s.cranes[i].holding;\n            s.cranes[i].holding = EMPTY;\n        }\n    }\n    \n    // Apply Move/Bomb\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        char act = actions[i];\n        if (act == 'B') {\n            s.cranes[i].active = false;\n        } else if (act == 'U') s.cranes[i].x--;\n        else if (act == 'D') s.cranes[i].x++;\n        else if (act == 'L') s.cranes[i].y--;\n        else if (act == 'R') s.cranes[i].y++;\n    }\n    \n    // Update grid\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            s.grid[i][j] = next_grid[i][j];\n        }\n    }\n    \n    // Step 3: Dispatch\n    for(int i=0; i<N; ++i) {\n        int container = s.grid[i][4];\n        if (container != EMPTY) {\n            int expected = N * i + s.dispatch_count[i];\n            if (container == expected) {\n                s.dispatch_count[i]++;\n                s.grid[i][4] = EMPTY;\n            }\n        }\n    }\n}\n\n// Get all valid actions for a crane\nvector<char> getValidActions(const Crane& c, const State& s) {\n    vector<char> actions;\n    if (!c.active) {\n        actions.push_back('.');\n        return actions;\n    }\n    \n    vector<char> candidates = {'P', 'Q', 'U', 'D', 'L', 'R', '.'};\n    for(char a : candidates) {\n        if (isActionValid(c, a, s)) {\n            actions.push_back(a);\n        }\n    }\n    return actions;\n}\n\n// Check if a set of actions has any collisions\nbool hasAnyCollision(const vector<char>& actions, const State& s) {\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if (hasCollision(s.cranes[i], actions[i], s.cranes[j], actions[j])) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int N_in;\n    if (!(cin >> N_in)) return 0;\n    \n    State s;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int val;\n            cin >> val;\n            s.input_queue[i].push_back(val);\n        }\n    }\n    \n    vector<string> result(N, \"\");\n    \n    auto start_time = chrono::steady_clock::now();\n    int time_limit_ms = 2800;\n    \n    for(int t=0; t<MAX_TURNS; ++t) {\n        auto current_time = chrono::steady_clock::now();\n        int elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n        \n        bool all_dispatched = true;\n        for(int i=0; i<N; ++i) {\n            if (s.dispatch_count[i] < N) {\n                all_dispatched = false;\n                break;\n            }\n        }\n        if (all_dispatched) break;\n        \n        // Get valid actions for each crane\n        vector<vector<char>> valid_actions(N);\n        for(int i=0; i<N; ++i) {\n            valid_actions[i] = getValidActions(s.cranes[i], s);\n        }\n        \n        // Find best collision-free action combination\n        // Use greedy approach with backtracking for small N\n        vector<char> best_actions(N, '.');\n        int best_score = -1e9;\n        \n        // Try all combinations (at most 7^5 = 16807, but usually much less)\n        // Use recursive search with pruning\n        auto search = [&](auto&& self, int idx, vector<char>& current, int& score) -> void {\n            if (idx == N) {\n                if (!hasAnyCollision(current, s)) {\n                    // Calculate score\n                    int sc = 0;\n                    for(int i=0; i<N; ++i) {\n                        sc += getActionPriority(s.cranes[i], current[i], s);\n                    }\n                    if (sc > best_score) {\n                        best_score = sc;\n                        best_actions = current;\n                    }\n                }\n                return;\n            }\n            \n            for(char a : valid_actions[idx]) {\n                current[idx] = a;\n                self(self, idx + 1, current, score);\n            }\n        };\n        \n        vector<char> current(N);\n        int dummy = 0;\n        search(search, 0, current, dummy);\n        \n        // Apply actions\n        for(int i=0; i<N; ++i) {\n            result[i] += best_actions[i];\n        }\n        \n        simulateTurn(s, best_actions);\n    }\n    \n    for(int i=0; i<N; ++i) {\n        cout << result[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nint dist(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nstruct Solution {\n    vector<vector<pair<int, int>>> requests;\n    vector<int> source_order;\n    vector<vector<int>> sink_orders;\n    long long cost = -1;\n    \n    void calculate_cost(const vector<Point>& sources, const vector<Point>& sinks) {\n        long long total_cost = 0;\n        int cx = 0, cy = 0;\n        int cur_load = 0;\n        \n        for (int src_idx : source_order) {\n            if (sink_orders[src_idx].empty()) continue;\n            \n            // Move to source (empty)\n            int d = dist({cx, cy}, sources[src_idx]);\n            total_cost += d * 100;\n            cx = sources[src_idx].x;\n            cy = sources[src_idx].y;\n            \n            // Load\n            int total_load = 0;\n            for (int sink_idx : sink_orders[src_idx]) {\n                total_load += requests[src_idx][sink_idx].second;\n            }\n            total_cost += total_load;\n            cur_load = total_load;\n            \n            // Visit sinks (loaded)\n            for (int sink_idx : sink_orders[src_idx]) {\n                int v_idx = requests[src_idx][sink_idx].first;\n                int amount = requests[src_idx][sink_idx].second;\n                int tx = sinks[v_idx].x;\n                int ty = sinks[v_idx].y;\n                \n                d = dist({cx, cy}, {tx, ty});\n                total_cost += d * (100 + cur_load);\n                cx = tx;\n                cy = ty;\n                total_cost += amount;\n                cur_load -= amount;\n            }\n        }\n        cost = total_cost;\n    }\n};\n\nSolution solve(const vector<Point>& sources, const vector<Point>& sinks, \n               vector<int>& remaining_supply, vector<int>& remaining_demand) {\n    Solution sol;\n    sol.requests.resize(sources.size());\n    sol.sink_orders.resize(sources.size());\n    \n    // Greedy matching\n    vector<int> temp_supply = remaining_supply;\n    vector<int> temp_demand = remaining_demand;\n    \n    while (true) {\n        int best_u = -1, best_v = -1;\n        int min_d = 1e9;\n        \n        for (int i = 0; i < (int)sources.size(); ++i) {\n            if (temp_supply[i] <= 0) continue;\n            for (int j = 0; j < (int)sinks.size(); ++j) {\n                if (temp_demand[j] <= 0) continue;\n                int d = dist(sources[i], sinks[j]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_u = i;\n                    best_v = j;\n                }\n            }\n        }\n        \n        if (best_u == -1) break;\n        \n        int amount = min(temp_supply[best_u], temp_demand[best_v]);\n        temp_supply[best_u] -= amount;\n        temp_demand[best_v] -= amount;\n        sol.requests[best_u].push_back({best_v, amount});\n    }\n    \n    // Optimize sink ordering using nearest neighbor\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        if (sol.requests[i].empty()) continue;\n        \n        sol.sink_orders[i].resize(sol.requests[i].size());\n        vector<bool> sink_done(sol.requests[i].size(), false);\n        int cur_x = sources[i].x, cur_y = sources[i].y;\n        \n        for (size_t k = 0; k < sol.requests[i].size(); ++k) {\n            int best_v = -1;\n            int min_d = 1e9;\n            for (size_t idx = 0; idx < sol.requests[i].size(); ++idx) {\n                if (!sink_done[idx]) {\n                    int v_idx = sol.requests[i][idx].first;\n                    int d = dist({cur_x, cur_y}, sinks[v_idx]);\n                    if (d < min_d) {\n                        min_d = d;\n                        best_v = (int)idx;\n                    }\n                }\n            }\n            if (best_v != -1) {\n                sink_done[best_v] = true;\n                sol.sink_orders[i][k] = best_v;\n                int v_idx = sol.requests[i][best_v].first;\n                cur_x = sinks[v_idx].x;\n                cur_y = sinks[v_idx].y;\n            }\n        }\n        \n        // 2-opt for sink ordering\n        bool sink_improved = true;\n        while (sink_improved) {\n            sink_improved = false;\n            for (size_t a = 0; a < sol.sink_orders[i].size() - 1; ++a) {\n                for (size_t b = a + 1; b < sol.sink_orders[i].size(); ++b) {\n                    auto calc = [&]() {\n                        int cost = 0;\n                        int cx = sources[i].x, cy = sources[i].y;\n                        for (size_t k = 0; k < sol.sink_orders[i].size(); ++k) {\n                            int v_idx = sol.requests[i][sol.sink_orders[i][k]].first;\n                            cost += dist({cx, cy}, sinks[v_idx]);\n                            cx = sinks[v_idx].x;\n                            cy = sinks[v_idx].y;\n                        }\n                        return cost;\n                    };\n                    \n                    int old_cost = calc();\n                    reverse(sol.sink_orders[i].begin() + a, sol.sink_orders[i].begin() + b + 1);\n                    int new_cost = calc();\n                    \n                    if (new_cost >= old_cost) {\n                        reverse(sol.sink_orders[i].begin() + a, sol.sink_orders[i].begin() + b + 1);\n                    } else {\n                        sink_improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Calculate end positions\n    vector<Point> source_end(sources.size());\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        if (sol.sink_orders[i].empty()) {\n            source_end[i] = sources[i];\n        } else {\n            int last_sink = sol.requests[i][sol.sink_orders[i].back()].first;\n            source_end[i] = sinks[last_sink];\n        }\n    }\n    \n    // Source ordering with 2-opt\n    sol.source_order.resize(sources.size());\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        sol.source_order[i] = i;\n    }\n    \n    // Greedy initial ordering\n    vector<bool> visited(sources.size(), false);\n    int cur_x = 0, cur_y = 0;\n    for (int iter = 0; iter < (int)sources.size(); ++iter) {\n        int best = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); ++i) {\n            if (!visited[i]) {\n                int d = dist({cur_x, cur_y}, sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best = i;\n                }\n            }\n        }\n        if (best != -1) {\n            visited[best] = true;\n            sol.source_order[iter] = best;\n            cur_x = source_end[best].x;\n            cur_y = source_end[best].y;\n        }\n    }\n    \n    // 2-opt for source ordering\n    bool src_improved = true;\n    while (src_improved) {\n        src_improved = false;\n        for (int i = 0; i < (int)sources.size() - 1; ++i) {\n            for (int j = i + 1; j < (int)sources.size(); ++j) {\n                auto calc = [&]() {\n                    int cost = 0;\n                    int cx = 0, cy = 0;\n                    for (int idx : sol.source_order) {\n                        cost += dist({cx, cy}, sources[idx]);\n                        cx = source_end[idx].x;\n                        cy = source_end[idx].y;\n                    }\n                    return cost;\n                };\n                \n                int old_cost = calc();\n                reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                int new_cost = calc();\n                \n                if (new_cost >= old_cost) {\n                    reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                } else {\n                    src_improved = true;\n                }\n            }\n        }\n    }\n    \n    sol.calculate_cost(sources, sinks);\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<vector<int>> h(N, vector<int>(N));\n    vector<Point> sources, sinks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n            }\n        }\n    }\n\n    int num_sources = sources.size();\n    int num_sinks = sinks.size();\n\n    vector<int> remaining_supply(num_sources);\n    vector<int> remaining_demand(num_sinks, 0);\n    \n    for (int i = 0; i < num_sources; ++i) {\n        remaining_supply[i] = h[sources[i].x][sources[i].y];\n    }\n    for (int i = 0; i < num_sinks; ++i) {\n        remaining_demand[i] = abs(h[sinks[i].x][sinks[i].y]);\n    }\n\n    // Try multiple solutions and pick best\n    Solution best_sol = solve(sources, sinks, remaining_supply, remaining_demand);\n    \n    // Try shuffled starting points\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    vector<int> perm(num_sources);\n    for (int i = 0; i < num_sources; ++i) perm[i] = i;\n    \n    for (int trial = 0; trial < 5; ++trial) {\n        shuffle(perm.begin(), perm.end(), rng);\n        vector<int> temp_supply(num_sources);\n        vector<int> temp_demand(num_sinks);\n        copy(remaining_supply.begin(), remaining_supply.end(), temp_supply.begin());\n        copy(remaining_demand.begin(), remaining_demand.end(), temp_demand.begin());\n        \n        Solution sol = solve(sources, sinks, temp_supply, temp_demand);\n        if (sol.cost < best_sol.cost || best_sol.cost == -1) {\n            best_sol = sol;\n        }\n    }\n\n    // Routing\n    int cx = 0, cy = 0;\n    vector<string> ops;\n    \n    auto move_to = [&](int tx, int ty) {\n        while (cx < tx) {\n            cx++;\n            ops.push_back(\"D\");\n        }\n        while (cx > tx) {\n            cx--;\n            ops.push_back(\"U\");\n        }\n        while (cy < ty) {\n            cy++;\n            ops.push_back(\"R\");\n        }\n        while (cy > ty) {\n            cy--;\n            ops.push_back(\"L\");\n        }\n    };\n\n    auto load = [&](int amount) {\n        ops.push_back(\"+\" + to_string(amount));\n    };\n\n    auto unload = [&](int amount) {\n        ops.push_back(\"-\" + to_string(amount));\n    };\n\n    // Execute optimized tour\n    for (int src_idx : best_sol.source_order) {\n        if (best_sol.sink_orders[src_idx].empty()) continue;\n        \n        // Move to source\n        move_to(sources[src_idx].x, sources[src_idx].y);\n\n        // Load soil\n        int total_load = 0;\n        for (int sink_idx : best_sol.sink_orders[src_idx]) {\n            total_load += best_sol.requests[src_idx][sink_idx].second;\n        }\n        if (total_load > 0) {\n            load(total_load);\n        }\n\n        // Execute Sink Tour\n        for (int sink_idx : best_sol.sink_orders[src_idx]) {\n            int v_idx = best_sol.requests[src_idx][sink_idx].first;\n            int amount = best_sol.requests[src_idx][sink_idx].second;\n            int tx = sinks[v_idx].x;\n            int ty = sinks[v_idx].y;\n            \n            move_to(tx, ty);\n            unload(amount);\n        }\n    }\n\n    // Output\n    for (const string &s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\nint N, M, T;\nint seed_count;\nvector<vector<int>> seeds;\nvector<int> seed_val;\nvector<vector<int>> adj;\nvector<int> pos_neighbors;\nvector<int> grid;\nlong long current_score;\n\n// Random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n// Enhanced complementarity metric with better diversity scoring\ninline long long calc_complementarity(int u, int v) {\n    long long s = 0;\n    int diversity = 0;\n    int strong_diff = 0;\n    \n    for (int l = 0; l < M; ++l) {\n        int a = seeds[u][l];\n        int b = seeds[v][l];\n        s += (a > b ? a : b);\n        \n        // Bonus for complementary patterns\n        if (a > 60 && b < 35) { diversity += 4; strong_diff++; }\n        else if (a > 55 && b < 30) { diversity += 3; strong_diff++; }\n        else if (a > 50 && b < 25) { diversity += 2; strong_diff++; }\n        else if (abs(a - b) > 30) { diversity += 2; }\n        else if (abs(a - b) > 20) { diversity += 1; }\n    }\n    \n    // Extra bonus if seeds have different strong criteria\n    if (strong_diff >= 3) diversity += 5;\n    \n    return s + diversity;\n}\n\n// Calculate total score for current grid configuration\ninline long long calc_grid_score() {\n    long long total = 0;\n    for (int i = 0; i < N * N; ++i) {\n        for (int n : adj[i]) {\n            if (i < n) {\n                total += calc_complementarity(grid[i], grid[n]) * pos_neighbors[i];\n            }\n        }\n    }\n    return total;\n}\n\nvoid init_adj() {\n    adj.assign(N * N, vector<int>());\n    pos_neighbors.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (i > 0) { adj[u].push_back((i - 1) * N + j); pos_neighbors[u]++; }\n            if (i < N - 1) { adj[u].push_back((i + 1) * N + j); pos_neighbors[u]++; }\n            if (j > 0) { adj[u].push_back(i * N + (j - 1)); pos_neighbors[u]++; }\n            if (j < N - 1) { adj[u].push_back(i * N + (j + 1)); pos_neighbors[u]++; }\n        }\n    }\n}\n\n// Initialize grid with different strategies\nvoid init_grid(int strategy) {\n    vector<int> p(seed_count);\n    iota(p.begin(), p.end(), 0);\n    \n    if (strategy == 0) {\n        // Sort by total value\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            return seed_val[a] > seed_val[b];\n        });\n    } else if (strategy == 1) {\n        // Sort by max criterion value\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            int max_a = 0, max_b = 0;\n            for (int l = 0; l < M; ++l) {\n                max_a = max(max_a, seeds[a][l]);\n                max_b = max(max_b, seeds[b][l]);\n            }\n            return max_a > max_b;\n        });\n    } else if (strategy == 2) {\n        // Sort by diversity (number of high-value criteria)\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            int div_a = 0, div_b = 0;\n            for (int l = 0; l < M; ++l) {\n                div_a += (seeds[a][l] > 50 ? 1 : 0);\n                div_b += (seeds[b][l] > 50 ? 1 : 0);\n            }\n            return div_a > div_b;\n        });\n    } else {\n        // Random order\n        shuffle(p.begin(), p.end(), gen);\n    }\n    \n    vector<int> pos_order(N * N);\n    iota(pos_order.begin(), pos_order.end(), 0);\n    sort(pos_order.begin(), pos_order.end(), [&](int a, int b) {\n        return pos_neighbors[a] > pos_neighbors[b];\n    });\n    \n    for (int k = 0; k < N * N; ++k) {\n        grid[pos_order[k]] = p[k];\n    }\n    \n    current_score = calc_grid_score();\n}\n\nvoid sa_optimize(int iterations) {\n    uniform_int_distribution<int> dist_pos(0, N * N - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n    \n    double temp = 5000.0;\n    double cooling = 0.998;\n    \n    for (int iter = 0; iter < iterations; ++iter) {\n        int u = dist_pos(gen);\n        int v = dist_pos(gen);\n        if (u == v) continue;\n        \n        long long old_score = current_score;\n        \n        long long delta = 0;\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta -= calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta -= calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n        }\n        \n        swap(grid[u], grid[v]);\n        \n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta += calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta += calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n        }\n        \n        if (delta >= 0 || dist_prob(gen) < exp(delta / temp)) {\n            current_score += delta;\n        } else {\n            swap(grid[u], grid[v]);\n            current_score = old_score;\n        }\n        \n        temp *= cooling;\n    }\n}\n\nvoid local_refinement() {\n    // Quick local search - try swapping each pair once\n    for (int u = 0; u < N * N; ++u) {\n        for (int v = u + 1; v < N * N; ++v) {\n            long long old_score = current_score;\n            \n            long long delta = 0;\n            for (int n : adj[u]) {\n                if (n == v) continue;\n                delta -= calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n            }\n            for (int n : adj[v]) {\n                if (n == u) continue;\n                delta -= calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n            }\n            \n            swap(grid[u], grid[v]);\n            \n            for (int n : adj[u]) {\n                if (n == v) continue;\n                delta += calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n            }\n            for (int n : adj[v]) {\n                if (n == u) continue;\n                delta += calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n            }\n            \n            if (delta > 0) {\n                current_score += delta;\n            } else {\n                swap(grid[u], grid[v]);\n                current_score = old_score;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> T;\n    seed_count = 2 * N * (N - 1);\n    seeds.resize(seed_count, vector<int>(M));\n    seed_val.resize(seed_count);\n    \n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n            seed_val[i] += seeds[i][j];\n        }\n    }\n    \n    init_adj();\n    grid.resize(N * N);\n    \n    for (int t = 0; t < T; ++t) {\n        for (int i = 0; i < seed_count; ++i) {\n            seed_val[i] = 0;\n            for (int j = 0; j < M; ++j) {\n                seed_val[i] += seeds[i][j];\n            }\n        }\n        \n        // Multiple restarts with different strategies\n        long long best_score = -1;\n        vector<int> best_grid;\n        \n        // Full optimizations with different strategies\n        for (int restart = 0; restart < 3; ++restart) {\n            init_grid(restart);\n            sa_optimize(40000);\n            local_refinement();\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_grid = grid;\n            }\n        }\n        \n        // Quick random restart\n        init_grid(3);\n        sa_optimize(20000);\n        local_refinement();\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_grid = grid;\n        }\n        \n        grid = best_grid;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << grid[i * N + j] << (j == N - 1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n        \n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Takoyaki {\n    Point src, tgt;\n    int id;\n    bool done = false;\n};\n\nint N, M, V;\nvector<string> s_grid, t_grid;\nvector<Takoyaki> takoyakis;\nvector<int> edge_len;\nint root_x, root_y;\nint dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // R, D, L, U\nchar dir_char[4] = {'R', 'D', 'L', 'U'};\n\n// Current state\nint arm_dir[16]; // direction of each edge (0-3)\nbool holding[16]; // whether each fingertip is holding\nPoint fingertip_pos[16]; // current position of each fingertip\n\n// Calculate fingertip positions based on root and directions\nvoid update_fingertip_positions() {\n    for (int i = 1; i < edge_len.size() + 1; i++) {\n        int fx = root_x + dir[arm_dir[i]][0] * edge_len[i];\n        int fy = root_y + dir[arm_dir[i]][1] * edge_len[i];\n        fingertip_pos[i] = {fx, fy};\n    }\n}\n\n// Check if position is valid\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there's a takoyaki at position\nbool has_takoyaki(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1';\n}\n\n// Check if position is a target\nbool is_target(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return t_grid[x][y] == '1';\n}\n\n// Check if position has been filled (target completed)\nbool is_filled(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1' && t_grid[x][y] == '1';\n}\n\n// Find nearest available source for a fingertip\nPoint find_nearest_source(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].src.x) + abs(fp.y - takoyakis[i].src.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].src;\n        }\n    }\n    return best;\n}\n\n// Find nearest available target for a fingertip\nPoint find_nearest_target(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].tgt.x) + abs(fp.y - takoyakis[i].tgt.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].tgt;\n        }\n    }\n    return best;\n}\n\n// Get direction to move towards a target\nint get_direction(Point current, Point target) {\n    if (current.x < target.x) return 1; // D\n    if (current.x > target.x) return 3; // U\n    if (current.y < target.y) return 0; // R\n    if (current.y > target.y) return 2; // L\n    return 0; // Default\n}\n\n// Get rotation to achieve desired direction\nchar get_rotation(int current_dir, int target_dir) {\n    int diff = (target_dir - current_dir + 4) % 4;\n    if (diff == 0) return '.';\n    if (diff == 1 || diff == 3) return 'R'; // clockwise\n    return 'L'; // counterclockwise\n}\n\n// Check if all takoyaki are delivered\nbool all_delivered() {\n    for (int i = 0; i < M; i++) {\n        if (!takoyakis[i].done) return false;\n    }\n    return true;\n}\n\n// Check if a source still has takoyaki\nbool source_has_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return s_grid[p.x][p.y] == '1' && t_grid[p.x][p.y] == '0';\n}\n\n// Check if a target needs takoyaki\nbool target_needs_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return t_grid[p.x][p.y] == '1' && s_grid[p.x][p.y] == '0';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> V;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    \n    for (int i = 0; i < N; i++) cin >> s_grid[i];\n    for (int i = 0; i < N; i++) cin >> t_grid[i];\n    \n    // Parse takoyaki positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                takoyakis.push_back({{i, j}, {0, 0}, (int)takoyakis.size()});\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (t_grid[i][j] == '1' && s_grid[i][j] == '0') {\n                // Find matching source\n                for (auto& t : takoyakis) {\n                    if (t.tgt.x == 0 && t.tgt.y == 0) {\n                        t.tgt = {i, j};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Design star topology robot\n    int num_fingertips = min(V - 1, M); // Each fingertip handles one takoyaki\n    \n    // Output robot design\n    cout << num_fingertips + 1 << \"\\n\";\n    edge_len.resize(num_fingertips + 1);\n    \n    // Use different edge lengths for better coverage\n    for (int i = 1; i <= num_fingertips; i++) {\n        edge_len[i] = min(i * 2, N - 1);\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Initial position: center of grid\n    root_x = N / 2;\n    root_y = N / 2;\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Initialize directions (all pointing right initially)\n    for (int i = 0; i <= num_fingertips; i++) {\n        arm_dir[i] = 0;\n        holding[i] = false;\n    }\n    \n    update_fingertip_positions();\n    \n    // Main operation loop\n    int turn = 0;\n    int max_turns = 80000; // Leave margin for system test\n    \n    while (turn < max_turns && !all_delivered()) {\n        string cmd = \"\";\n        \n        // Step 1: Decide arm movement\n        // Find average direction to move towards pending sources/targets\n        int total_dx = 0, total_dy = 0;\n        int count = 0;\n        \n        for (int i = 0; i < M; i++) {\n            if (takoyakis[i].done) continue;\n            if (holding[i % (num_fingertips + 1)]) {\n                // Moving towards target\n                total_dx += takoyakis[i].tgt.x - root_x;\n                total_dy += takoyakis[i].tgt.y - root_y;\n            } else {\n                // Moving towards source\n                total_dx += takoyakis[i].src.x - root_x;\n                total_dy += takoyakis[i].src.y - root_y;\n                count++;\n            }\n        }\n        \n        // Determine movement direction\n        char move = '.';\n        if (count > 0) {\n            if (abs(total_dx) > abs(total_dy)) {\n                if (total_dx > 0) move = 'D';\n                else if (total_dx < 0) move = 'U';\n            } else {\n                if (total_dy > 0) move = 'R';\n                else if (total_dy < 0) move = 'L';\n            }\n        }\n        \n        // Check if movement is valid\n        int nx = root_x, ny = root_y;\n        if (move == 'D') nx++;\n        else if (move == 'U') nx--;\n        else if (move == 'R') ny++;\n        else if (move == 'L') ny--;\n        \n        if (!is_valid(nx, ny)) move = '.';\n        else { root_x = nx; root_y = ny; }\n        \n        cmd += move;\n        \n        // Step 2: Decide rotations for each fingertip\n        for (int i = 1; i <= num_fingertips; i++) {\n            char rot = '.';\n            \n            // Find what this fingertip should do\n            Point fp = fingertip_pos[i];\n            \n            if (holding[i]) {\n                // Try to drop at target\n                Point tgt = find_nearest_target(fp);\n                if (tgt.x >= 0 && target_needs_takoyaki(tgt)) {\n                    // Calculate direction to reach target\n                    int dx = tgt.x - root_x;\n                    int dy = tgt.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            } else {\n                // Try to pick from source\n                Point src = find_nearest_source(fp);\n                if (src.x >= 0 && source_has_takoyaki(src)) {\n                    // Calculate direction to reach source\n                    int dx = src.x - root_x;\n                    int dy = src.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            }\n            \n            cmd += rot;\n        }\n        \n        // Step 3: Decide pick/place actions\n        for (int i = 1; i <= num_fingertips; i++) {\n            update_fingertip_positions();\n            Point fp = fingertip_pos[i];\n            char action = '.';\n            \n            if (is_valid(fp.x, fp.y)) {\n                if (holding[i] && target_needs_takoyaki(fp.x, fp.y)) {\n                    // Drop takoyaki\n                    action = 'P';\n                    holding[i] = false;\n                    s_grid[fp.x][fp.y] = '1';\n                    \n                    // Mark as done\n                    for (int j = 0; j < M; j++) {\n                        if (!takoyakis[j].done && \n                            takoyakis[j].tgt.x == fp.x && \n                            takoyakis[j].tgt.y == fp.y) {\n                            takoyakis[j].done = true;\n                            break;\n                        }\n                    }\n                } else if (!holding[i] && source_has_takoyaki(fp.x, fp.y)) {\n                    // Pick takoyaki\n                    action = 'P';\n                    holding[i] = true;\n                    s_grid[fp.x][fp.y] = '0';\n                }\n            }\n            \n            cmd += action;\n        }\n        \n        // Add '.' for root (not a fingertip)\n        cmd += '.';\n        \n        cout << cmd << \"\\n\";\n        turn++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Distance squared\nlong long distSq(Point p1, Point p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Simple DSU for clustering\nstruct SimpleDSU {\n    vector<int> parent;\n    SimpleDSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx != ry) parent[rx] = ry;\n    }\n};\n\nstruct ClusterInfo {\n    int id;\n    vector<int> indices;\n    long long minX, maxX, minY, maxY;\n    int m_count, s_count;\n    long long score;\n};\n\n// Check if point is inside or on boundary of orthogonal polygon\nbool isInside(const vector<Point>& poly, Point p) {\n    int n = poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        bool cond1 = ((poly[i].y > p.y) != (poly[j].y > p.y));\n        if (poly[j].y != poly[i].y) {\n            bool cond2 = (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (double)(poly[j].y - poly[i].y) + poly[i].x);\n            if (cond1 && cond2) inside = !inside;\n        }\n    }\n    if (!inside) {\n        for (int i = 0; i < n; ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % n];\n            if (p1.x == p2.x) {\n                if (p.x == p1.x && min(p1.y, p2.y) <= p.y && p.y <= max(p1.y, p2.y)) return true;\n            } else {\n                if (p.y == p1.y && min(p1.x, p2.x) <= p.x && p.x <= max(p1.x, p2.x)) return true;\n            }\n        }\n    }\n    return inside;\n}\n\n// Calculate score for a polygon\nlong long calculateScore(const vector<Point>& poly) {\n    int m_cnt = 0;\n    int s_cnt = 0;\n    for (const auto& m : mackerels) {\n        if (isInside(poly, m)) m_cnt++;\n    }\n    for (const auto& s : sardines) {\n        if (isInside(poly, s)) s_cnt++;\n    }\n    return (long long)m_cnt - s_cnt;\n}\n\n// Validate polygon\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4) return false;\n    for (int i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x != p2.x && p1.y != p2.y) return false;\n    }\n    // Check for consecutive duplicates\n    for (int i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x && p1.y == p2.y) return false;\n    }\n    return true;\n}\n\n// Remove duplicate consecutive vertices\nvector<Point> removeDuplicates(const vector<Point>& poly) {\n    vector<Point> result;\n    for (int i = 0; i < poly.size(); ++i) {\n        if (i > 0 && poly[i].x == poly[i-1].x && poly[i].y == poly[i-1].y) continue;\n        result.push_back(poly[i]);\n    }\n    // Check first and last\n    if (result.size() > 1 && result.front().x == result.back().x && result.front().y == result.back().y) {\n        result.pop_back();\n    }\n    return result;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // 1. Cluster Mackerels\n    const long long CLUSTER_DIST_SQ = 6000LL * 6000LL;\n    SimpleDSU dsu_m(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (distSq(mackerels[i], mackerels[j]) <= CLUSTER_DIST_SQ) {\n                dsu_m.unite(i, j);\n            }\n        }\n    }\n\n    vector<vector<int>> m_clusters(N);\n    for (int i = 0; i < N; ++i) {\n        m_clusters[dsu_m.find(i)].push_back(i);\n    }\n\n    // 2. Evaluate Clusters\n    vector<ClusterInfo> good_clusters;\n    for (int i = 0; i < N; ++i) {\n        if (m_clusters[i].empty()) continue;\n        \n        long long minX = 1e9, maxX = -1e9, minY = 1e9, maxY = -1e9;\n        for (int idx : m_clusters[i]) {\n            minX = min(minX, mackerels[idx].x);\n            maxX = max(maxX, mackerels[idx].x);\n            minY = min(minY, mackerels[idx].y);\n            maxY = max(maxY, mackerels[idx].y);\n        }\n\n        int m_cnt = m_clusters[i].size();\n        int s_cnt = 0;\n        for (const auto& s : sardines) {\n            if (s.x >= minX && s.x <= maxX && s.y >= minY && s.y <= maxY) {\n                s_cnt++;\n            }\n        }\n\n        long long sc = (long long)m_cnt - s_cnt;\n        if (sc > 0) {\n            good_clusters.push_back({i, m_clusters[i], minX, maxX, minY, maxY, m_cnt, s_cnt, sc});\n        }\n    }\n\n    // 3. Merge Good Clusters\n    sort(good_clusters.begin(), good_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n        return a.score > b.score;\n    });\n\n    vector<int> used(N, 0);\n    vector<ClusterInfo> final_clusters;\n    \n    auto distBox = [](const ClusterInfo& a, const ClusterInfo& b) {\n        long long dx = max(0LL, max(a.minX, b.minX) - min(a.maxX, b.maxX));\n        long long dy = max(0LL, max(a.minY, b.minY) - min(a.maxY, b.maxY));\n        return dx * dx + dy * dy;\n    };\n\n    for (int i = 0; i < (int)good_clusters.size(); ++i) {\n        if (used[i]) continue;\n        \n        ClusterInfo current = good_clusters[i];\n        used[i] = 1;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int j = 0; j < (int)good_clusters.size(); ++j) {\n                if (i == j || used[j]) continue;\n                \n                long long d2 = distBox(current, good_clusters[j]);\n                if (d2 <= 2500LL * 2500LL) { // Increased threshold\n                    current.minX = min(current.minX, good_clusters[j].minX);\n                    current.maxX = max(current.maxX, good_clusters[j].maxX);\n                    current.minY = min(current.minY, good_clusters[j].minY);\n                    current.maxY = max(current.maxY, good_clusters[j].maxY);\n                    \n                    int m_cnt = 0;\n                    int s_cnt = 0;\n                    for (const auto& m : mackerels) {\n                        if (m.x >= current.minX && m.x <= current.maxX && m.y >= current.minY && m.y <= current.maxY) m_cnt++;\n                    }\n                    for (const auto& s : sardines) {\n                        if (s.x >= current.minX && s.x <= current.maxX && s.y >= current.minY && s.y <= current.maxY) s_cnt++;\n                    }\n                    current.m_count = m_cnt;\n                    current.s_count = s_cnt;\n                    current.score = (long long)m_cnt - s_cnt;\n                    \n                    used[j] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (current.score > 0) {\n            final_clusters.push_back(current);\n        }\n    }\n\n    if (final_clusters.empty()) {\n        cout << 4 << \"\\n\";\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    // Try to find the best valid polygon\n    vector<Point> best_poly;\n    long long best_score = -1e18;\n\n    for (const auto& cluster : final_clusters) {\n        long long cur_minX = cluster.minX;\n        long long cur_maxX = cluster.maxX;\n        long long cur_minY = cluster.minY;\n        long long cur_maxY = cluster.maxY;\n\n        // First, try simple shrunken box\n        long long sh_minX = cur_minX, sh_maxX = cur_maxX;\n        long long sh_minY = cur_minY, sh_maxY = cur_maxY;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (const auto& s : sardines) {\n                if (s.y >= sh_minY && s.y <= sh_maxY && s.x == sh_minX) {\n                    sh_minX = s.x + 1;\n                    changed = true;\n                }\n                if (s.y >= sh_minY && s.y <= sh_maxY && s.x == sh_maxX) {\n                    sh_maxX = s.x - 1;\n                    changed = true;\n                }\n                if (s.x >= sh_minX && s.x <= sh_maxX && s.y == sh_minY) {\n                    sh_minY = s.y + 1;\n                    changed = true;\n                }\n                if (s.x >= sh_minX && s.x <= sh_maxX && s.y == sh_maxY) {\n                    sh_maxY = s.y - 1;\n                    changed = true;\n                }\n            }\n        }\n\n        if (sh_minX <= sh_maxX && sh_minY <= sh_maxY) {\n            vector<Point> box_poly;\n            box_poly.push_back({sh_minX, sh_minY});\n            box_poly.push_back({sh_maxX, sh_minY});\n            box_poly.push_back({sh_maxX, sh_maxY});\n            box_poly.push_back({sh_minX, sh_maxY});\n            \n            if (validatePolygon(box_poly)) {\n                long long sc = calculateScore(box_poly);\n                if (sc > best_score) {\n                    best_score = sc;\n                    best_poly = box_poly;\n                }\n            }\n        }\n\n        // Identify sardines on the 4 sides for notch version\n        struct SideSardine {\n            long long pos; // x for horizontal, y for vertical\n            int side; // 0: Bottom, 1: Top, 2: Left, 3: Right\n            Point p;\n        };\n        vector<SideSardine> sardines_on_sides;\n\n        for (const auto& s : sardines) {\n            // Check Bottom (y = cur_minY) - exclude corners\n            if (s.y == cur_minY && s.x > cur_minX && s.x < cur_maxX) {\n                sardines_on_sides.push_back({s.x, 0, s});\n            }\n            // Check Top (y = cur_maxY) - exclude corners\n            if (s.y == cur_maxY && s.x > cur_minX && s.x < cur_maxX) {\n                sardines_on_sides.push_back({s.x, 1, s});\n            }\n            // Check Left (x = cur_minX) - exclude corners\n            if (s.x == cur_minX && s.y > cur_minY && s.y < cur_maxY) {\n                sardines_on_sides.push_back({s.y, 2, s});\n            }\n            // Check Right (x = cur_maxX) - exclude corners\n            if (s.x == cur_maxX && s.y > cur_minY && s.y < cur_maxY) {\n                sardines_on_sides.push_back({s.y, 3, s});\n            }\n        }\n\n        // Sort by side and position\n        sort(sardines_on_sides.begin(), sardines_on_sides.end(), [](const SideSardine& a, const SideSardine& b) {\n            if (a.side != b.side) return a.side < b.side;\n            return a.pos < b.pos;\n        });\n\n        // Track used intervals\n        vector<vector<pair<long long, long long>>> used_intervals(4);\n\n        for (const auto& ss : sardines_on_sides) {\n            int side = ss.side;\n            long long pos = ss.pos;\n            \n            // Check overlap - notch interval: [pos-1, pos+1]\n            long long start = pos - 1;\n            long long end = pos + 1;\n            \n            // Ensure notch doesn't overlap with corners\n            if (side == 0 || side == 1) { // Horizontal\n                if (start <= cur_minX || end >= cur_maxX) continue;\n            } else { // Vertical\n                if (start <= cur_minY || end >= cur_maxY) continue;\n            }\n            \n            bool overlap = false;\n            for (auto& interval : used_intervals[side]) {\n                if (start < interval.second && end > interval.first) {\n                    overlap = true;\n                    break;\n                }\n            }\n            if (overlap) continue;\n\n            // Check net gain (allow removing mackerels if we remove more sardines)\n            int m_removed = 0;\n            int s_removed = 0;\n            \n            if (side == 0) { // Bottom\n                for (const auto& m : mackerels) {\n                    if (m.x >= start && m.x <= end && m.y >= cur_minY && m.y <= cur_minY + 1) {\n                        m_removed++;\n                    }\n                }\n                for (const auto& s : sardines) {\n                    if (s.x >= start && s.x <= end && s.y >= cur_minY && s.y <= cur_minY + 1) {\n                        s_removed++;\n                    }\n                }\n            } else if (side == 1) { // Top\n                for (const auto& m : mackerels) {\n                    if (m.x >= start && m.x <= end && m.y >= cur_maxY - 1 && m.y <= cur_maxY) {\n                        m_removed++;\n                    }\n                }\n                for (const auto& s : sardines) {\n                    if (s.x >= start && s.x <= end && s.y >= cur_maxY - 1 && s.y <= cur_maxY) {\n                        s_removed++;\n                    }\n                }\n            } else if (side == 2) { // Left\n                for (const auto& m : mackerels) {\n                    if (m.x >= cur_minX && m.x <= cur_minX + 1 && m.y >= start && m.y <= end) {\n                        m_removed++;\n                    }\n                }\n                for (const auto& s : sardines) {\n                    if (s.x >= cur_minX && s.x <= cur_minX + 1 && s.y >= start && s.y <= end) {\n                        s_removed++;\n                    }\n                }\n            } else { // Right\n                for (const auto& m : mackerels) {\n                    if (m.x >= cur_maxX - 1 && m.x <= cur_maxX && m.y >= start && m.y <= end) {\n                        m_removed++;\n                    }\n                }\n                for (const auto& s : sardines) {\n                    if (s.x >= cur_maxX - 1 && s.x <= cur_maxX && s.y >= start && s.y <= end) {\n                        s_removed++;\n                    }\n                }\n            }\n            \n            // Only add notch if net gain is positive\n            if (s_removed <= m_removed) continue;\n\n            // Add notch\n            used_intervals[side].push_back({start, end});\n        }\n\n        // Reconstruct polygon with notches\n        vector<Point> final_poly;\n        \n        // Start at bottom-left corner\n        final_poly.push_back({cur_minX, cur_minY});\n        \n        // Bottom edge (cur_minY) - left to right\n        long long curr_x = cur_minX;\n        for (auto& interval : used_intervals[0]) {\n            if (curr_x < interval.first) {\n                final_poly.push_back({interval.first, cur_minY});\n            }\n            final_poly.push_back({interval.first, cur_minY + 1});\n            final_poly.push_back({interval.second, cur_minY + 1});\n            final_poly.push_back({interval.second, cur_minY});\n            curr_x = interval.second;\n        }\n        if (curr_x < cur_maxX) {\n            final_poly.push_back({cur_maxX, cur_minY});\n        }\n\n        // Right edge (cur_maxX) - bottom to top\n        long long curr_y = cur_minY;\n        for (auto& interval : used_intervals[3]) {\n            if (curr_y < interval.first) {\n                final_poly.push_back({cur_maxX, interval.first});\n            }\n            final_poly.push_back({cur_maxX - 1, interval.first});\n            final_poly.push_back({cur_maxX - 1, interval.second});\n            final_poly.push_back({cur_maxX, interval.second});\n            curr_y = interval.second;\n        }\n        if (curr_y < cur_maxY) {\n            final_poly.push_back({cur_maxX, cur_maxY});\n        }\n\n        // Top edge (cur_maxY) - right to left\n        curr_x = cur_maxX;\n        for (auto& interval : used_intervals[1]) {\n            if (curr_x > interval.second) {\n                final_poly.push_back({interval.second, cur_maxY});\n            }\n            final_poly.push_back({interval.second, cur_maxY - 1});\n            final_poly.push_back({interval.first, cur_maxY - 1});\n            final_poly.push_back({interval.first, cur_maxY});\n            curr_x = interval.first;\n        }\n        if (curr_x > cur_minX) {\n            final_poly.push_back({cur_minX, cur_maxY});\n        }\n\n        // Left edge (cur_minX) - top to bottom\n        curr_y = cur_maxY;\n        for (auto& interval : used_intervals[2]) {\n            if (curr_y > interval.second) {\n                final_poly.push_back({cur_minX, interval.second});\n            }\n            final_poly.push_back({cur_minX + 1, interval.second});\n            final_poly.push_back({cur_minX + 1, interval.first});\n            final_poly.push_back({cur_minX, interval.first});\n            curr_y = interval.first;\n        }\n        if (curr_y > cur_minY) {\n            final_poly.push_back({cur_minX, cur_minY});\n        }\n\n        // Remove duplicates\n        final_poly = removeDuplicates(final_poly);\n\n        if (final_poly.size() < 4) continue;\n\n        if (!validatePolygon(final_poly)) continue;\n\n        long long sc = calculateScore(final_poly);\n        if (sc > best_score) {\n            best_score = sc;\n            best_poly = final_poly;\n        }\n    }\n\n    if (best_poly.empty()) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Placement {\n    int p, r;\n    char d;\n    int b;\n};\n\nclass Solver {\nprivate:\n    int N, T;\n    double sigma;\n    vector<pair<int, int>> wh;\n    mt19937 rng;\n    \n    pair<int, int> calculatePosition(const vector<pair<int, int>>& placed_wh, \n                                     const vector<pair<int, int>>& placed_xy,\n                                     int rw, int rh, char dir, int ref) {\n        int x = 0, y = 0;\n        \n        if (dir == 'U') {\n            x = (ref == -1) ? 0 : placed_xy[ref].first + placed_wh[ref].first;\n            y = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (x < px + pw && x + rw > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            y = (ref == -1) ? 0 : placed_xy[ref].second + placed_wh[ref].second;\n            x = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (y < py + ph && y + rh > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        return {x, y};\n    }\n    \n    vector<Placement> greedyPlacement(int seed) {\n        vector<Placement> placements;\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        mt19937 local_rng(seed);\n        \n        for (int i = 0; i < N; i++) {\n            int best_score = 2e9;\n            Placement best_p = {i, 0, 'U', -1};\n            \n            int w = wh[i].first;\n            int h = wh[i].second;\n            // Prefer rotation that keeps larger dimension horizontal\n            bool prefer_horizontal = (w >= h);\n            \n            for (int rot = 0; rot < 2; rot++) {\n                int rw = rot ? h : w;\n                int rh = rot ? w : h;\n                \n                // Small penalty for non-preferred rotation\n                int rot_penalty = (rot != prefer_horizontal) ? 500 : 0;\n                \n                for (char dir : {'U', 'L'}) {\n                    // Try limited references for efficiency\n                    int max_refs = min(i, 8);\n                    vector<int> refs_to_try;\n                    refs_to_try.push_back(-1);\n                    for (int r = i - 1; r >= max(0, i - max_refs); r--) {\n                        refs_to_try.push_back(r);\n                    }\n                    \n                    for (int ref : refs_to_try) {\n                        auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, dir, ref);\n                        \n                        int W = 0, H = 0;\n                        for (size_t j = 0; j < placed_wh.size(); j++) {\n                            W = max(W, placed_xy[j].first + placed_wh[j].first);\n                            H = max(H, placed_xy[j].second + placed_wh[j].second);\n                        }\n                        W = max(W, x + rw);\n                        H = max(H, y + rh);\n                        \n                        int score = W + H + rot_penalty;\n                        if (score < best_score) {\n                            best_score = score;\n                            best_p = {i, rot, dir, ref};\n                        }\n                    }\n                }\n            }\n            \n            placements.push_back(best_p);\n            int rw = best_p.r ? h : w;\n            int rh = best_p.r ? w : h;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, best_p.d, best_p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        return placements;\n    }\n    \n    int calculateScore(const vector<Placement>& placements) {\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        \n        for (const auto& p : placements) {\n            int rw = p.r ? wh[p.p].second : wh[p.p].first;\n            int rh = p.r ? wh[p.p].first : wh[p.p].second;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, p.d, p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        int W = 0, H = 0;\n        for (size_t i = 0; i < placed_wh.size(); i++) {\n            W = max(W, placed_xy[i].first + placed_wh[i].first);\n            H = max(H, placed_xy[i].second + placed_wh[i].second);\n        }\n        \n        return W + H;\n    }\n    \n    vector<Placement> localSearch(const vector<Placement>& placements) {\n        vector<Placement> cur = placements;\n        int best_score = calculateScore(cur);\n        \n        // Try flipping rotation for each rectangle\n        for (int i = 0; i < N; i++) {\n            cur[i].r ^= 1;\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].r ^= 1;  // Revert if not better\n            }\n        }\n        \n        // Try changing direction for some rectangles\n        for (int i = 0; i < N; i++) {\n            char orig_d = cur[i].d;\n            cur[i].d = (orig_d == 'U' ? 'L' : 'U');\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].d = orig_d;  // Revert if not better\n            }\n        }\n        \n        return cur;\n    }\n    \npublic:\n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void solve() {\n        cin >> N >> T >> sigma;\n        wh.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> wh[i].first >> wh[i].second;\n        }\n        \n        auto startTime = chrono::steady_clock::now();\n        const double MAX_TIME = 2.6;  // Conservative for system test\n        \n        for (int t = 0; t < T; t++) {\n            auto currentTime = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed > MAX_TIME) break;\n            \n            int best_score = 2e9;\n            vector<Placement> best_placements;\n            \n            // Adaptive number of strategies - more exploration early\n            int num_strategies = max(2, 6 - t / (T / 4));\n            for (int s = 0; s < num_strategies; s++) {\n                vector<Placement> placements = greedyPlacement(t * 1000 + s);\n                placements = localSearch(placements);\n                int score = calculateScore(placements);\n                if (score < best_score) {\n                    best_score = score;\n                    best_placements = placements;\n                }\n            }\n            \n            cout << best_placements.size() << \"\\n\";\n            for (const auto& p : best_placements) {\n                cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n            }\n            cout.flush();\n            \n            int W, H;\n            cin >> W >> H;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.solve();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Global buffers to avoid reallocation overhead\nconst int MAXN = 1005;\nvector<int> adj[MAXN];\nint A[MAXN];\nint L[MAXN];\nint pc[MAXN]; // parent count: number of neighbors u with L[u] == L[v] - 1\nint p[MAXN];  // output parent array\nint x[MAXN], y[MAXN];\n\nvoid solve() {\n    int N, M, H;\n    // Read until EOF\n    while (cin >> N >> M >> H) {\n        // Read Beauty values\n        for (int i = 0; i < N; ++i) {\n            cin >> A[i];\n        }\n        // Read Edges\n        for (int i = 0; i < M; ++i) {\n            int u, v;\n            cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // Read Coordinates (ignored but must be read)\n        for (int i = 0; i < N; ++i) {\n            cin >> x[i] >> y[i];\n        }\n\n        // Initialize State\n        for (int i = 0; i < N; ++i) {\n            L[i] = 0;\n            pc[i] = 0;\n        }\n\n        // Random number generator\n        static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_int_distribution<int> dist_idx(0, N - 1);\n        uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n        // Simulated Annealing\n        // Increased iterations to 20,000 to allow better exploration within 2.0s\n        // T and decay tuned for longer run\n        int iterations = 20000;\n        double T = 1000.0;\n        double decay = 0.9995;\n\n        long long current_score = 0;\n        // current_score tracks sum L[v] * A[v]\n\n        // Pre-allocate candidate array to avoid vector allocation in loop\n        int candidates[2];\n        int c_count;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            // Pick random vertex\n            int v = dist_idx(rng);\n            \n            int old_L = L[v];\n            \n            // Candidate moves\n            c_count = 0;\n            if (old_L < H) candidates[c_count++] = old_L + 1;\n            if (old_L > 0) candidates[c_count++] = old_L - 1;\n            \n            // Shuffle candidates to avoid bias\n            shuffle(candidates, candidates + c_count, rng);\n            \n            bool move_accepted = false;\n            \n            for (int k = 0; k < c_count; ++k) {\n                int new_L = candidates[k];\n                if (new_L == old_L) continue;\n                \n                // Check validity\n                bool valid = true;\n                \n                // 1. Check v's own parent requirement\n                if (new_L > 0) {\n                    bool has_parent = false;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L - 1) {\n                            has_parent = true;\n                            break;\n                        }\n                    }\n                    if (!has_parent) valid = false;\n                }\n                \n                // 2. Check neighbors' parent count requirement\n                if (valid) {\n                    for (int u : adj[v]) {\n                        if (L[u] == old_L + 1) {\n                            // v was a parent, now not\n                            if (pc[u] == 1) {\n                                valid = false;\n                                break;\n                            }\n                        }\n                    }\n                }\n                \n                if (valid) {\n                    long long delta = (long long)(new_L - old_L) * A[v];\n                    // Calculate acceptance probability\n                    double prob = 1.0;\n                    if (delta < 0) {\n                        prob = exp((double)delta / T);\n                    }\n                    \n                    if (dist_prob(rng) < prob) {\n                        // Accept move\n                        L[v] = new_L;\n                        current_score += delta;\n                        \n                        // Update pc for neighbors\n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                pc[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                pc[u]++;\n                            }\n                        }\n                        move_accepted = true;\n                        break; // Accept first valid move\n                    }\n                }\n            }\n            \n            // Cool down\n            T *= decay;\n        }\n\n        // Construct parent array\n        for (int i = 0; i < N; ++i) {\n            if (L[i] == 0) {\n                p[i] = -1;\n            } else {\n                // Find a neighbor with L[u] == L[i] - 1\n                int parent = -1;\n                for (int u : adj[i]) {\n                    if (L[u] == L[i] - 1) {\n                        parent = u;\n                        break;\n                    }\n                }\n                p[i] = parent;\n            }\n        }\n\n        // Output\n        for (int i = 0; i < N; ++i) {\n            cout << p[i] << (i == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Move {\n    char d;\n    int p;\n};\n\nstruct OniInfo {\n    int r, c;\n    int safe_dirs;\n};\n\nint N;\nvector<string> board;\nvector<Move> moves;\n\nint count_oni() {\n    int c = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\nvoid apply_move(char d, int p, int k) {\n    for (int step = 0; step < k; ++step) {\n        if (d == 'L') {\n            moves.push_back({'L', p});\n            for (int j = 0; j < N - 1; ++j) {\n                board[p][j] = board[p][j + 1];\n            }\n            board[p][N - 1] = '.';\n        } else if (d == 'R') {\n            moves.push_back({'R', p});\n            for (int j = N - 1; j > 0; --j) {\n                board[p][j] = board[p][j - 1];\n            }\n            board[p][0] = '.';\n        } else if (d == 'U') {\n            moves.push_back({'U', p});\n            for (int i = 0; i < N - 1; ++i) {\n                board[i][p] = board[i + 1][p];\n            }\n            board[N - 1][p] = '.';\n        } else if (d == 'D') {\n            moves.push_back({'D', p});\n            for (int i = N - 1; i > 0; --i) {\n                board[i][p] = board[i - 1][p];\n            }\n            board[0][p] = '.';\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n    board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> board[i];\n    }\n\n    while (count_oni() > 0) {\n        vector<OniInfo> oni_list;\n        \n        // Find all Oni and count safe directions for each\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] == 'x') {\n                    OniInfo oni;\n                    oni.r = i;\n                    oni.c = j;\n                    oni.safe_dirs = 0;\n                    \n                    // Check left\n                    bool safe_left = true;\n                    for (int jj = 0; jj < j; ++jj) {\n                        if (board[i][jj] == 'o') {\n                            safe_left = false;\n                            break;\n                        }\n                    }\n                    if (safe_left) oni.safe_dirs++;\n                    \n                    // Check right\n                    bool safe_right = true;\n                    for (int jj = j + 1; jj < N; ++jj) {\n                        if (board[i][jj] == 'o') {\n                            safe_right = false;\n                            break;\n                        }\n                    }\n                    if (safe_right) oni.safe_dirs++;\n                    \n                    // Check up\n                    bool safe_up = true;\n                    for (int ii = 0; ii < i; ++ii) {\n                        if (board[ii][j] == 'o') {\n                            safe_up = false;\n                            break;\n                        }\n                    }\n                    if (safe_up) oni.safe_dirs++;\n                    \n                    // Check down\n                    bool safe_down = true;\n                    for (int ii = i + 1; ii < N; ++ii) {\n                        if (board[ii][j] == 'o') {\n                            safe_down = false;\n                            break;\n                        }\n                    }\n                    if (safe_down) oni.safe_dirs++;\n                    \n                    oni_list.push_back(oni);\n                }\n            }\n        }\n\n        // Sort Oni by safe_dirs (ascending) - most constrained first\n        sort(oni_list.begin(), oni_list.end(), [](const OniInfo& a, const OniInfo& b) {\n            return a.safe_dirs < b.safe_dirs;\n        });\n\n        // Try to remove the most constrained Oni first\n        bool found = false;\n        for (const auto& oni : oni_list) {\n            int r = oni.r;\n            int c = oni.c;\n            \n            // Try each direction, prioritizing by number of Oni removed\n            int best_oni_removed = 0;\n            char best_d = 0;\n            int best_p = -1;\n            int best_k = 0;\n            \n            // Left\n            bool safe_left = true;\n            for (int jj = 0; jj < c; ++jj) {\n                if (board[r][jj] == 'o') {\n                    safe_left = false;\n                    break;\n                }\n            }\n            if (safe_left) {\n                int k = c + 1;\n                int oni_removed = 0;\n                for (int jj = 0; jj < k; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'L';\n                    best_p = r;\n                    best_k = k;\n                }\n            }\n            \n            // Right\n            bool safe_right = true;\n            for (int jj = c + 1; jj < N; ++jj) {\n                if (board[r][jj] == 'o') {\n                    safe_right = false;\n                    break;\n                }\n            }\n            if (safe_right) {\n                int k = N - c;\n                int oni_removed = 0;\n                for (int jj = N - k; jj < N; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'R';\n                    best_p = r;\n                    best_k = k;\n                }\n            }\n            \n            // Up\n            bool safe_up = true;\n            for (int ii = 0; ii < r; ++ii) {\n                if (board[ii][c] == 'o') {\n                    safe_up = false;\n                    break;\n                }\n            }\n            if (safe_up) {\n                int k = r + 1;\n                int oni_removed = 0;\n                for (int ii = 0; ii < k; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'U';\n                    best_p = c;\n                    best_k = k;\n                }\n            }\n            \n            // Down\n            bool safe_down = true;\n            for (int ii = r + 1; ii < N; ++ii) {\n                if (board[ii][c] == 'o') {\n                    safe_down = false;\n                    break;\n                }\n            }\n            if (safe_down) {\n                int k = N - r;\n                int oni_removed = 0;\n                for (int ii = N - k; ii < N; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'D';\n                    best_p = c;\n                    best_k = k;\n                }\n            }\n            \n            if (best_p != -1) {\n                apply_move(best_d, best_p, best_k);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) break;\n    }\n\n    for (const auto& m : moves) {\n        cout << m.d << \" \" << m.p << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nint N, L;\nint T[105];\nint A[105], B[105];\nint current_cnt[105];\n\n// Fast simulation\ninline long long evaluate() {\n    memset(current_cnt, 0, sizeof(current_cnt));\n    int cur = 0;\n    for(int w = 0; w < L; ++w) {\n        current_cnt[cur]++;\n        if (current_cnt[cur] & 1) cur = A[cur];\n        else cur = B[cur];\n    }\n    long long err = 0;\n    for(int i = 0; i < N; ++i) {\n        err += abs(current_cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    for(int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_node(0, N - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Flow-based initialization (from first successful attempt)\n    // Distribute 2*N edges such that in-degree of i is proportional to T[i]\n    vector<int> targets;\n    targets.reserve(2 * N);\n    vector<int> base_counts(N, 0);\n    long long distributed = 0;\n    for(int i = 0; i < N; ++i) {\n        long long k = (2LL * N * T[i]) / L;\n        base_counts[i] = k;\n        distributed += k;\n    }\n    long long remainder = 2 * N - distributed;\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    // Sort indices by T[i] descending to distribute remainder\n    sort(p.begin(), p.end(), [&](int i, int j){\n        return T[i] > T[j];\n    });\n    for(int i = 0; i < remainder && i < N; ++i) {\n        base_counts[p[i]]++;\n    }\n    for(int i = 0; i < N; ++i) {\n        for(int k = 0; k < base_counts[i]; ++k) {\n            targets.push_back(i);\n        }\n    }\n    // Shuffle to avoid deterministic structure\n    shuffle(targets.begin(), targets.end(), rng);\n    // Assign A and B\n    for(int i = 0; i < N; ++i) {\n        A[i] = targets[2 * i];\n        B[i] = targets[2 * i + 1];\n    }\n\n    // Initial evaluation\n    long long current_err = evaluate();\n    long long best_err = current_err;\n    vector<int> best_A(N), best_B(N);\n    for(int i = 0; i < N; ++i) {\n        best_A[i] = A[i];\n        best_B[i] = B[i];\n    }\n\n    // Simulated Annealing parameters (from first successful attempt)\n    double temp = 1e7;\n    double cooling = 0.999;\n    \n    // Time limit handling (use more time)\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1) + chrono::milliseconds(950);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Save current counts for potential revert\n        vector<int> saved_cnt(N);\n        for(int i = 0; i < N; ++i) saved_cnt[i] = current_cnt[i];\n        \n        // Pick node u to modify (biased by error)\n        int u = dist_node(rng);\n        long long total_err = 0;\n        for(int i = 0; i < N; ++i) total_err += abs(current_cnt[i] - T[i]);\n        if (total_err > 0) {\n            long long r = rng() % total_err;\n            long long sum = 0;\n            for(int i = 0; i < N; ++i) {\n                long long w = abs(current_cnt[i] - T[i]);\n                sum += w;\n                if (sum > r) {\n                    u = i;\n                    break;\n                }\n            }\n        }\n\n        // Pick target node v (biased by need)\n        int v = dist_node(rng);\n        long long total_need = 0;\n        for(int i = 0; i < N; ++i) {\n            if (T[i] > current_cnt[i]) total_need += (T[i] - current_cnt[i]);\n        }\n        if (total_need > 0) {\n            long long r = rng() % total_need;\n            long long sum = 0;\n            for(int i = 0; i < N; ++i) {\n                long long w = max(0, T[i] - current_cnt[i]);\n                sum += w;\n                if (sum > r) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n\n        // Propose change: modify A[u] or B[u]\n        int edge_type = dist_node(rng) % 2;\n        int old_target = (edge_type == 0) ? A[u] : B[u];\n        \n        if (edge_type == 0) A[u] = v;\n        else B[u] = v;\n\n        // Evaluate new state\n        long long new_err = evaluate();\n        \n        // Acceptance probability\n        double delta = new_err - current_err;\n        double prob = exp(-delta / temp);\n        \n        if (delta < 0 || dist_prob(rng) < prob) {\n            current_err = new_err;\n            if (current_err < best_err) {\n                best_err = current_err;\n                for(int i = 0; i < N; ++i) {\n                    best_A[i] = A[i];\n                    best_B[i] = B[i];\n                }\n            }\n        } else {\n            // Revert change\n            if (edge_type == 0) A[u] = old_target;\n            else B[u] = old_target;\n            // Restore counts\n            for(int i = 0; i < N; ++i) current_cnt[i] = saved_cnt[i];\n        }\n        \n        // Cool down\n        temp *= cooling;\n        if (temp < 1e-3) temp = 1e-3;\n    }\n\n    // Output best solution\n    for(int i = 0; i < N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    double cx, cy;\n};\n\nstruct Edge {\n    int u, v;\n    int dist;\n    bool queried;\n    bool operator<(const Edge& other) const {\n        if (dist != other.dist) return dist < other.dist;\n        if (queried != other.queried) return queried > other.queried;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\nclass DSU {\npublic:\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) {\n            parent[rootX] = rootY;\n            return true;\n        }\n        return false;\n    }\n};\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<City> cities;\nvector<vector<int>> groups;\nint query_cnt = 0;\nvector<vector<int>> dist_cache;\nvector<vector<bool>> edge_queried;\n\nint calc_dist(int i, int j) {\n    double dx = cities[i].cx - cities[j].cx;\n    double dy = cities[i].cy - cities[j].cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\nint get_dist(int i, int j) {\n    if (i > j) swap(i, j);\n    return dist_cache[i][j];\n}\n\nvoid perform_query(const vector<int>& subset) {\n    if (query_cnt >= Q) return;\n    cout << \"? \" << subset.size();\n    for (int id : subset) {\n        cout << \" \" << id;\n    }\n    cout << endl;\n    query_cnt++;\n}\n\nvector<pair<int, int>> read_query_response(int size) {\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < size - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.push_back({u, v});\n        dist_cache[u][v] = 0;\n        edge_queried[u][v] = true;\n    }\n    return edges;\n}\n\nvector<pair<int, int>> build_mst(const vector<int>& group) {\n    vector<Edge> all_edges;\n    int sz = (int)group.size();\n    \n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            bool queried = edge_queried[u][v];\n            all_edges.push_back({u, v, d, queried});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n\n    DSU dsu(sz);\n    vector<pair<int, int>> mst_edges;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        if (u_idx != -1 && v_idx != -1) {\n            if (dsu.unite(u_idx, v_idx)) {\n                mst_edges.push_back({e.u, e.v});\n                if ((int)mst_edges.size() == sz - 1) break;\n            }\n        }\n    }\n    return mst_edges;\n}\n\nint calc_estimated_cost(const vector<int>& group) {\n    int sz = (int)group.size();\n    if (sz <= 1) return 0;\n    \n    vector<Edge> all_edges;\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            all_edges.push_back({u, v, d, false});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n    \n    DSU dsu(sz);\n    int cost = 0;\n    int edges_count = 0;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        \n        if (u_idx != -1 && v_idx != -1 && dsu.unite(u_idx, v_idx)) {\n            cost += e.dist;\n            edges_count++;\n        }\n    }\n    return cost;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2.0;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2.0;\n    }\n\n    // Pre-calculate all distances\n    dist_cache.assign(N, vector<int>(N, 0));\n    edge_queried.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            dist_cache[i][j] = calc_dist(i, j);\n        }\n    }\n\n    // Sort cities by X then Y\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (cities[a].cx != cities[b].cx) return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n\n    // Assign cities to groups\n    groups.resize(M);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(p[current_idx++]);\n        }\n    }\n\n    // Simple local search - swap boundary cities (very limited iterations)\n    auto start_time = chrono::high_resolution_clock::now();\n    auto time_limit = chrono::high_resolution_clock::now() + chrono::milliseconds(800);\n\n    for (int iter = 0; iter < 3; ++iter) {\n        if (chrono::high_resolution_clock::now() > time_limit) break;\n        bool improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            if (groups[i].empty() || groups[i+1].empty()) continue;\n            \n            int cost_before = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            swap(groups[i].back(), groups[i+1].front());\n            \n            int cost_after = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            if (cost_after < cost_before) {\n                improved = true;\n            } else {\n                swap(groups[i].back(), groups[i+1].front());\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Query Phase\n    vector<vector<pair<int, int>>> group_queried_edges(M);\n\n    // Query small groups first (3 <= size <= L)\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] >= 3 && G[i] <= L) {\n            perform_query(groups[i]);\n            group_queried_edges[i] = read_query_response(G[i]);\n        }\n    }\n\n    // Query large groups\n    for (int i = 0; i < M; ++i) {\n        if (query_cnt >= Q) break;\n        if (G[i] > L) {\n            int step = max(2, L / 2);\n            for (int start = 0; start < G[i]; start += step) {\n                if (query_cnt >= Q) break;\n                int end = min(start + L, G[i]);\n                if (end - start < 2) continue;\n                \n                vector<int> subset;\n                for (int k = start; k < end; ++k) {\n                    subset.push_back(groups[i][k]);\n                }\n                \n                perform_query(subset);\n                vector<pair<int, int>> sub_edges = read_query_response(end - start);\n                \n                for (auto& e : sub_edges) {\n                    group_queried_edges[i].push_back(e);\n                }\n            }\n        }\n    }\n\n    // Final Output\n    cout << \"!\" << endl;\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            cout << groups[i][j] << (j == G[i] - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n\n        if (G[i] <= 1) continue;\n\n        vector<pair<int, int>> final_edges = build_mst(groups[i]);\n        \n        for (const auto& e : final_edges) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\n// Directions: U, D, L, R\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dirChar[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nclass SkatingSolver {\nprivate:\n    int n;\n    vector<Point> targets;\n    Point currentPos;\n    vector<vector<bool>> blocks;\n    vector<pair<char, char>> actions;\n    int actionCount = 0;\n    \n    bool isValid(int x, int y) const {\n        return x >= 0 && x < n && y >= 0 && y < n;\n    }\n    \n    bool hasBlock(int x, int y) const {\n        return isValid(x, y) && blocks[x][y];\n    }\n    \n    // Check if we can slide from currentPos in direction d and reach target\n    bool canSlideToPoint(Point target, int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny)) return false;\n            if (nx == target.x && ny == target.y) return true;\n            if (hasBlock(nx, ny)) return false;\n            \n            x = nx;\n            y = ny;\n        }\n    }\n    \n    // Find where we would stop if we slide in direction d\n    Point slideDestination(int d) const {\n        int x = currentPos.x;\n        int y = currentPos.y;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                break;\n            }\n            x = nx;\n            y = ny;\n        }\n        \n        return {x, y};\n    }\n    \n    // Safe action execution with validation\n    bool executeAction(char action, char dir) {\n        if (actionCount >= 2 * N * M) return false;\n        \n        int d = 0;\n        if (dir == 'U') d = 0;\n        else if (dir == 'D') d = 1;\n        else if (dir == 'L') d = 2;\n        else if (dir == 'R') d = 3;\n        \n        if (action == 'M') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                return false;  // Invalid move\n            }\n            currentPos = {nx, ny};\n        } else if (action == 'S') {\n            Point dest = slideDestination(d);\n            if (dest == currentPos) {\n                return false;  // No movement possible\n            }\n            currentPos = dest;\n        } else if (action == 'A') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny)) {\n                return false;  // Can't alter outside grid\n            }\n            blocks[nx][ny] = !blocks[nx][ny];\n        }\n        \n        actions.push_back({action, dir});\n        actionCount++;\n        return true;\n    }\n    \n    // BFS to find path using Move actions\n    vector<pair<char, char>> bfsPath(Point target) {\n        vector<pair<char, char>> path;\n        \n        using State = tuple<int, int, int>;\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<int>> parentDir(n, vector<int>(n, -1));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                // Reconstruct path\n                int cx = x, cy = y;\n                vector<int> dirs;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    dirs.push_back(parentDir[cx][cy]);\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                // Execute moves in correct order\n                for (int i = dirs.size() - 1; i >= 0; i--) {\n                    executeAction('M', dirChar[dirs[i]]);\n                }\n                \n                return path;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parentDir[nx][ny] = dir;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return path;\n    }\n    \n    // Try to reach target using sliding with block placement\n    bool trySlideToTarget(Point target) {\n        for (int d = 0; d < 4; d++) {\n            if (canSlideToPoint(target, d)) {\n                // Check if we need to place a block after target\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                // If there's already a block or we're at boundary, we can slide directly\n                if (!isValid(stopX, stopY) || hasBlock(stopX, stopY)) {\n                    executeAction('S', dirChar[d]);\n                    return true;\n                }\n                \n                // Need to place block after target to stop the slide\n                executeAction('A', dirChar[d]);\n                executeAction('S', dirChar[d]);\n                executeAction('A', dirChar[d]);  // Remove block\n                \n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // Find optimal path to target\n    void findPathToTarget(Point target) {\n        // First try sliding (most efficient)\n        if (trySlideToTarget(target)) {\n            return;\n        }\n        \n        // Fall back to BFS with Move actions\n        bfsPath(target);\n    }\n\npublic:\n    SkatingSolver(int n) : n(n) {\n        blocks.assign(n, vector<bool>(n, false));\n    }\n    \n    void setInitialPosition(int x, int y) {\n        currentPos = {x, y};\n    }\n    \n    void addTarget(int x, int y) {\n        targets.push_back({x, y});\n    }\n    \n    void solve() {\n        for (const auto& target : targets) {\n            if (actionCount >= 2 * N * M) break;\n            \n            findPathToTarget(target);\n        }\n    }\n    \n    void output() const {\n        for (const auto& action : actions) {\n            cout << action.first << \" \" << action.second << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    SkatingSolver solver(n);\n    \n    int x, y;\n    cin >> x >> y;\n    solver.setInitialPosition(x, y);\n    \n    for (int i = 0; i < m; i++) {\n        cin >> x >> y;\n        solver.addTarget(x, y);\n    }\n    \n    solver.solve();\n    solver.output();\n    \n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int a, b, c, d;\n};\n\ndouble calculate_p(int r, int s) {\n    if (s <= 0) return 0.0;\n    double ratio = (double)min(r, s) / max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble calculate_total_p(const vector<Company>& companies) {\n    double total = 0;\n    for (auto& c : companies) {\n        int s = (c.c - c.a) * (c.d - c.b);\n        if (s <= 0) continue;\n        total += calculate_p(c.r, s);\n    }\n    return total;\n}\n\nbool rectangles_overlap(int a1, int b1, int c1, int d1, int a2, int b2, int c2, int d2) {\n    bool x_separated = (c1 <= a2) || (c2 <= a1);\n    bool y_separated = (d1 <= b2) || (d2 <= b1);\n    return !(x_separated || y_separated);\n}\n\nbool can_place(const vector<Rect>& placed, int a, int b, int c, int d) {\n    for (const auto& r : placed) {\n        if (rectangles_overlap(a, b, c, d, r.a, r.b, r.c, r.d)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nbool has_overlap(const vector<Company>& companies) {\n    for (int i = 0; i < (int)companies.size(); i++) {\n        for (int j = i + 1; j < (int)companies.size(); j++) {\n            if (companies[i].a == 0 && companies[i].b == 0 && companies[i].c == 0 && companies[i].d == 0) continue;\n            if (companies[j].a == 0 && companies[j].b == 0 && companies[j].c == 0 && companies[j].d == 0) continue;\n            if (rectangles_overlap(companies[i].a, companies[i].b, companies[i].c, companies[i].d,\n                                   companies[j].a, companies[j].b, companies[j].c, companies[j].d)) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nvoid place_rectangles(vector<Company>& companies, const vector<int>& order, int n) {\n    vector<Rect> placed;\n    placed.reserve(n);\n    \n    for (int idx : order) {\n        int x = companies[idx].x;\n        int y = companies[idx].y;\n        int r = companies[idx].r;\n        \n        bool placed_rect = false;\n        \n        // Try key area values\n        vector<int> areas_to_try;\n        areas_to_try.push_back(r);\n        \n        for (int d = 2; d * d <= r && (int)areas_to_try.size() < 5; d++) {\n            if (r % d == 0) {\n                areas_to_try.push_back(r / d);\n                if (d != r / d && (int)areas_to_try.size() < 5) {\n                    areas_to_try.push_back(d);\n                }\n            }\n        }\n        \n        if ((int)areas_to_try.size() < 5) areas_to_try.push_back(max(1, r / 2));\n        if ((int)areas_to_try.size() < 5) areas_to_try.push_back(max(1, r / 4));\n        if ((int)areas_to_try.size() < 5) areas_to_try.push_back(max(1, r / 8));\n        areas_to_try.push_back(1);\n        \n        sort(areas_to_try.begin(), areas_to_try.end(), greater<int>());\n        \n        for (int area : areas_to_try) {\n            if (placed_rect) break;\n            \n            vector<pair<int, int>> dims;\n            for (int w = 1; w * w <= area; w++) {\n                if (area % w == 0) {\n                    int h = area / w;\n                    dims.push_back({w, h});\n                    if (w * w != area) {\n                        dims.push_back({h, w});\n                    }\n                }\n            }\n            \n            sort(dims.begin(), dims.end(), [](auto& p1, auto& p2) {\n                return abs(p1.first - p1.second) < abs(p2.first - p2.second);\n            });\n            \n            if (dims.size() > 10) dims.resize(10);\n            \n            for (auto [w, h] : dims) {\n                if (placed_rect) break;\n                \n                int min_a = max(0, x - w + 1);\n                int max_a = min(x, 10000 - w);\n                int min_b = max(0, y - h + 1);\n                int max_b = min(y, 10000 - h);\n                \n                if (min_a > max_a || min_b > max_b) continue;\n                \n                vector<pair<int, int>> positions;\n                positions.push_back({min_a, min_b});\n                positions.push_back({max_a, min_b});\n                positions.push_back({min_a, max_b});\n                positions.push_back({max_a, max_b});\n                positions.push_back({(min_a + max_a) / 2, (min_b + max_b) / 2});\n                \n                if (max_a > min_a) {\n                    positions.push_back({min_a + (max_a - min_a) / 3, (min_b + max_b) / 2});\n                    positions.push_back({max_a - (max_a - min_a) / 3, (min_b + max_b) / 2});\n                }\n                if (max_b > min_b) {\n                    positions.push_back({(min_a + max_a) / 2, min_b + (max_b - min_b) / 3});\n                    positions.push_back({(min_a + max_a) / 2, max_b - (max_b - min_b) / 3});\n                }\n                \n                for (auto [a, b] : positions) {\n                    int c = a + w;\n                    int d = b + h;\n                    \n                    if (a < 0 || c > 10000 || b < 0 || d > 10000) continue;\n                    if (!(a <= x && x < c && b <= y && y < d)) continue;\n                    \n                    if (can_place(placed, a, b, c, d)) {\n                        companies[idx].a = a;\n                        companies[idx].b = b;\n                        companies[idx].c = c;\n                        companies[idx].d = d;\n                        placed.push_back({a, b, c, d});\n                        placed_rect = true;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        // Fallback: try small areas with ALL positions (no stepping)\n        if (!placed_rect) {\n            for (int area = 1; area <= 25 && !placed_rect; area++) {\n                vector<pair<int, int>> dims;\n                for (int w = 1; w * w <= area; w++) {\n                    if (area % w == 0) {\n                        int h = area / w;\n                        dims.push_back({w, h});\n                        if (w * w != area) {\n                            dims.push_back({h, w});\n                        }\n                    }\n                }\n                \n                for (auto [w, h] : dims) {\n                    if (placed_rect) break;\n                    \n                    int min_a = max(0, x - w + 1);\n                    int max_a = min(x, 10000 - w);\n                    int min_b = max(0, y - h + 1);\n                    int max_b = min(y, 10000 - h);\n                    \n                    if (min_a > max_a || min_b > max_b) continue;\n                    \n                    // Try ALL positions (limit to avoid TLE)\n                    int max_positions = 500;\n                    int pos_count = 0;\n                    \n                    for (int a = min_a; a <= max_a && !placed_rect && pos_count < max_positions; a++) {\n                        for (int b = min_b; b <= max_b && !placed_rect && pos_count < max_positions; b++) {\n                            pos_count++;\n                            int c = a + w;\n                            int d = b + h;\n                            \n                            if (a < 0 || c > 10000 || b < 0 || d > 10000) continue;\n                            if (!(a <= x && x < c && b <= y && y < d)) continue;\n                            \n                            if (can_place(placed, a, b, c, d)) {\n                                companies[idx].a = a;\n                                companies[idx].b = b;\n                                companies[idx].c = c;\n                                companies[idx].d = d;\n                                placed.push_back({a, b, c, d});\n                                placed_rect = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Absolute last resort - ensure positive area\n        if (!placed_rect) {\n            int a = min(x, 9999);\n            int b = min(y, 9999);\n            int c = a + 1;\n            int d = b + 1;\n            \n            if (a > x) a = x;\n            if (b > y) b = y;\n            if (c <= x) c = x + 1;\n            if (d <= y) d = y + 1;\n            \n            a = max(0, a);\n            b = max(0, b);\n            c = min(10000, c);\n            d = min(10000, d);\n            \n            if (a >= c) { c = a + 1; if (c > 10000) { c = 10000; a = 9999; } }\n            if (b >= d) { d = b + 1; if (d > 10000) { d = 10000; b = 9999; } }\n            \n            companies[idx].a = a;\n            companies[idx].b = b;\n            companies[idx].c = c;\n            companies[idx].d = d;\n            // This might overlap - we'll detect and handle later\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        companies[i].a = 0;\n        companies[i].b = 0;\n        companies[i].c = 0;\n        companies[i].d = 0;\n    }\n    \n    vector<Company> best_companies = companies;\n    double best_p = -1;\n    bool best_valid = false;\n    \n    // Strategy 1: Sort by r (largest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r > current[j].r;\n        });\n        place_rectangles(current, order, n);\n        bool valid = !has_overlap(current);\n        double p = calculate_total_p(current);\n        if (valid && p > best_p) {\n            best_p = p;\n            best_companies = current;\n            best_valid = true;\n        }\n    }\n    \n    // Strategy 2: Sort by position (x then y)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (current[i].x != current[j].x) return current[i].x < current[j].x;\n            return current[i].y < current[j].y;\n        });\n        place_rectangles(current, order, n);\n        bool valid = !has_overlap(current);\n        double p = calculate_total_p(current);\n        if (valid && p > best_p) {\n            best_p = p;\n            best_companies = current;\n            best_valid = true;\n        }\n    }\n    \n    // Strategy 3: Random order\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 10; trial++) {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        place_rectangles(current, order, n);\n        bool valid = !has_overlap(current);\n        double p = calculate_total_p(current);\n        if (valid && p > best_p) {\n            best_p = p;\n            best_companies = current;\n            best_valid = true;\n        }\n    }\n    \n    // Strategy 4: Sort by r (smallest first)\n    {\n        vector<Company> current = companies;\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return current[i].r < current[j].r;\n        });\n        place_rectangles(current, order, n);\n        bool valid = !has_overlap(current);\n        double p = calculate_total_p(current);\n        if (valid && p > best_p) {\n            best_p = p;\n            best_companies = current;\n            best_valid = true;\n        }\n    }\n    \n    // If no valid solution found, use the best one anyway (might have some overlaps)\n    if (!best_valid) {\n        best_companies = companies;\n        for (int i = 0; i < n; i++) {\n            if (best_companies[i].a == 0 && best_companies[i].b == 0 && \n                best_companies[i].c == 0 && best_companies[i].d == 0) {\n                best_companies[i].a = min(companies[i].x, 9999);\n                best_companies[i].b = min(companies[i].y, 9999);\n                best_companies[i].c = best_companies[i].a + 1;\n                best_companies[i].d = best_companies[i].b + 1;\n            }\n        }\n    }\n    \n    // Output best solution\n    for (int i = 0; i < n; i++) {\n        cout << best_companies[i].a << \" \" << best_companies[i].b << \" \" \n             << best_companies[i].c << \" \" << best_companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Global problem data\nint si, sj;\nint t[50][50];\nint p[50][50];\nint adj[50][50][4];\nint adj_count[50][50];\nchar move_char[4] = {'U', 'D', 'L', 'R'};\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\n// Global path state\nint path_r[2505];\nint path_c[2505];\nchar path_moves[2505];\nbool visited_tile[2505];\nint path_len;\nlong long current_score;\n\n// Tabu list\nint tabu_count[2505];\n\n// Best path\nlong long best_score;\nstring best_moves;\n\n// Region tracking (5x5 grid)\nbool region_visited[10][10];\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < 50 && c >= 0 && c < 50;\n}\n\nvoid precompute_adj() {\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            adj_count[i][j] = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (is_valid(ni, nj)) {\n                    adj[i][j][adj_count[i][j]++] = k;\n                }\n            }\n        }\n    }\n}\n\nvoid save_best() {\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_moves.clear();\n        best_moves.reserve(path_len - 1);\n        for (int i = 0; i < path_len - 1; ++i) {\n            best_moves += path_moves[i];\n        }\n    }\n}\n\nvoid reset_state() {\n    memset(visited_tile, 0, sizeof(visited_tile));\n    memset(tabu_count, 0, sizeof(tabu_count));\n    memset(region_visited, 0, sizeof(region_visited));\n    path_len = 0;\n    current_score = 0;\n}\n\nvoid mark_region(int r, int c) {\n    region_visited[r / 5][c / 5] = true;\n}\n\n// Count available neighbors (not tabu)\nint count_available_neighbors(int r, int c) {\n    int count = 0;\n    for (int k = 0; k < adj_count[r][c]; ++k) {\n        int dir = adj[r][c][k];\n        int nr = r + di[dir];\n        int nc = c + dj[dir];\n        int tile = t[nr][nc];\n        if (!visited_tile[tile] && tabu_count[tile] == 0) {\n            count++;\n        }\n    }\n    return count;\n}\n\n// Simple lookahead - count reachable tiles in 2 steps\nint simple_lookahead(int r, int c) {\n    int total = 0;\n    for (int k = 0; k < adj_count[r][c]; ++k) {\n        int dir = adj[r][c][k];\n        int nr = r + di[dir];\n        int nc = c + dj[dir];\n        int tile = t[nr][nc];\n        if (!visited_tile[tile] && tabu_count[tile] == 0) {\n            total += p[nr][nc];\n            // Count next level\n            for (int m = 0; m < adj_count[nr][nc]; ++m) {\n                int ndir = adj[nr][nc][m];\n                int nnr = nr + di[ndir];\n                int nnc = nc + dj[ndir];\n                int ntile = t[nnr][nnc];\n                if (!visited_tile[ntile] && ntile != tile && tabu_count[ntile] == 0) {\n                    total += p[nnr][nnc] * 0.5;\n                }\n            }\n        }\n    }\n    return total;\n}\n\nint move_score(int nr, int nc, int tile, int phase) {\n    int score = p[nr][nc];\n    \n    // Connectivity bonus - critical for avoiding dead ends\n    int neighbors = count_available_neighbors(nr, nc);\n    if (neighbors >= 3) score += 40;\n    else if (neighbors >= 2) score += 25;\n    else if (neighbors == 1) score += 12;\n    else score -= 350; // Heavy penalty for dead ends\n    \n    // Tabu penalty\n    if (tabu_count[tile] > 0) score -= 40;\n    \n    // Distance from start bonus (encourage exploration)\n    int dist = abs(nr - si) + abs(nc - sj);\n    if (dist > 18) score += 18;\n    if (dist > 28) score += 18;\n    \n    // Region exploration bonus (early phase)\n    if (phase < 100) {\n        if (!region_visited[nr / 5][nc / 5]) {\n            score += 35;\n        }\n    }\n    \n    // Lookahead bonus\n    if (phase < 150) {\n        int lookahead = simple_lookahead(nr, nc);\n        score += lookahead / 10;\n    }\n    \n    // Phase-based adjustment - prioritize high-value tiles later\n    if (phase > 180) {\n        score += p[nr][nc];\n    }\n    \n    return score;\n}\n\nvoid run_single_path(mt19937& rng, uniform_real_distribution<double>& prob_dist, uniform_real_distribution<double>& prob_dist2, int mode) {\n    reset_state();\n\n    // Start from initial position\n    path_r[0] = si;\n    path_c[0] = sj;\n    visited_tile[t[si][sj]] = true;\n    mark_region(si, sj);\n    path_len = 1;\n    current_score = p[si][sj];\n\n    save_best();\n\n    int stuck_steps = 0;\n    int backtrack_count = 0;\n    int no_improve_count = 0;\n    int last_best_len = path_len;\n    int last_best_score = current_score;\n    \n    // SA temperature - balanced\n    double temp = (mode == 0) ? 150.0 : 80.0;\n    int tabu_duration = (mode == 0) ? 35 : 50;\n\n    while (path_len > 0 && stuck_steps < 280) {\n        int r = path_r[path_len - 1];\n        int c = path_c[path_len - 1];\n        \n        // Decay tabu\n        for (int i = 0; i < 2500; ++i) {\n            if (tabu_count[i] > 0) tabu_count[i]--;\n        }\n        \n        // Find valid neighbors with scores\n        struct Candidate {\n            int dir;\n            int nr, nc;\n            int tile;\n            int score;\n        };\n        \n        vector<Candidate> candidates;\n        for (int k = 0; k < adj_count[r][c]; ++k) {\n            int dir = adj[r][c][k];\n            int nr = r + di[dir];\n            int nc = c + dj[dir];\n            int tile = t[nr][nc];\n            \n            if (!visited_tile[tile]) {\n                Candidate cand;\n                cand.dir = dir;\n                cand.nr = nr;\n                cand.nc = nc;\n                cand.tile = tile;\n                cand.score = move_score(nr, nc, tile, path_len);\n                candidates.push_back(cand);\n            }\n        }\n\n        if (!candidates.empty()) {\n            // Sort by score\n            sort(candidates.begin(), candidates.end(), \n                [](const Candidate& a, const Candidate& b) {\n                    return a.score > b.score;\n                });\n\n            // Adaptive exploration rate - balanced\n            double exploration_rate = 0.10 + (stuck_steps * 0.005);\n            exploration_rate = min(mode == 0 ? 0.75 : 0.65, exploration_rate);\n            \n            int chosen_idx = 0;\n            if (candidates.size() > 1 && prob_dist(rng) < exploration_rate) {\n                // SA-based weighted selection\n                double total_weight = 0;\n                vector<double> weights;\n                for (size_t i = 0; i < candidates.size(); ++i) {\n                    double weight = max(1.0, (double)(candidates[i].score + 200));\n                    weight = exp(weight / temp);\n                    total_weight += weight;\n                    weights.push_back(total_weight);\n                }\n                \n                double r_val = prob_dist2(rng) * total_weight;\n                for (size_t i = 0; i < weights.size(); ++i) {\n                    if (r_val <= weights[i]) {\n                        chosen_idx = i;\n                        break;\n                    }\n                }\n            }\n\n            // Extend path\n            Candidate& chosen = candidates[chosen_idx];\n            path_r[path_len] = chosen.nr;\n            path_c[path_len] = chosen.nc;\n            path_moves[path_len - 1] = move_char[chosen.dir];\n            visited_tile[chosen.tile] = true;\n            tabu_count[chosen.tile] = tabu_duration;\n            mark_region(chosen.nr, chosen.nc);\n            path_len++;\n            current_score += p[chosen.nr][chosen.nc];\n            \n            stuck_steps = 0;\n            \n            // Track improvement\n            if (path_len > last_best_len || current_score > last_best_score) {\n                last_best_len = path_len;\n                last_best_score = current_score;\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n            }\n            \n            save_best();\n            \n            // Adaptive temperature cooling\n            if (no_improve_count > 100) {\n                temp *= 0.90;\n            } else if (no_improve_count > 50) {\n                temp *= 0.96;\n            } else {\n                temp *= 0.995;\n            }\n            if (temp < 0.5) temp = 0.5;\n        } else {\n            // No valid moves - backtrack\n            stuck_steps++;\n            no_improve_count++;\n            \n            if (path_len <= 1) break;\n            \n            // Conservative backtracking - 1-2 steps\n            int backtrack_depth = min(2, stuck_steps / 30);\n            if (backtrack_depth < 1) backtrack_depth = 1;\n            \n            for (int bd = 0; bd < backtrack_depth && path_len > 1; bd++) {\n                int last_r = path_r[path_len - 1];\n                int last_c = path_c[path_len - 1];\n                int last_tile = t[last_r][last_c];\n                \n                path_len--;\n                current_score -= p[last_r][last_c];\n                visited_tile[last_tile] = false;\n                \n                backtrack_count++;\n            }\n            \n            // Restart threshold\n            if (backtrack_count > 100 || no_improve_count > 250) {\n                break;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> t[i][j];\n        }\n    }\n\n    for (int i = 0; i < 50; ++i) {\n        for (int j = 0; j < 50; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    precompute_adj();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_real_distribution<double> prob_dist2(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1995);\n\n    best_score = -1;\n    best_moves.clear();\n\n    // Multiple restarts with two modes\n    int restart = 0;\n    int mode = 0;\n    while (chrono::steady_clock::now() < end_time && restart < 5000) {\n        restart++;\n        // Alternate between exploration and exploitation modes\n        mode = (restart % 2 == 0) ? 1 : 0;\n        run_single_path(rng, prob_dist, prob_dist2, mode);\n    }\n\n    cout << best_moves << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nconst int N = 30;\nconst double INIT_W = 5000.0;\n\nstruct Stats {\n    double log_sum = 0.0;\n    int cnt = 0;\n};\n\nStats h_stats[N][N];\nStats v_stats[N][N];\nStats h_avg_stats[N];\nStats v_avg_stats[N];\n\ndouble get_weight(const Stats& s) {\n    if (s.cnt == 0) return INIT_W;\n    return INIT_W * exp(s.log_sum / s.cnt);\n}\n\ndouble get_h_weight(int i, int j) {\n    double w_edge = get_weight(h_stats[i][j]);\n    double w_avg = get_weight(h_avg_stats[i]);\n    int edge_cnt = h_stats[i][j].cnt;\n    \n    // Adaptive K: more samples on edge -> less reliance on average\n    // K starts at 10 and decreases as edge gets more samples\n    // Decay factor 0.06 - very conservative\n    double k = 10.0 / (1.0 + edge_cnt * 0.06);\n    \n    return (edge_cnt * w_edge + k * w_avg) / (edge_cnt + k);\n}\n\ndouble get_v_weight(int i, int j) {\n    double w_edge = get_weight(v_stats[i][j]);\n    double w_avg = get_weight(v_avg_stats[j]);\n    int edge_cnt = v_stats[i][j].cnt;\n    \n    double k = 10.0 / (1.0 + edge_cnt * 0.06);\n    \n    return (edge_cnt * w_edge + k * w_avg) / (edge_cnt + k);\n}\n\nvoid update_h(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    h_stats[i][j].log_sum += log(ratio);\n    h_stats[i][j].cnt++;\n    h_avg_stats[i].log_sum += log(ratio);\n    h_avg_stats[i].cnt++;\n}\n\nvoid update_v(int i, int j, double ratio) {\n    if (ratio <= 0) ratio = 1.0;\n    v_stats[i][j].log_sum += log(ratio);\n    v_stats[i][j].cnt++;\n    v_avg_stats[j].log_sum += log(ratio);\n    v_avg_stats[j].cnt++;\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int queries = 1000;\n    \n    for (int q = 0; q < queries; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // Dijkstra\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n        vector<vector<char>> move_dir(N, vector<char>(N, 0));\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[si][sj] = 0.0;\n        pq.push({0.0, si, sj});\n\n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        char dirs[] = {'U', 'D', 'L', 'R'};\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n\n            if (current.dist > dist[r][c]) continue;\n            if (r == ti && c == tj) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    double w = 0.0;\n                    if (d == 0) { // U\n                        w = get_v_weight(nr, nc);\n                    } else if (d == 1) { // D\n                        w = get_v_weight(r, c);\n                    } else if (d == 2) { // L\n                        w = get_h_weight(r, nc);\n                    } else if (d == 3) { // R\n                        w = get_h_weight(r, c);\n                    }\n\n                    if (dist[r][c] + w < dist[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + w;\n                        parent[nr][nc] = {r, c};\n                        move_dir[nr][nc] = dirs[d];\n                        pq.push({dist[nr][nc], nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path\n        string path = \"\";\n        int curr_r = ti, curr_c = tj;\n        double path_est = 0.0;\n        vector<pair<int, int>> path_edges_h;\n        vector<pair<int, int>> path_edges_v;\n\n        while (curr_r != si || curr_c != sj) {\n            int pr = parent[curr_r][curr_c].first;\n            int pc = parent[curr_r][curr_c].second;\n            char d = move_dir[curr_r][curr_c];\n            path += d;\n\n            if (d == 'U') {\n                path_edges_v.push_back({curr_r, curr_c});\n                path_est += get_v_weight(curr_r, curr_c);\n            } else if (d == 'D') {\n                path_edges_v.push_back({pr, pc});\n                path_est += get_v_weight(pr, pc);\n            } else if (d == 'L') {\n                path_edges_h.push_back({pr, curr_c});\n                path_est += get_h_weight(pr, curr_c);\n            } else if (d == 'R') {\n                path_edges_h.push_back({pr, pc});\n                path_est += get_h_weight(pr, pc);\n            }\n\n            curr_r = pr;\n            curr_c = pc;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << endl;\n\n        int result;\n        cin >> result;\n\n        if (path_est > 0) {\n            double ratio = (double)result / path_est;\n            if (ratio <= 0) ratio = 1.0;\n\n            for (auto& e : path_edges_h) {\n                update_h(e.first, e.second, ratio);\n            }\n            for (auto& e : path_edges_v) {\n                update_v(e.first, e.second, ratio);\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\nconst int NUM_CHARS = 8;\n\nint matrix[N][N];\nint string_counts[MAX_M];\nint total_matched = 0;\nint M;\n\nbitset<10000> valid_placements[MAX_M];\n\nstruct PlacementInfo {\n    int s;\n    int id;\n};\nvector<PlacementInfo> cell_active[N * N];\nvector<PlacementInfo> potential_lists[NUM_CHARS][N * N];\n\ninline int encode_id(int r, int c, int dir, int offset) {\n    return dir * N * N * MAX_LEN + r * N * MAX_LEN + c * MAX_LEN + offset;\n}\n\ninline void decode_id(int id, int &r, int &c, int &dir, int &offset) {\n    offset = id % MAX_LEN;\n    id /= MAX_LEN;\n    c = id % N;\n    id /= N;\n    r = id % N;\n    dir = id / N;\n}\n\nvector<string> strings;\nvector<int> string_lens;\n\nmt19937 rng;\nuniform_int_distribution<int> dist_char(0, NUM_CHARS - 1);\nuniform_int_distribution<int> dist_cell(0, N * N - 1);\n\nbool is_placement_valid(int s, int r, int c, int dir) {\n    int len = string_lens[s];\n    const string &str = strings[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        if (matrix[cr][cc] != (str[k] - 'A')) return false;\n    }\n    return true;\n}\n\nvoid add_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (valid_placements[s].test(id)) return;\n\n    valid_placements[s].set(id);\n    string_counts[s]++;\n    if (string_counts[s] == 1) total_matched++;\n\n    int len = string_lens[s];\n    for (int k = 0; k < len; ++k) {\n        int cr, cc;\n        if (dir == 0) {\n            cr = r;\n            cc = (c + k) % N;\n        } else {\n            cr = (r + k) % N;\n            cc = c;\n        }\n        cell_active[cr * N + cc].push_back({s, id});\n    }\n}\n\nvoid remove_placement(int s, int r, int c, int dir) {\n    int id = encode_id(r, c, dir, 0);\n    if (!valid_placements[s].test(id)) return;\n\n    valid_placements[s].reset(id);\n    string_counts[s]--;\n    if (string_counts[s] == 0) total_matched--;\n}\n\nvoid init_potential_lists() {\n    for (int ch = 0; ch < NUM_CHARS; ++ch) {\n        for (int c = 0; c < N * N; ++c) {\n            potential_lists[ch][c].clear();\n        }\n    }\n    \n    for (int s = 0; s < M; ++s) {\n        int len = string_lens[s];\n        const string &str = strings[s];\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_c = (c - k);\n                    if (start_c < 0) start_c += N;\n                    int id = encode_id(r, start_c, 0, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n                for (int k = 0; k < len; ++k) {\n                    int char_idx = str[k] - 'A';\n                    int start_r = (r - k);\n                    if (start_r < 0) start_r += N;\n                    int id = encode_id(start_r, c, 1, k);\n                    potential_lists[char_idx][r * N + c].push_back({s, id});\n                }\n            }\n        }\n    }\n}\n\nvoid clear_state() {\n    for (int s = 0; s < M; ++s) {\n        valid_placements[s].reset();\n        string_counts[s] = 0;\n    }\n    total_matched = 0;\n    \n    for (int c = 0; c < N * N; ++c) {\n        cell_active[c].clear();\n    }\n}\n\nvoid init_state() {\n    clear_state();\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            matrix[i][j] = dist_char(rng);\n        }\n    }\n\n    for (int s = 0; s < M; ++s) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (is_placement_valid(s, r, c, 0)) {\n                    add_placement(s, r, c, 0);\n                }\n                if (is_placement_valid(s, r, c, 1)) {\n                    add_placement(s, r, c, 1);\n                }\n            }\n        }\n    }\n}\n\nbool update_cell(int r, int c, int new_char) {\n    int old_char = matrix[r][c];\n    if (old_char == new_char) return true;\n\n    int cell_idx = r * N + c;\n\n    for (auto &p : cell_active[cell_idx]) {\n        if (valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            \n            int k = -1;\n            if (tdir == 0) {\n                k = (c - tc);\n                if (k < 0) k += N;\n            } else {\n                k = (r - tr);\n                if (k < 0) k += N;\n            }\n            \n            if (k >= string_lens[p.s]) continue;\n\n            int required_char = strings[p.s][k] - 'A';\n            if (required_char != new_char) {\n                remove_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    for (auto &p : potential_lists[new_char][cell_idx]) {\n        if (!valid_placements[p.s].test(p.id)) {\n            int tr, tc, tdir, toffset;\n            decode_id(p.id, tr, tc, tdir, toffset);\n            if (is_placement_valid(p.s, tr, tc, tdir)) {\n                add_placement(p.s, tr, tc, tdir);\n            }\n        }\n    }\n\n    matrix[r][c] = new_char;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_input;\n    cin >> N_input >> M;\n    \n    strings.resize(M);\n    string_lens.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        string_lens[i] = strings[i].length();\n    }\n\n    init_potential_lists();\n\n    // Very fast SA with strict time limit\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(20); // 20ms per test case\n    \n    double best_score = -1;\n    int best_matrix[N][N];\n    \n    // Fewer, faster restarts\n    int seeds[] = {1337, 42, 12345, 54321};\n    int num_seeds = sizeof(seeds) / sizeof(seeds[0]);\n    \n    for (int s = 0; s < num_seeds; ++s) {\n        auto current_time = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() >= time_limit.count()) {\n            break;\n        }\n        \n        rng.seed(seeds[s]);\n        init_state();\n        \n        double temperature = 60.0;\n        double cooling_rate = 0.998;\n        int max_iter = 3000;\n        \n        for (int iter = 0; iter < max_iter && temperature > 0.01; ++iter) {\n            int cell = dist_cell(rng);\n            int r = cell / N;\n            int c = cell % N;\n            \n            int old_char = matrix[r][c];\n            int new_char = dist_char(rng);\n            \n            int old_total_matched = total_matched;\n            \n            update_cell(r, c, new_char);\n            \n            double delta_score = total_matched - old_total_matched;\n            \n            double prob = 1.0;\n            if (delta_score < 0) {\n                prob = exp(delta_score / temperature);\n            }\n            \n            double rand_val = (double)dist_char(rng) / (double)NUM_CHARS;\n            if (rand_val >= prob) {\n                update_cell(r, c, old_char);\n            }\n\n            temperature *= cooling_rate;\n        }\n        \n        if (total_matched > best_score) {\n            best_score = total_matched;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    best_matrix[i][j] = matrix[i][j];\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int ch = best_matrix[i][j];\n            if (ch < 0) ch = 0;\n            if (ch >= NUM_CHARS) ch = NUM_CHARS - 1;\n            cout << (char)('A' + ch);\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> roads;\nint total_roads = 0;\n\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && grid[i][j] != '#';\n}\n\nbool isVisible(int ci, int cj, int ti, int tj) {\n    if (ci == ti) {\n        for (int j = min(cj, tj); j <= max(cj, tj); j++) {\n            if (grid[ci][j] == '#') return false;\n        }\n        return true;\n    }\n    if (cj == tj) {\n        for (int i = min(ci, ti); i <= max(ci, ti); i++) {\n            if (grid[i][cj] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\nint getCost(int i, int j) {\n    return grid[i][j] - '0';\n}\n\n// BFS for shortest path\nvector<pair<int,int>> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {{si, sj}};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    queue<pair<int,int>> q;\n    \n    dist[si][sj] = 0;\n    q.push({si, sj});\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) {\n            vector<pair<int,int>> path;\n            int i = ti, j = tj;\n            while (!(i == si && j == sj)) {\n                path.push_back({i, j});\n                auto [pi, pj] = parent[i][j];\n                i = pi; j = pj;\n            }\n            path.push_back({si, sj});\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (isValid(ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                parent[ni][nj] = {ci, cj};\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    return {{si, sj}, {ti, tj}};\n}\n\n// Calculate path cost\nlong long calcPathCost(const vector<pair<int,int>>& path) {\n    if (path.size() <= 1) return 0;\n    long long cost = 0;\n    for (size_t i = 1; i < path.size(); i++) {\n        cost += getCost(path[i].first, path[i].second);\n    }\n    return cost;\n}\n\n// Check coverage\nbool checkCoverage(const vector<pair<int,int>>& path, \n                   const vector<vector<vector<int>>>& visible,\n                   int total_roads) {\n    if (path.empty()) return total_roads == 0;\n    \n    vector<bool> covered(total_roads, false);\n    int count = 0;\n    \n    for (const auto& [ci, cj] : path) {\n        for (int k : visible[ci][cj]) {\n            if (!covered[k]) {\n                covered[k] = true;\n                count++;\n            }\n        }\n    }\n    \n    return count == total_roads;\n}\n\n// Lightweight 2-opt - only check coverage at end\nvector<pair<int,int>> optimize2optLight(vector<pair<int,int>> path,\n                                        const vector<vector<vector<int>>>& visible,\n                                        int total_roads) {\n    int n = path.size();\n    if (n < 6) return path;\n    \n    long long currentCost = calcPathCost(path);\n    bool improved = true;\n    int maxIter = 50;\n    int iter = 0;\n    \n    while (improved && iter < maxIter) {\n        improved = false;\n        iter++;\n        \n        // Try random swaps\n        for (int attempt = 0; attempt < 20; attempt++) {\n            int i = rand() % (n - 3) + 1;\n            int j = rand() % (n - i - 2) + i + 1;\n            \n            vector<pair<int,int>> newPath = path;\n            reverse(newPath.begin() + i + 1, newPath.begin() + j + 1);\n            \n            long long newCost = calcPathCost(newPath);\n            if (newCost < currentCost) {\n                // Check coverage only if improvement\n                if (checkCoverage(newPath, visible, total_roads)) {\n                    path = newPath;\n                    currentCost = newCost;\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    return path;\n}\n\n// Try to remove redundant positions\nvector<pair<int,int>> removeRedundant(vector<pair<int,int>> path,\n                                      const vector<vector<vector<int>>>& visible,\n                                      int total_roads) {\n    if (path.size() < 4) return path;\n    \n    vector<pair<int,int>> newPath = path;\n    \n    // Try removing positions that are not critical\n    for (int attempt = 0; attempt < 30; attempt++) {\n        int i = rand() % (path.size() - 2) + 1;\n        \n        // Check if removing this position maintains adjacency\n        if (i > 0 && i < (int)path.size() - 1) {\n            int di = abs(path[i-1].first - path[i+1].first);\n            int dj = abs(path[i-1].second - path[i+1].second);\n            \n            if (di + dj == 1) {  // Adjacent positions\n                newPath = path;\n                newPath.erase(newPath.begin() + i);\n                \n                if (checkCoverage(newPath, visible, total_roads)) {\n                    path = newPath;\n                }\n            }\n        }\n    }\n    \n    return path;\n}\n\n// Run greedy coverage and return path\nvector<pair<int,int>> runGreedy(int seed, const vector<vector<vector<int>>>& visible,\n                                const vector<vector<int>>& roadIndex, int total_roads) {\n    srand(seed);\n    \n    vector<bool> covered(total_roads, false);\n    int covered_count = 0;\n    for (int k : visible[si][sj]) {\n        if (!covered[k]) {\n            covered[k] = true;\n            covered_count++;\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    path.push_back({si, sj});\n    int ci = si, cj = sj;\n    \n    int max_iter = 10000;\n    int iter = 0;\n    int stuck_count = 0;\n    \n    while (covered_count < total_roads && iter < max_iter) {\n        iter++;\n        \n        int best_d = -1;\n        double best_score = -1;\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (!isValid(ni, nj)) continue;\n            \n            int new_count = 0;\n            for (int k : visible[ni][nj]) {\n                if (!covered[k]) {\n                    new_count++;\n                }\n            }\n            \n            int move_cost = getCost(ni, nj);\n            double score = new_count - 0.1 * move_cost;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1 || best_score < 0) {\n            stuck_count++;\n            \n            if (stuck_count % 2 == 0) {\n                int best_target_i = -1, best_target_j = -1;\n                int best_new = -1;\n                \n                for (const auto& [ti, tj] : roads) {\n                    if (!covered[roadIndex[ti][tj]]) {\n                        int new_vis = 0;\n                        for (int k : visible[ti][tj]) {\n                            if (!covered[k]) {\n                                new_vis++;\n                            }\n                        }\n                        if (new_vis > best_new) {\n                            best_new = new_vis;\n                            best_target_i = ti;\n                            best_target_j = tj;\n                        }\n                    }\n                }\n                \n                if (best_target_i != -1 && best_new > 0) {\n                    auto subPath = bfsPath(ci, cj, best_target_i, best_target_j);\n                    for (size_t k = 1; k < subPath.size(); k++) {\n                        path.push_back(subPath[k]);\n                        ci = subPath[k].first;\n                        cj = subPath[k].second;\n                        for (int idx : visible[ci][cj]) {\n                            if (!covered[idx]) {\n                                covered[idx] = true;\n                                covered_count++;\n                            }\n                        }\n                    }\n                    stuck_count = 0;\n                    continue;\n                }\n            }\n            \n            best_d = rand() % 4;\n            while (!isValid(ci + di[best_d], cj + dj[best_d])) {\n                best_d = (best_d + 1) % 4;\n            }\n        }\n        \n        ci += di[best_d];\n        cj += dj[best_d];\n        path.push_back({ci, cj});\n        \n        for (int k : visible[ci][cj]) {\n            if (!covered[k]) {\n                covered[k] = true;\n                covered_count++;\n            }\n        }\n    }\n    \n    // Return to start\n    auto returnPath = bfsPath(ci, cj, si, sj);\n    for (size_t i = 1; i < returnPath.size(); i++) {\n        path.push_back(returnPath[i]);\n    }\n    \n    // Clean duplicates\n    vector<pair<int,int>> cleaned;\n    for (size_t i = 0; i < path.size(); i++) {\n        if (i == 0 || path[i] != path[i-1]) {\n            cleaned.push_back(path[i]);\n        }\n    }\n    \n    // Ensure ends at start\n    if (cleaned.back().first != si || cleaned.back().second != sj) {\n        auto forceReturn = bfsPath(cleaned.back().first, cleaned.back().second, si, sj);\n        for (size_t i = 1; i < forceReturn.size(); i++) {\n            cleaned.push_back(forceReturn[i]);\n        }\n    }\n    \n    return cleaned;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                roads.push_back({i, j});\n            }\n        }\n    }\n    total_roads = roads.size();\n    \n    // Precompute visibility\n    vector<vector<vector<int>>> visible(N, vector<vector<int>>(N));\n    vector<vector<int>> roadIndex(N, vector<int>(N, -1));\n    \n    int idx = 0;\n    for (const auto& [i, j] : roads) {\n        roadIndex[i][j] = idx++;\n    }\n    \n    for (const auto& [i, j] : roads) {\n        for (const auto& [ti, tj] : roads) {\n            if (isVisible(i, j, ti, tj)) {\n                visible[i][j].push_back(roadIndex[ti][tj]);\n            }\n        }\n    }\n    \n    // Try multiple seeds and pick best\n    vector<pair<int,int>> bestPath;\n    long long bestCost = -1;\n    \n    for (int seed = 42; seed < 42 + 5; seed++) {\n        auto path = runGreedy(seed, visible, roadIndex, total_roads);\n        \n        if (checkCoverage(path, visible, total_roads)) {\n            long long cost = calcPathCost(path);\n            \n            // Apply optimization\n            path = optimize2optLight(path, visible, total_roads);\n            path = removeRedundant(path, visible, total_roads);\n            \n            // Ensure still ends at start\n            if (path.back().first != si || path.back().second != sj) {\n                auto forceReturn = bfsPath(path.back().first, path.back().second, si, sj);\n                for (size_t i = 1; i < forceReturn.size(); i++) {\n                    path.push_back(forceReturn[i]);\n                }\n            }\n            \n            // Clean duplicates\n            vector<pair<int,int>> cleaned;\n            for (size_t i = 0; i < path.size(); i++) {\n                if (i == 0 || path[i] != path[i-1]) {\n                    cleaned.push_back(path[i]);\n                }\n            }\n            \n            cost = calcPathCost(cleaned);\n            \n            if (bestCost == -1 || cost < bestCost) {\n                bestPath = cleaned;\n                bestCost = cost;\n            }\n        }\n    }\n    \n    // Convert to movement string\n    string result;\n    for (size_t i = 1; i < bestPath.size(); i++) {\n        int di_val = bestPath[i].first - bestPath[i-1].first;\n        int dj_val = bestPath[i].second - bestPath[i-1].second;\n        \n        if (di_val == -1) result += 'U';\n        else if (di_val == 1) result += 'D';\n        else if (dj_val == -1) result += 'L';\n        else if (dj_val == 1) result += 'R';\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int status; // 0: available, 1: assigned, 2: done\n    int start_day;\n    int indegree;\n    int outdegree;\n};\n\nstruct Member {\n    int id;\n    vector<double> estimate;\n    vector<double> confidence;\n    int current_task;\n    int tasks_completed;\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<vector<int>> adj;\nint day = 0;\n\ndouble calculate_work(int task_idx, int member_idx) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            work += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n        }\n    }\n    return work;\n}\n\ndouble calculate_cost(int task_idx, int member_idx) {\n    double work = calculate_work(task_idx, member_idx);\n    \n    // Add small uncertainty penalty for low confidence\n    double uncertainty = 0;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            uncertainty += (1.0 / (1.0 + members[member_idx].confidence[k]));\n        }\n    }\n    \n    double expected_time = max(1.0, work);\n    expected_time += uncertainty * 0.5; // Smaller penalty\n    \n    return expected_time;\n}\n\nvoid update_skills(int member_idx, int task_idx, int t) {\n    int& completed = members[member_idx].tasks_completed;\n    completed++;\n    \n    // If completed in 1 day, we know w=0, so s >= d for all skills\n    if (t == 1) {\n        for (int k = 0; k < K; ++k) {\n            if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n                members[member_idx].estimate[k] = tasks[task_idx].d[k];\n            }\n        }\n    }\n    \n    // Calculate predicted work\n    double work_pred = 0;\n    vector<int> contributing_skills;\n    for (int k = 0; k < K; ++k) {\n        if (tasks[task_idx].d[k] > members[member_idx].estimate[k]) {\n            work_pred += (tasks[task_idx].d[k] - members[member_idx].estimate[k]);\n            contributing_skills.push_back(k);\n        }\n    }\n    \n    // Observed work\n    double work_obs = 0;\n    if (t > 1) {\n        work_obs = t;\n    }\n    \n    // Update estimates with moderate learning rate\n    if (contributing_skills.size() > 0) {\n        double diff = work_pred - work_obs;\n        // Learning rate: moderate, not too aggressive\n        double learning_rate = 0.5 / (1.0 + completed * 0.2);\n        \n        for (int k : contributing_skills) {\n            double adjust = diff / contributing_skills.size() * learning_rate;\n            members[member_idx].estimate[k] -= adjust;\n            members[member_idx].estimate[k] = max(0.0, members[member_idx].estimate[k]);\n        }\n    }\n    \n    // Increase confidence for all skills\n    for (int k = 0; k < K; ++k) {\n        members[member_idx].confidence[k] += 0.8;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n        }\n        tasks[i].status = 0;\n        tasks[i].start_day = 0;\n        tasks[i].indegree = 0;\n        tasks[i].outdegree = 0;\n    }\n\n    adj.resize(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        tasks[v].indegree++;\n        tasks[u].outdegree++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].estimate.assign(K, 0.0);\n        members[i].confidence.assign(K, 0.0);\n        members[i].current_task = -1;\n        members[i].tasks_completed = 0;\n    }\n\n    while (true) {\n        day++;\n        if (day > 2000) break;\n\n        // Identify free members\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (members[j].current_task == -1) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Identify available tasks (status == 0 AND indegree == 0)\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (tasks[i].status == 0 && tasks[i].indegree == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // If no available tasks, output nothing\n        if (available_tasks.empty()) {\n            cout << \"0\\n\" << flush;\n            \n            int n_completions;\n            cin >> n_completions;\n            if (n_completions == -1) break;\n\n            vector<int> completed_members(n_completions);\n            for (int i = 0; i < n_completions; ++i) {\n                cin >> completed_members[i];\n                --completed_members[i];\n            }\n\n            for (int j : completed_members) {\n                int task_idx = members[j].current_task;\n                if (task_idx != -1) {\n                    int t = day - tasks[task_idx].start_day + 1;\n                    update_skills(j, task_idx, t);\n                    tasks[task_idx].status = 2;\n                    members[j].current_task = -1;\n                    \n                    for (int v : adj[task_idx]) {\n                        tasks[v].indegree--;\n                    }\n                }\n            }\n            continue;\n        }\n\n        // Create assignment candidates\n        struct Assignment {\n            double cost;\n            int task_idx;\n            int member_idx;\n            int outdegree;\n            int member_tasks;\n            bool operator<(const Assignment& other) const {\n                // Primary: minimize cost\n                if (abs(cost - other.cost) > 1e-6) return cost < other.cost;\n                // Secondary: maximize outdegree (unlock more tasks)\n                if (outdegree != other.outdegree) return outdegree > other.outdegree;\n                // Tertiary: prefer members with fewer completed tasks (exploration)\n                return member_tasks < other.member_tasks;\n            }\n        };\n\n        vector<Assignment> candidates;\n        candidates.reserve(free_members.size() * available_tasks.size());\n\n        for (int j : free_members) {\n            for (int i : available_tasks) {\n                candidates.push_back({\n                    calculate_cost(i, j),\n                    i,\n                    j,\n                    tasks[i].outdegree,\n                    members[j].tasks_completed\n                });\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n\n        // Greedy assignment\n        vector<pair<int, int>> output_assignments;\n        vector<int> assigned_task(N, -1);\n        vector<int> assigned_member(M, -1);\n\n        for (const auto& cand : candidates) {\n            if (assigned_task[cand.task_idx] == -1 && assigned_member[cand.member_idx] == -1) {\n                assigned_task[cand.task_idx] = cand.task_idx;\n                assigned_member[cand.member_idx] = cand.member_idx;\n                output_assignments.push_back({cand.member_idx, cand.task_idx});\n                \n                tasks[cand.task_idx].status = 1;\n                tasks[cand.task_idx].start_day = day;\n                members[cand.member_idx].current_task = cand.task_idx;\n            }\n        }\n\n        // Output\n        cout << output_assignments.size();\n        for (const auto& p : output_assignments) {\n            cout << \" \" << (p.first + 1) << \" \" << (p.second + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completions\n        int n_completions;\n        cin >> n_completions;\n        if (n_completions == -1) break;\n\n        vector<int> completed_members(n_completions);\n        for (int i = 0; i < n_completions; ++i) {\n            cin >> completed_members[i];\n            --completed_members[i];\n        }\n\n        for (int j : completed_members) {\n            int task_idx = members[j].current_task;\n            if (task_idx != -1) {\n                int t = day - tasks[task_idx].start_day + 1;\n                update_skills(j, task_idx, t);\n                tasks[task_idx].status = 2;\n                members[j].current_task = -1;\n                \n                for (int v : adj[task_idx]) {\n                    tasks[v].indegree--;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <vector>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n    int orderId; // -1 for office\n    int type; // 0 for pickup, 1 for dropoff, 2 for office\n};\n\nint dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nclass Solver {\nprivate:\n    vector<Order> orders;\n    int ox = 400, oy = 400;\n    vector<int> selected;\n    vector<bool> isSelected;\n    vector<int> notSelected;\n    vector<Point> route;\n    int currentCost;\n    int bestCost;\n    vector<Point> bestRoute;\n    vector<int> bestSelected;\n    \n    mt19937 gen;\n    uniform_real_distribution<double> randDist;\n    \npublic:\n    Solver() {\n        gen.seed(chrono::steady_clock::now().time_since_epoch().count());\n        randDist = uniform_real_distribution<double>(0.0, 1.0);\n    }\n    \n    void readInput() {\n        orders.resize(1000);\n        for (int i = 0; i < 1000; i++) {\n            orders[i].id = i + 1;\n            cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n        }\n    }\n    \n    void init() {\n        selected.clear();\n        isSelected.assign(1000, false);\n        notSelected.clear();\n        \n        // Initial selection with small randomness for diversity\n        vector<pair<int, int>> scoreList;\n        for (int i = 0; i < 1000; i++) {\n            int pickupDist = dist(orders[i].a, orders[i].b, ox, oy);\n            int dropoffDist = dist(orders[i].c, orders[i].d, ox, oy);\n            int internalDist = dist(orders[i].a, orders[i].b, orders[i].c, orders[i].d);\n            int score = pickupDist + dropoffDist + internalDist + (int)(randDist(gen) * 50);\n            scoreList.push_back({score, i});\n        }\n        sort(scoreList.begin(), scoreList.end());\n        \n        for (int i = 0; i < 50; i++) {\n            int idx = scoreList[i].second;\n            selected.push_back(idx);\n            isSelected[idx] = true;\n        }\n        for (int i = 50; i < 1000; i++) {\n            notSelected.push_back(scoreList[i].second);\n        }\n        \n        buildRoute();\n        currentCost = calcCost();\n        bestCost = currentCost;\n        bestRoute = route;\n        bestSelected = selected;\n    }\n    \n    void buildRoute() {\n        route.clear();\n        route.reserve(102);\n        route.push_back({ox, oy, -1, 2});\n        for (int idx : selected) {\n            route.push_back({orders[idx].a, orders[idx].b, idx, 0});\n        }\n        for (int idx : selected) {\n            route.push_back({orders[idx].c, orders[idx].d, idx, 1});\n        }\n        route.push_back({ox, oy, -1, 2});\n    }\n    \n    int calcCost() {\n        int cost = 0;\n        for (size_t i = 0; i + 1 < route.size(); i++) {\n            cost += dist(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n        }\n        return cost;\n    }\n    \n    bool isValidRoute() {\n        vector<int> pickupPos(1000, -1), dropoffPos(1000, -1);\n        for (size_t k = 0; k < route.size(); k++) {\n            if (route[k].orderId >= 0) {\n                if (route[k].type == 0) pickupPos[route[k].orderId] = k;\n                else dropoffPos[route[k].orderId] = k;\n            }\n        }\n        for (int idx : selected) {\n            if (pickupPos[idx] >= dropoffPos[idx]) return false;\n        }\n        return true;\n    }\n    \n    void optimize(double timeLimit) {\n        double temperature = 5000.0;\n        double coolingRate = 0.99996;\n        double minTemp = 1.0;\n        \n        auto startTime = chrono::high_resolution_clock::now();\n        \n        while (true) {\n            auto currentTime = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed >= timeLimit) break;\n            \n            // Move type selection\n            double r = randDist(gen);\n            int moveType;\n            if (r < 0.30) moveType = 0;      // Swap\n            else if (r < 0.60) moveType = 1; // 2-opt\n            else if (r < 0.85) moveType = 2; // Insert\n            else moveType = 3;               // Relocate\n            \n            if (moveType == 0 && notSelected.size() > 0) {\n                int inIdx = (int)(randDist(gen) * selected.size());\n                int outIdx = (int)(randDist(gen) * notSelected.size());\n                \n                int inOrder = selected[inIdx];\n                int outOrder = notSelected[outIdx];\n                \n                auto oldSelected = selected;\n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                selected[inIdx] = outOrder;\n                isSelected[inOrder] = false;\n                isSelected[outOrder] = true;\n                notSelected[outIdx] = inOrder;\n                \n                buildRoute();\n                \n                if (!isValidRoute()) {\n                    selected = oldSelected;\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    isSelected[inOrder] = true;\n                    isSelected[outOrder] = false;\n                    notSelected[outIdx] = outOrder;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                        bestSelected = selected;\n                    }\n                } else {\n                    selected = oldSelected;\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    isSelected[inOrder] = true;\n                    isSelected[outOrder] = false;\n                    notSelected[outIdx] = outOrder;\n                }\n            } else if (moveType == 1) {\n                int i = 1 + (int)(randDist(gen) * (route.size() - 4));\n                int j = i + 1 + (int)(randDist(gen) * (route.size() - i - 3));\n                i = max(1, i);\n                j = min((int)route.size() - 2, j);\n                \n                if (i >= j) continue;\n                \n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                reverse(route.begin() + i, route.begin() + j + 1);\n                \n                if (!isValidRoute()) {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                    }\n                } else {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                }\n            } else if (moveType == 2) {\n                int pos1 = 1 + (int)(randDist(gen) * (route.size() - 3));\n                int pos2 = 1 + (int)(randDist(gen) * (route.size() - 3));\n                \n                if (pos1 == pos2) continue;\n                \n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                Point p = route[pos1];\n                route.erase(route.begin() + pos1);\n                route.insert(route.begin() + pos2, p);\n                \n                if (!isValidRoute()) {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                        bestSelected = selected;\n                    }\n                } else {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                }\n            } else {\n                int orderIdx = (int)(randDist(gen) * selected.size());\n                int order = selected[orderIdx];\n                \n                int pickupPos = -1, dropoffPos = -1;\n                for (size_t k = 0; k < route.size(); k++) {\n                    if (route[k].orderId == order) {\n                        if (route[k].type == 0) pickupPos = k;\n                        else dropoffPos = k;\n                    }\n                }\n                \n                if (pickupPos < 0 || dropoffPos < 0) continue;\n                \n                int maxPos = (int)route.size() - 3;\n                int minPos = 1;\n                int newPos = minPos + (int)(randDist(gen) * (maxPos - minPos));\n                \n                if (newPos >= pickupPos) newPos++;\n                if (newPos >= dropoffPos) newPos++;\n                \n                newPos = min(newPos, (int)route.size() - 3);\n                newPos = max(newPos, 1);\n                \n                auto oldRoute = route;\n                auto oldCost = currentCost;\n                \n                Point pickup = route[pickupPos];\n                Point dropoff = route[dropoffPos];\n                \n                route.erase(route.begin() + dropoffPos);\n                route.erase(route.begin() + pickupPos);\n                route.insert(route.begin() + newPos, pickup);\n                route.insert(route.begin() + newPos + 1, dropoff);\n                \n                if (!isValidRoute()) {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                    continue;\n                }\n                \n                int newCost = calcCost();\n                int delta = newCost - currentCost;\n                \n                if (delta < 0 || randDist(gen) < exp(-delta / temperature)) {\n                    currentCost = newCost;\n                    if (currentCost < bestCost) {\n                        bestCost = currentCost;\n                        bestRoute = route;\n                        bestSelected = selected;\n                    }\n                } else {\n                    route = oldRoute;\n                    currentCost = oldCost;\n                }\n            }\n            \n            temperature *= coolingRate;\n            if (temperature < minTemp) temperature = minTemp;\n        }\n    }\n    \n    void output() {\n        cout << bestSelected.size();\n        for (int idx : bestSelected) {\n            cout << \" \" << orders[idx].id;\n        }\n        cout << \"\\n\";\n        cout << bestRoute.size();\n        for (auto& p : bestRoute) {\n            cout << \" \" << p.x << \" \" << p.y;\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.readInput();\n    \n    // Multi-start optimization with 4 restarts\n    int numRestarts = 4;\n    double totalTimeLimit = 1.90;\n    double timePerRestart = totalTimeLimit / numRestarts;\n    \n    for (int r = 0; r < numRestarts; r++) {\n        solver.init();\n        solver.optimize(timePerRestart);\n    }\n    \n    solver.output();\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<pair<int, int>> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        long long dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = (int)round(sqrt(dx * dx + dy * dy));\n    }\n\n    DSU dsu(N);\n    int accepted_edges = 0;\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int root_u = dsu.find(u);\n        int root_v = dsu.find(v);\n\n        if (root_u == root_v) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Count remaining edges for each component\n        vector<int> edge_count(N, 0);\n        long long min_d_direct = 1e18;\n        long long min_d_any = 1e18;\n        int remaining_edges = 0;\n        bool has_direct = false;\n\n        for (int j = i + 1; j < M; ++j) {\n            int u_j = edges[j].u;\n            int v_j = edges[j].v;\n            int ru = dsu.find(u_j);\n            int rv = dsu.find(v_j);\n\n            if (ru != rv) {\n                remaining_edges++;\n                edge_count[ru]++;\n                edge_count[rv]++;\n                min_d_any = min(min_d_any, (long long)edges[j].d);\n                \n                if ((ru == root_u && rv == root_v) || (ru == root_v && rv == root_u)) {\n                    min_d_direct = min(min_d_direct, (long long)edges[j].d);\n                    has_direct = true;\n                }\n            }\n        }\n\n        bool accept = true;\n\n        // CRITICAL SAFETY: If either component has very few remaining edges, ALWAYS accept\n        if (edge_count[root_u] <= 3 || edge_count[root_v] <= 3) {\n            accept = true;\n        }\n        // SAFETY: If remaining edges are close to what we need, accept\n        else if (remaining_edges <= (N - 1 - accepted_edges) + 5) {\n            accept = true;\n        }\n        // SAFETY: If we're behind on progress, accept\n        else if (accepted_edges < i * 0.15) {\n            accept = true;\n        }\n        // Cost optimization (only when safe)\n        else {\n            if (has_direct) {\n                // Use 2.8x threshold (expected value is 2x, add buffer)\n                if (l_i > 2.8 * min_d_direct) {\n                    accept = false;\n                }\n            }\n            else if (min_d_any != 1e18) {\n                // For indirect path, use 3.2x threshold\n                if (l_i > 3.2 * min_d_any) {\n                    accept = false;\n                }\n            }\n        }\n\n        cout << (accept ? \"1\" : \"0\") << \"\\n\";\n        cout.flush();\n\n        if (accept) {\n            dsu.unite(u, v);\n            accepted_edges++;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Pet {\n    int x, y, type;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct State {\n    int turn;\n    vector<Pet> pets;\n    vector<Human> humans;\n    vector<vector<bool>> wall;\n};\n\nState state;\nmt19937 rng;\n\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char moveChars[] = {'U', 'D', 'L', 'R'};\nconst char wallChars[] = {'u', 'd', 'l', 'r'};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;\n}\n\nbool hasPetAt(int x, int y) {\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].x == x && state.pets[i].y == y) return true;\n    }\n    return false;\n}\n\nbool hasHumanAt(int x, int y) {\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        if (state.humans[i].x == x && state.humans[i].y == y) return true;\n    }\n    return false;\n}\n\nbool hasPetAdjacent(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (hasPetAt(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canPlaceWall(int x, int y) {\n    if (!isValid(x, y)) return false;\n    if (state.wall[x][y]) return false;\n    if (hasPetAt(x, y)) return false;\n    if (hasHumanAt(x, y)) return false;\n    if (hasPetAdjacent(x, y)) return false;\n    return true;\n}\n\nint bfsReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    if (state.wall[startX][startY]) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint countPetsInReachable(int startX, int startY) {\n    if (!isValid(startX, startY)) return 0;\n    if (state.wall[startX][startY]) return 0;\n    \n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    \n    visited[startX][startY] = true;\n    q.push({startX, startY});\n    int count = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (hasPetAt(x, y)) count++;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !visited[nx][ny] && !state.wall[nx][ny]) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return count;\n}\n\nint bfsDistance(int x1, int y1, int x2, int y2) {\n    if (!isValid(x1, y1) || !isValid(x2, y2)) return 1e9;\n    if (x1 == x2 && y1 == y2) return 0;\n    \n    vector<vector<int>> dist(GRID_SIZE, vector<int>(GRID_SIZE, 1e9));\n    queue<pair<int, int>> q;\n    \n    dist[x1][y1] = 0;\n    q.push({x1, y1});\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == x2 && y == y2) return dist[x][y];\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny] && dist[nx][ny] == 1e9) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return 1e9;\n}\n\nint countDangerousPets(int x, int y) {\n    int count = 0;\n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].type == 4 || state.pets[i].type == 5) {\n            int dist = bfsDistance(x, y, state.pets[i].x, state.pets[i].y);\n            if (dist < 20) count++;\n        }\n    }\n    return count;\n}\n\npair<int, int> findNearestDangerousPet(int hx, int hy) {\n    int minDist = 1e9;\n    pair<int, int> nearest = {-1, -1};\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        if (state.pets[i].type == 4 || state.pets[i].type == 5) {\n            int dist = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n            if (dist < minDist) {\n                minDist = dist;\n                nearest = {state.pets[i].x, state.pets[i].y};\n            }\n        }\n    }\n    \n    return nearest;\n}\n\npair<int, int> findNearestAnyPet(int hx, int hy) {\n    int minDist = 1e9;\n    pair<int, int> nearest = {-1, -1};\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        int dist = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n        if (dist < minDist) {\n            minDist = dist;\n            nearest = {state.pets[i].x, state.pets[i].y};\n        }\n    }\n    \n    return nearest;\n}\n\ndouble evaluatePosition(int x, int y) {\n    if (!isValid(x, y) || state.wall[x][y]) return -1e9;\n    \n    int reachable = bfsReachable(x, y);\n    int petsInArea = countPetsInReachable(x, y);\n    int dangerousPets = countDangerousPets(x, y);\n    \n    double score = (double)reachable / 900.0 * pow(0.5, petsInArea);\n    score -= dangerousPets * 0.8;\n    score -= petsInArea * 0.5;\n    \n    int distToCenter = abs(x - 14) + abs(y - 14);\n    score += (30 - distToCenter) * 0.01;\n    \n    return score;\n}\n\ndouble evaluateWallPlacement(int hx, int hy, int wx, int wy, int turn) {\n    if (!canPlaceWall(wx, wy)) return -1e9;\n    \n    bool originalWall = state.wall[wx][wy];\n    state.wall[wx][wy] = true;\n    \n    double score = evaluatePosition(hx, hy);\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        int distBefore = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n        state.wall[wx][wy] = false;\n        int distAfter = bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n        state.wall[wx][wy] = true;\n        \n        if (distAfter > distBefore) {\n            if (state.pets[i].type == 4 || state.pets[i].type == 5) {\n                score += 1.0;\n            } else {\n                score += 0.5;\n            }\n        }\n    }\n    \n    if (turn < 20) {\n        score += 0.5;\n    } else if (turn < 40) {\n        score += 0.3;\n    } else if (turn < 80) {\n        score += 0.2;\n    } else if (turn < 150) {\n        score += 0.1;\n    }\n    \n    state.wall[wx][wy] = originalWall;\n    \n    return score;\n}\n\npair<int, int> findHumanCenter() {\n    int sumX = 0, sumY = 0;\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        sumX += state.humans[i].x;\n        sumY += state.humans[i].y;\n    }\n    return {sumX / (int)state.humans.size(), sumY / (int)state.humans.size()};\n}\n\nbool isMoveSafe(int nx, int ny, int humanIdx) {\n    if (!isValid(nx, ny)) return false;\n    if (state.wall[nx][ny]) return false;\n    \n    for (size_t i = 0; i < state.humans.size(); i++) {\n        if (i == (size_t)humanIdx) continue;\n        int dist = abs(state.humans[i].x - nx) + abs(state.humans[i].y - ny);\n        if (dist == 1) return false;\n    }\n    \n    return true;\n}\n\nbool moveIncreasesPetDistance(int hx, int hy, int nx, int ny) {\n    int totalDistBefore = 0;\n    int totalDistAfter = 0;\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        totalDistBefore += bfsDistance(hx, hy, state.pets[i].x, state.pets[i].y);\n        totalDistAfter += bfsDistance(nx, ny, state.pets[i].x, state.pets[i].y);\n    }\n    \n    return totalDistAfter >= totalDistBefore;\n}\n\nbool moveIncreasesReachableArea(int hx, int hy, int nx, int ny) {\n    int areaBefore = bfsReachable(hx, hy);\n    int areaAfter = bfsReachable(nx, ny);\n    return areaAfter > areaBefore;\n}\n\nbool isInCorner(int x, int y) {\n    return (x <= 2 || x >= 27 || y <= 2 || y >= 27);\n}\n\nbool isInEdge(int x, int y) {\n    return (x <= 5 || x >= 24 || y <= 5 || y >= 24);\n}\n\n// Check if position is in a tight space (hard to expand from)\nbool isInTightSpace(int x, int y) {\n    int freeDirections = 0;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (isValid(nx, ny) && !state.wall[nx][ny]) {\n            freeDirections++;\n        }\n    }\n    return freeDirections <= 2;\n}\n\nchar decideAction(int humanIdx) {\n    int hx = state.humans[humanIdx].x;\n    int hy = state.humans[humanIdx].y;\n    int turn = state.turn;\n    \n    pair<int, int> nearestDangerous = findNearestDangerousPet(hx, hy);\n    pair<int, int> nearestAny = findNearestAnyPet(hx, hy);\n    int distToDangerous = (nearestDangerous.first >= 0) ? \n                          bfsDistance(hx, hy, nearestDangerous.first, nearestDangerous.second) : 1e9;\n    int distToAny = (nearestAny.first >= 0) ? \n                    bfsDistance(hx, hy, nearestAny.first, nearestAny.second) : 1e9;\n    \n    pair<int, int> center = findHumanCenter();\n    int currentArea = bfsReachable(hx, hy);\n    \n    char bestAction = '.';\n    double bestScore = evaluatePosition(hx, hy);\n    \n    // Phase 1: Early game (0-20) - Build defensive perimeter\n    if (turn < 20) {\n        for (int d = 0; d < 4; d++) {\n            int wx = hx + dx[d];\n            int wy = hy + dy[d];\n            char wallChar = wallChars[d];\n            \n            if (!canPlaceWall(wx, wy)) continue;\n            \n            double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n            \n            if (nearestAny.first >= 0) {\n                int distToWall = abs(wx - nearestAny.first) + abs(wy - nearestAny.second);\n                if (distToWall <= 5) {\n                    score += 2.0;\n                }\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = wallChar;\n            }\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            if (!moveIncreasesPetDistance(hx, hy, nx, ny)) continue;\n            \n            int distToCenterBefore = abs(hx - center.first) + abs(hy - center.second);\n            int distToCenterAfter = abs(nx - center.first) + abs(ny - center.second);\n            \n            if (distToCenterAfter < distToCenterBefore) {\n                double score = evaluatePosition(nx, ny);\n                score += 0.3;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = moveChar;\n                }\n            }\n        }\n    }\n    // Phase 2: Early-mid game (21-40) - Continue building walls\n    else if (turn < 40) {\n        if (distToAny < 10) {\n            for (int d = 0; d < 4; d++) {\n                int wx = hx + dx[d];\n                int wy = hy + dy[d];\n                char wallChar = wallChars[d];\n                \n                if (!canPlaceWall(wx, wy)) continue;\n                \n                double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n                \n                if (nearestAny.first >= 0) {\n                    int distToWall = abs(wx - nearestAny.first) + abs(wy - nearestAny.second);\n                    if (distToWall <= 6) {\n                        score += 1.5;\n                    }\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = wallChar;\n                }\n            }\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            if (!moveIncreasesPetDistance(hx, hy, nx, ny)) continue;\n            \n            double score = evaluatePosition(nx, ny);\n            int dangerous = countDangerousPets(nx, ny);\n            score -= dangerous * 0.5;\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = moveChar;\n            }\n        }\n    }\n    // Phase 3: Mid game (41-100) - Balance defense and expansion\n    else if (turn < 100) {\n        if (distToDangerous < 12) {\n            for (int d = 0; d < 4; d++) {\n                int wx = hx + dx[d];\n                int wy = hy + dy[d];\n                char wallChar = wallChars[d];\n                \n                if (!canPlaceWall(wx, wy)) continue;\n                \n                double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n                \n                if (nearestDangerous.first >= 0) {\n                    int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                    if (distToWall <= 8) {\n                        score += 1.2;\n                    }\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = wallChar;\n                }\n            }\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            if (!moveIncreasesPetDistance(hx, hy, nx, ny)) continue;\n            if (!moveIncreasesReachableArea(hx, hy, nx, ny)) continue;\n            \n            double score = evaluatePosition(nx, ny);\n            int dangerous = countDangerousPets(nx, ny);\n            score -= dangerous * 0.4;\n            \n            if (isInCorner(hx, hy) && !isInCorner(nx, ny)) {\n                score += 0.5;\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = moveChar;\n            }\n        }\n    }\n    // Phase 4: Late mid game (101-180) - Expand strategically\n    else if (turn < 180) {\n        if (distToDangerous < 15) {\n            for (int d = 0; d < 4; d++) {\n                int wx = hx + dx[d];\n                int wy = hy + dy[d];\n                char wallChar = wallChars[d];\n                \n                if (!canPlaceWall(wx, wy)) continue;\n                \n                double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n                \n                if (nearestDangerous.first >= 0) {\n                    int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                    if (distToWall <= 10) {\n                        score += 1.0;\n                    }\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = wallChar;\n                }\n            }\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            \n            double score = evaluatePosition(nx, ny);\n            int dangerous = countDangerousPets(nx, ny);\n            score -= dangerous * 0.3;\n            \n            if (moveIncreasesReachableArea(hx, hy, nx, ny)) {\n                score += 1.0;\n            }\n            \n            int distToCenterBefore = abs(hx - 14) + abs(hy - 14);\n            int distToCenterAfter = abs(nx - 14) + abs(ny - 14);\n            if (distToCenterAfter < distToCenterBefore) {\n                score += 0.5;\n            }\n            \n            if (isInTightSpace(hx, hy) && !isInTightSpace(nx, ny)) {\n                score += 0.8;\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = moveChar;\n            }\n        }\n    }\n    // Phase 5: Late game (181-300) - Maximize reachable area aggressively\n    else {\n        if (distToDangerous < 10) {\n            for (int d = 0; d < 4; d++) {\n                int wx = hx + dx[d];\n                int wy = hy + dy[d];\n                char wallChar = wallChars[d];\n                \n                if (!canPlaceWall(wx, wy)) continue;\n                \n                double score = evaluateWallPlacement(hx, hy, wx, wy, turn);\n                \n                if (nearestDangerous.first >= 0) {\n                    int distToWall = abs(wx - nearestDangerous.first) + abs(wy - nearestDangerous.second);\n                    if (distToWall <= 8) {\n                        score += 1.5;\n                    }\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestAction = wallChar;\n                }\n            }\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = hx + dx[d];\n            int ny = hy + dy[d];\n            char moveChar = moveChars[d];\n            \n            if (!isMoveSafe(nx, ny, humanIdx)) continue;\n            \n            double score = evaluatePosition(nx, ny);\n            int dangerous = countDangerousPets(nx, ny);\n            score -= dangerous * 0.2;\n            \n            // Very strong bonus for increasing reachable area\n            if (moveIncreasesReachableArea(hx, hy, nx, ny)) {\n                score += 2.0;\n            }\n            \n            // Strong bonus for moving toward grid center\n            int distToCenterBefore = abs(hx - 14) + abs(hy - 14);\n            int distToCenterAfter = abs(nx - 14) + abs(ny - 14);\n            if (distToCenterAfter < distToCenterBefore) {\n                score += 1.0;\n            }\n            \n            // Bonus for escaping tight spaces\n            if (isInTightSpace(hx, hy) && !isInTightSpace(nx, ny)) {\n                score += 1.5;\n            }\n            \n            // Bonus for escaping corners/edges\n            if (isInCorner(hx, hy) && !isInCorner(nx, ny)) {\n                score += 1.0;\n            }\n            if (isInEdge(hx, hy) && !isInEdge(nx, ny)) {\n                score += 0.5;\n            }\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestAction = moveChar;\n            }\n        }\n        \n        // Penalty for staying in place when expansion is possible\n        if (bestAction == '.') {\n            bool canExpand = false;\n            for (int d = 0; d < 4; d++) {\n                int nx = hx + dx[d];\n                int ny = hy + dy[d];\n                if (isMoveSafe(nx, ny, humanIdx) && moveIncreasesReachableArea(hx, hy, nx, ny)) {\n                    canExpand = true;\n                    break;\n                }\n            }\n            if (canExpand) {\n                bestScore -= 0.5; // Penalty for not expanding\n            }\n        }\n    }\n    \n    return bestAction;\n}\n\nvoid updateState(const vector<string>& petMoves, const string& actions) {\n    for (size_t i = 0; i < state.humans.size(); i++) {\n        char action = actions[i];\n        \n        if (action >= 'A' && action <= 'Z') {\n            int d = 0;\n            if (action == 'U') d = 0;\n            else if (action == 'D') d = 1;\n            else if (action == 'L') d = 2;\n            else if (action == 'R') d = 3;\n            \n            int nx = state.humans[i].x + dx[d];\n            int ny = state.humans[i].y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                state.humans[i].x = nx;\n                state.humans[i].y = ny;\n            }\n        } else if (action >= 'a' && action <= 'z') {\n            int d = 0;\n            if (action == 'u') d = 0;\n            else if (action == 'd') d = 1;\n            else if (action == 'l') d = 2;\n            else if (action == 'r') d = 3;\n            \n            int wx = state.humans[i].x + dx[d];\n            int wy = state.humans[i].y + dy[d];\n            \n            if (canPlaceWall(wx, wy)) {\n                state.wall[wx][wy] = true;\n            }\n        }\n    }\n    \n    for (size_t i = 0; i < state.pets.size(); i++) {\n        const string& move = petMoves[i];\n        int x = state.pets[i].x;\n        int y = state.pets[i].y;\n        \n        for (char c : move) {\n            int d = 0;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            \n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (isValid(nx, ny) && !state.wall[nx][ny]) {\n                x = nx;\n                y = ny;\n            }\n        }\n        \n        state.pets[i].x = x;\n        state.pets[i].y = y;\n    }\n    \n    state.turn++;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    int N;\n    cin >> N;\n    \n    state.pets.resize(N);\n    for (size_t i = 0; i < (size_t)N; i++) {\n        cin >> state.pets[i].x >> state.pets[i].y >> state.pets[i].type;\n        state.pets[i].x--;\n        state.pets[i].y--;\n    }\n    \n    int M;\n    cin >> M;\n    \n    state.humans.resize(M);\n    for (size_t i = 0; i < (size_t)M; i++) {\n        cin >> state.humans[i].x >> state.humans[i].y;\n        state.humans[i].x--;\n        state.humans[i].y--;\n    }\n    \n    state.turn = 0;\n    state.wall.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (int turn = 0; turn < MAX_TURNS; turn++) {\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2900) {\n            for (size_t i = 0; i < state.humans.size(); i++) {\n                cout << '.';\n            }\n            cout << endl;\n            flush(cout);\n            \n            vector<string> petMoves(N);\n            for (size_t i = 0; i < (size_t)N; i++) {\n                cin >> petMoves[i];\n            }\n            updateState(petMoves, string(state.humans.size(), '.'));\n            continue;\n        }\n        \n        string actions = \"\";\n        for (size_t i = 0; i < state.humans.size(); i++) {\n            char action = decideAction((int)i);\n            \n            if (action >= 'A' && action <= 'Z') {\n                int d = 0;\n                if (action == 'U') d = 0;\n                else if (action == 'D') d = 1;\n                else if (action == 'L') d = 2;\n                else if (action == 'R') d = 3;\n                \n                int nx = state.humans[i].x + dx[d];\n                int ny = state.humans[i].y + dy[d];\n                \n                if (!isValid(nx, ny) || state.wall[nx][ny]) {\n                    action = '.';\n                } else {\n                    bool safe = true;\n                    for (size_t j = 0; j < state.humans.size(); j++) {\n                        if (j == i) continue;\n                        int dist = abs(state.humans[j].x - nx) + abs(state.humans[j].y - ny);\n                        if (dist == 1) {\n                            safe = false;\n                            break;\n                        }\n                    }\n                    if (!safe) action = '.';\n                }\n            }\n            \n            actions += action;\n        }\n        \n        cout << actions << endl;\n        flush(cout);\n        \n        vector<string> petMoves(N);\n        for (size_t i = 0; i < (size_t)N; i++) {\n            cin >> petMoves[i];\n        }\n        \n        updateState(petMoves, actions);\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int INF = 1e9;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    if (!(cin >> si >> sj >> ti >> tj >> p)) return 0;\n\n    vector<string> h(MAX_N);\n    for (int i = 0; i < MAX_N; ++i) {\n        cin >> h[i];\n    }\n\n    vector<string> v(MAX_N - 1);\n    for (int i = 0; i < MAX_N - 1; ++i) {\n        cin >> v[i];\n    }\n\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    char moves[] = {'R', 'L', 'D', 'U'};\n\n    // BFS from target to compute distances\n    vector<vector<int>> dist(MAX_N, vector<int>(MAX_N, INF));\n    queue<pair<int, int>> q;\n\n    dist[ti][tj] = 0;\n    q.push({ti, tj});\n\n    auto can_move = [&](int i, int j, int k) -> bool {\n        int ni = i + di[k];\n        int nj = j + dj[k];\n        if (ni < 0 || ni >= MAX_N || nj < 0 || nj >= MAX_N) return false;\n        if (k == 0) { if (h[i][j] == '1') return false; }\n        else if (k == 1) { if (h[i][j-1] == '1') return false; }\n        else if (k == 2) { if (v[i][j] == '1') return false; }\n        else if (k == 3) { if (v[i-1][j] == '1') return false; }\n        return true;\n    };\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k];\n            int nj = j + dj[k];\n\n            if (can_move(i, j, k) && dist[ni][nj] == INF) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n\n    // Probability distribution\n    vector<vector<double>> prob(MAX_N, vector<double>(MAX_N, 0.0));\n    prob[si][sj] = 1.0;\n    double move_prob = 1.0 - p;\n\n    // Helper function to simulate one move\n    auto simulate_move = [&](const vector<vector<double>>& current_prob, int k) {\n        vector<vector<double>> next_prob(MAX_N, vector<double>(MAX_N, 0.0));\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (current_prob[i][j] < 1e-15) continue;\n                if (i == ti && j == tj) {\n                    next_prob[i][j] += current_prob[i][j];\n                    continue;\n                }\n                if (can_move(i, j, k)) {\n                    int ni = i + di[k];\n                    int nj = j + dj[k];\n                    next_prob[ni][nj] += current_prob[i][j] * move_prob;\n                    next_prob[i][j] += current_prob[i][j] * p;\n                } else {\n                    next_prob[i][j] += current_prob[i][j];\n                }\n            }\n        }\n        return next_prob;\n    };\n\n    // Helper to calculate metrics\n    auto calc_metrics = [&](const vector<vector<double>>& current_prob) -> pair<double, double> {\n        double expected_dist = 0.0;\n        double reach_prob = 0.0;\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (i == ti && j == tj) {\n                    reach_prob += current_prob[i][j];\n                } else if (dist[i][j] != INF) {\n                    expected_dist += current_prob[i][j] * dist[i][j];\n                }\n            }\n        }\n        return {expected_dist, reach_prob};\n    };\n\n    string result = \"\";\n    int last_move = -1;\n    int repeat_count = 0;\n\n    for (int step = 0; step < 200; ++step) {\n        int remaining = 200 - step;\n        int best_move = 0;\n        double best_score = -1e18;\n        vector<vector<double>> best_next_prob;\n\n        // Calculate probability concentration\n        double max_prob = 0.0;\n        vector<pair<double, pair<int, int>>> top_probs;\n        for (int i = 0; i < MAX_N; ++i) {\n            for (int j = 0; j < MAX_N; ++j) {\n                if (prob[i][j] > max_prob) max_prob = prob[i][j];\n                if (prob[i][j] > 1e-10) {\n                    top_probs.push_back({prob[i][j], {i, j}});\n                }\n            }\n        }\n        sort(top_probs.rbegin(), top_probs.rend());\n        double prob_sum_top3 = 0.0;\n        for (int i = 0; i < min(3, (int)top_probs.size()); ++i) {\n            prob_sum_top3 += top_probs[i].first;\n        }\n\n        // Dynamic weight based on remaining steps and concentration\n        double weight;\n        if (remaining <= 50) {\n            // End-game: be more aggressive about reaching target\n            weight = 150.0 + (50.0 - remaining) * 3.0;\n        } else {\n            weight = 80.0 + (200.0 - remaining) * 0.5;\n        }\n\n        // 3-step lookahead for critical decisions\n        for (int k1 = 0; k1 < 4; ++k1) {\n            auto prob_after_1 = simulate_move(prob, k1);\n            auto metrics1 = calc_metrics(prob_after_1);\n            double score1_val = -metrics1.first + weight * metrics1.second;\n\n            // 2-step lookahead\n            double max_score2 = -1e18;\n            for (int k2 = 0; k2 < 4; ++k2) {\n                auto prob_after_2 = simulate_move(prob_after_1, k2);\n                auto metrics2 = calc_metrics(prob_after_2);\n                double score2_val = -metrics2.first + weight * metrics2.second;\n                max_score2 = max(max_score2, score2_val);\n            }\n\n            // 3-step lookahead for concentrated probability\n            double max_score3 = -1e18;\n            if (prob_sum_top3 > 0.5 || remaining <= 70) {\n                for (int k2 = 0; k2 < 4; ++k2) {\n                    auto prob_after_2 = simulate_move(prob_after_1, k2);\n                    for (int k3 = 0; k3 < 4; ++k3) {\n                        auto prob_after_3 = simulate_move(prob_after_2, k3);\n                        auto metrics3 = calc_metrics(prob_after_3);\n                        double score3_val = -metrics3.first + weight * metrics3.second;\n                        max_score3 = max(max_score3, score3_val);\n                    }\n                }\n            }\n\n            // Combined score with adaptive lookahead weight\n            double lookahead_weight = 0.4 + (200.0 - remaining) * 0.002;\n            lookahead_weight = min(lookahead_weight, 0.6);\n            double combined_score = (1.0 - lookahead_weight) * score1_val + lookahead_weight * max_score2;\n            if (max_score3 > -1e17) {\n                combined_score += 0.2 * max_score3;\n            }\n\n            // Bonus for moves that reduce distance from high-probability cells\n            double distance_bonus = 0.0;\n            for (int i = 0; i < MAX_N; ++i) {\n                for (int j = 0; j < MAX_N; ++j) {\n                    if (prob[i][j] > 0.05 && dist[i][j] != INF) {\n                        if (can_move(i, j, k1)) {\n                            int ni = i + di[k1];\n                            int nj = j + dj[k1];\n                            if (dist[ni][nj] < dist[i][j]) {\n                                distance_bonus += prob[i][j] * (dist[i][j] - dist[ni][nj]);\n                            }\n                        }\n                    }\n                }\n            }\n            combined_score += 3.0 * distance_bonus;\n\n            // Move repetition bonus when beneficial\n            if (last_move == k1 && repeat_count > 0) {\n                // Check if repeating this move is beneficial\n                double repeat_benefit = 0.0;\n                for (const auto& tp : top_probs) {\n                    if (tp.first < 0.1) break;\n                    int i = tp.second.first;\n                    int j = tp.second.second;\n                    if (dist[i][j] != INF && can_move(i, j, k1)) {\n                        int ni = i + di[k1];\n                        int nj = j + dj[k1];\n                        if (dist[ni][nj] < dist[i][j]) {\n                            repeat_benefit += tp.first * 2.0;\n                        }\n                    }\n                }\n                if (repeat_benefit > 0.5) {\n                    combined_score += repeat_benefit;\n                }\n            }\n\n            // End-game bonus: prioritize moves that increase reach probability\n            if (remaining <= 50) {\n                double reach_increase = metrics1.second - calc_metrics(prob).second;\n                if (reach_increase > 0) {\n                    combined_score += reach_increase * 100.0;\n                }\n            }\n\n            // Penalty for moves that don't progress when probability is concentrated\n            if (max_prob > 0.4 && prob_sum_top3 > 0.7) {\n                bool progresses = false;\n                for (const auto& tp : top_probs) {\n                    if (tp.first < 0.15) break;\n                    int i = tp.second.first;\n                    int j = tp.second.second;\n                    if (dist[i][j] != INF && can_move(i, j, k1)) {\n                        int ni = i + di[k1];\n                        int nj = j + dj[k1];\n                        if (dist[ni][nj] < dist[i][j]) {\n                            progresses = true;\n                            break;\n                        }\n                    }\n                }\n                if (!progresses) {\n                    combined_score -= 8.0;\n                }\n            }\n\n            if (combined_score > best_score + 1e-9) {\n                best_score = combined_score;\n                best_move = k1;\n                best_next_prob = prob_after_1;\n            }\n        }\n\n        // Track move repetition\n        if (best_move == last_move) {\n            repeat_count++;\n        } else {\n            repeat_count = 1;\n        }\n        last_move = best_move;\n\n        result += moves[best_move];\n        prob = best_next_prob;\n    }\n\n    cout << result << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to table from problem statement\nconst int to[8][4] = {\n    {1, 0, -1, -1}, // 0\n    {3, -1, -1, 0}, // 1\n    {-1, -1, 3, 2}, // 2\n    {-1, 2, 1, -1}, // 3\n    {1, 0, 3, 2},   // 4\n    {3, 2, 1, 0},   // 5\n    {2, -1, 0, -1}, // 6\n    {-1, 3, -1, 1}  // 7\n};\n\nint grid_type[30][30];\nint rot[30][30];\nint best_rot[30][30];\n\n// Visited generation array to avoid memset every time\nint vis_gen[30][30][4];\nint dist[30][30][4];\nint trace_id = 0;\n\nint get_effective_type(int base, int r) {\n    if (base < 4) return (base + r) % 4;\n    if (base == 4) return 4 + (r % 2);\n    if (base == 5) return 5 - (r % 2);\n    if (base == 6) return 6 + (r % 2);\n    if (base == 7) return 7 - (r % 2);\n    return 0;\n}\n\nlong long calc_score(vector<int>& lengths) {\n    lengths.clear();\n    lengths.reserve(900);\n\n    trace_id++;\n    if (trace_id == 0) {\n        memset(vis_gen, 0, sizeof(vis_gen));\n        trace_id = 1;\n    }\n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (vis_gen[i][j][d] == trace_id) continue;\n\n                int cur_i = i, cur_j = j, cur_d = d;\n                int steps = 0;\n                bool cycle_found = false;\n                int cycle_len = 0;\n\n                while (true) {\n                    if (vis_gen[cur_i][cur_j][cur_d] == trace_id) {\n                        cycle_len = steps - dist[cur_i][cur_j][cur_d];\n                        cycle_found = true;\n                        break;\n                    }\n                    if (vis_gen[cur_i][cur_j][cur_d] != 0) {\n                        break;\n                    }\n\n                    vis_gen[cur_i][cur_j][cur_d] = trace_id;\n                    dist[cur_i][cur_j][cur_d] = steps;\n\n                    int t = get_effective_type(grid_type[cur_i][cur_j], rot[cur_i][cur_j]);\n                    int next_d = to[t][cur_d];\n                    if (next_d == -1) break;\n\n                    int next_i = cur_i + di[next_d];\n                    int next_j = cur_j + dj[next_d];\n\n                    if (next_i < 0 || next_i >= 30 || next_j < 0 || next_j >= 30) break;\n\n                    cur_i = next_i;\n                    cur_j = next_j;\n                    cur_d = (next_d + 2) % 4;\n                    steps++;\n                }\n\n                if (cycle_found) {\n                    lengths.push_back(cycle_len);\n                }\n            }\n        }\n    }\n\n    if (lengths.size() < 2) return 0;\n    sort(lengths.rbegin(), lengths.rend());\n    return (long long)lengths[0] * lengths[1];\n}\n\nvoid copy_rot(int src[30][30], int dst[30][30]) {\n    for (int i = 0; i < 30; ++i)\n        for (int j = 0; j < 30; ++j)\n            dst[i][j] = src[i][j];\n}\n\nvoid randomize_rot(mt19937& rng, int rot[30][30]) {\n    uniform_int_distribution<int> dist_rot(0, 3);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            rot[i][j] = dist_rot(rng);\n        }\n    }\n}\n\nvoid solve() {\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            grid_type[i][j] = s[j] - '0';\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_rot(0, 3);\n    uniform_int_distribution<int> dist_idx(0, 29);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    long long best_score = 0;\n    vector<int> lengths;\n\n    auto start_time = chrono::steady_clock::now();\n    auto limit_time = start_time + chrono::seconds(1) + chrono::milliseconds(900);\n\n    // Multi-start with different strategies\n    int num_starts = 0;\n    int max_starts = 20;\n\n    while (chrono::steady_clock::now() < limit_time && num_starts < max_starts) {\n        num_starts++;\n\n        // Randomize rotations\n        randomize_rot(rng, rot);\n\n        // Initial score\n        long long current_score = calc_score(lengths);\n\n        // Local search with simulated annealing\n        double T = 5000.0;\n        int no_improve_count = 0;\n        int max_no_improve = 100000;\n\n        while (chrono::steady_clock::now() < limit_time && no_improve_count < max_no_improve) {\n            // Try single tile flip\n            int r = dist_idx(rng);\n            int c = dist_idx(rng);\n\n            int old_rot = rot[r][c];\n            rot[r][c] = (rot[r][c] + 1) % 4;\n\n            long long new_score = calc_score(lengths);\n\n            // Acceptance criteria\n            bool accept = false;\n            if (new_score > current_score) {\n                accept = true;\n                no_improve_count = 0;\n            } else if (new_score == current_score) {\n                accept = true;\n            } else {\n                double prob = exp((new_score - current_score) / T);\n                if (dist_prob(rng) < prob) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    copy_rot(rot, best_rot);\n                }\n            } else {\n                rot[r][c] = old_rot;\n                no_improve_count++;\n            }\n\n            // Occasionally try larger moves (flip 2-3 tiles)\n            if (no_improve_count % 100 == 0 && dist_prob(rng) < 0.1) {\n                int num_tiles = 2 + (dist_idx(rng) % 2);\n                vector<pair<int,int>> flipped;\n                \n                for (int k = 0; k < num_tiles; ++k) {\n                    int rr = dist_idx(rng);\n                    int cc = dist_idx(rng);\n                    flipped.push_back({rr, cc});\n                }\n                \n                // Apply flips\n                for (auto& p : flipped) {\n                    rot[p.first][p.second] = (rot[p.first][p.second] + 1) % 4;\n                }\n                \n                long long new_score2 = calc_score(lengths);\n                \n                if (new_score2 > current_score) {\n                    current_score = new_score2;\n                    no_improve_count = 0;\n                    if (new_score2 > best_score) {\n                        best_score = new_score2;\n                        copy_rot(rot, best_rot);\n                    }\n                } else {\n                    // Revert\n                    for (auto& p : flipped) {\n                        rot[p.first][p.second] = (rot[p.first][p.second] + 3) % 4;\n                    }\n                }\n            }\n\n            T *= 0.9995;\n            if (T < 1.0) T = 1.0;\n        }\n    }\n\n    // Final output\n    string out = \"\";\n    out.reserve(900);\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            out += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << out << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n\nusing namespace std;\n\nint N, T;\nint board[12][12];\nstring moves;\nint empty_r, empty_c;\nbool solved[12][12];\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dchar[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return 0;\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nvoid apply_move(char move) {\n    int dir = -1;\n    if (move == 'U') dir = 0;\n    else if (move == 'D') dir = 1;\n    else if (move == 'L') dir = 2;\n    else if (move == 'R') dir = 3;\n    \n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    \n    if (!is_valid(nr, nc)) return;\n    \n    int tile = board[nr][nc];\n    board[empty_r][empty_c] = tile;\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    moves += move;\n}\n\n// Simple BFS for empty square movement\nstring bfs_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return \"\";\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\n    \n    char parent_move[12][12];\n    bool visited[12][12];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        visited[i][j] = false;\n        parent_move[i][j] = 0;\n    }\n    \n    visited[empty_r][empty_c] = true;\n    \n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            string path = \"\";\n            int cr = tr, cc = tc;\n            while(cr != empty_r || cc != empty_c) {\n                char m = parent_move[cr][cc];\n                path += m;\n                int dir = -1;\n                if (m == 'U') dir = 0;\n                else if (m == 'D') dir = 1;\n                else if (m == 'L') dir = 2;\n                else if (m == 'R') dir = 3;\n                int rev_dr = -dr[dir];\n                int rev_dc = -dc[dir];\n                cr += rev_dr;\n                cc += rev_dc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (is_valid(nr, nc) && !visited[nr][nc] && !solved[nr][nc]) {\n                visited[nr][nc] = true;\n                parent_move[nr][nc] = dchar[i];\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\";\n}\n\n// Find position of a tile value\npair<int, int> find_tile(int val) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == val) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Place a tile at target position\nvoid place_tile_at(int tr, int tc, int target_val) {\n    // Skip if already correct\n    if (board[tr][tc] == target_val) {\n        solved[tr][tc] = true;\n        return;\n    }\n    \n    // Find where the target tile is\n    auto pos = find_tile(target_val);\n    int fr = pos.first, fc = pos.second;\n    \n    if (fr == -1) return; // Should not happen\n    \n    // Move tile from (fr, fc) to (tr, tc)\n    while (fr != tr || fc != tc) {\n        // Find best direction to move tile towards target\n        int best_dir = -1;\n        int best_dist = 1e9;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = fr + dr[i];\n            int nc = fc + dc[i];\n            if (is_valid(nr, nc) && !solved[nr][nc]) {\n                int dist = abs(nr - tr) + abs(nc - tc);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_dir = i;\n                }\n            }\n        }\n        \n        if (best_dir == -1) {\n            // Try any unsolved neighbor\n            for (int i = 0; i < 4; ++i) {\n                int nr = fr + dr[i];\n                int nc = fc + dc[i];\n                if (is_valid(nr, nc) && !solved[nr][nc]) {\n                    best_dir = i;\n                    break;\n                }\n            }\n        }\n        \n        if (best_dir == -1) break;\n        \n        int nr = fr + dr[best_dir];\n        int nc = fc + dc[best_dir];\n        \n        // Move empty square to (nr, nc)\n        string path = bfs_to(nr, nc);\n        for (char m : path) apply_move(m);\n        \n        // Move tile to (nr, nc)\n        int reverse_dir = (best_dir + 2) % 4;\n        apply_move(dchar[reverse_dir]);\n        \n        // Update tile position\n        fr = nr;\n        fc = nc;\n        \n        // Check move limit\n        if (moves.size() > T) {\n            cout << moves << endl;\n            exit(0);\n        }\n    }\n    solved[tr][tc] = true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T)) return 0;\n    \n    vector<string> input_board(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> input_board[i];\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(input_board[i][j]);\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    // Initialize solved array\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            solved[i][j] = false;\n    \n    // Strategy: Place tiles in order, but skip the last cell (empty square)\n    // We'll create a simple pattern that should work\n    \n    // Count available tiles\n    int counts[16] = {0};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] != 0) {\n                counts[board[i][j]]++;\n            }\n        }\n    }\n    \n    // Create target configuration (simple row-by-row placement)\n    int target[12][12];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            target[i][j] = -1;\n        }\n    }\n    \n    // Fill target with available tiles (skip last cell for empty square)\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) {\n                target[i][j] = 0; // Empty square\n            } else {\n                // Find next available tile\n                for (int t = 1; t <= 15; ++t) {\n                    if (counts[t] > 0) {\n                        target[i][j] = t;\n                        counts[t]--;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Solve puzzle\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == N - 1 && j == N - 1) continue; // Skip empty square\n            \n            int target_val = target[i][j];\n            if (target_val == -1) continue;\n            \n            place_tile_at(i, j, target_val);\n            \n            if (moves.size() > T) {\n                cout << moves << endl;\n                return 0;\n            }\n        }\n    }\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <unordered_map>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\n// Cross product to determine which side of line a point is on\nint point_side(const Line& line, const Point& p) {\n    long long dx = line.qx - line.px;\n    long long dy = line.qy - line.py;\n    long long px = p.x - line.px;\n    long long py = p.y - line.py;\n    long long cp = dx * py - dy * px;\n    if (cp > 0) return 1;\n    if (cp < 0) return -1;\n    return 0;\n}\n\n// Calculate score - optimized version\nint calculate_score(const vector<Point>& strawberries, \n                    const vector<Line>& cuts, \n                    const vector<int>& a) {\n    int n = strawberries.size();\n    int k = cuts.size();\n    \n    if (k == 0) {\n        int count = n;\n        if (count >= 1 && count <= 10) {\n            int total_attendees = 0;\n            for (int d = 1; d <= 10; d++) total_attendees += a[d];\n            if (total_attendees == 0) return 0;\n            int distributed = min(a[count], 1);\n            return round(1e6 * distributed / total_attendees);\n        }\n        return 0;\n    }\n    \n    // For each strawberry, determine its region (bitmask of which side of each cut)\n    vector<int> region(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < k; j++) {\n            int side = point_side(cuts[j], strawberries[i]);\n            if (side == 1) {\n                region[i] |= (1 << j);\n            }\n        }\n    }\n    \n    // Count strawberries in each region\n    unordered_map<int, int> region_count;\n    region_count.reserve(1 << min(k, 20));\n    for (int i = 0; i < n; i++) {\n        region_count[region[i]]++;\n    }\n    \n    // Calculate score\n    int total_attendees = 0;\n    for (int d = 1; d <= 10; d++) {\n        total_attendees += a[d];\n    }\n    \n    if (total_attendees == 0) return 0;\n    \n    // Count pieces with each number of strawberries\n    vector<int> b(11, 0);\n    for (const auto& [region_id, count] : region_count) {\n        if (count >= 1 && count <= 10) {\n            b[count]++;\n        }\n    }\n    \n    int distributed = 0;\n    for (int d = 1; d <= 10; d++) {\n        distributed += min(a[d], b[d]);\n    }\n    \n    return round(1e6 * distributed / total_attendees);\n}\n\n// Generate a random line\nLine generate_random_line(mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    line.px = dist(gen);\n    line.py = dist(gen);\n    line.qx = dist(gen);\n    line.qy = dist(gen);\n    \n    while (line.px == line.qx && line.py == line.qy) {\n        line.qx = dist(gen);\n        line.qy = dist(gen);\n    }\n    \n    return line;\n}\n\n// Generate a line that passes between two strawberries\nLine generate_separating_line(const Point& p1, const Point& p2, \n                              mt19937& gen, uniform_int_distribution<long long>& dist) {\n    Line line;\n    \n    long long dx = p2.x - p1.x;\n    long long dy = p2.y - p1.y;\n    \n    long long mx = (p1.x + p2.x) / 2;\n    long long my = (p1.y + p2.y) / 2;\n    \n    long long pdx = -dy;\n    long long pdy = dx;\n    \n    long long offset_x = dist(gen) % 100000 - 50000;\n    long long offset_y = dist(gen) % 100000 - 50000;\n    \n    line.px = mx + pdx + offset_x;\n    line.py = my + pdy + offset_y;\n    line.qx = mx - pdx + offset_x;\n    line.qy = my - pdy + offset_y;\n    \n    return line;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(11);\n    for (int i = 1; i <= 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<long long> dist(-1000000000, 1000000000);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = start_time + chrono::milliseconds(2900);\n    \n    vector<Line> best_cuts;\n    int best_score = 0;\n    \n    // Multiple restart strategy - restored 8.97M parameters\n    int num_restarts = 16;\n    int restarts_done = 0;\n    \n    while (restarts_done < num_restarts && chrono::steady_clock::now() < time_limit) {\n        restarts_done++;\n        vector<Line> cuts;\n        \n        // Phase 1: Generate initial cuts (pure random)\n        int initial_cuts = min(K, 6);\n        for (int i = 0; i < initial_cuts; i++) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            cuts.push_back(generate_random_line(gen, dist));\n        }\n        \n        // Phase 2: Iterative improvement (restored 8.97M parameters)\n        int max_iterations = 450;\n        int iteration = 0;\n        int no_improve_count = 0;\n        \n        while (iteration < max_iterations && \n               chrono::steady_clock::now() < time_limit && \n               no_improve_count < 180) {\n            iteration++;\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            Line best_new_cut;\n            int best_new_score = old_score;\n            int best_idx = -1;\n            bool should_add = false;\n            \n            // Try adding a cut (only if we haven't reached K)\n            if ((int)cuts.size() < K) {\n                for (int trial = 0; trial < 17; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    Line new_cut;\n                    if (gen() % 2 == 0 && N >= 2) {\n                        int i1 = gen() % N;\n                        int i2 = gen() % N;\n                        while (i2 == i1) i2 = gen() % N;\n                        new_cut = generate_separating_line(strawberries[i1], strawberries[i2], gen, dist);\n                    } else {\n                        new_cut = generate_random_line(gen, dist);\n                    }\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts.push_back(new_cut);\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = -1;\n                        should_add = true;\n                    }\n                }\n            }\n            \n            // Try replacing a cut\n            if ((int)cuts.size() >= 1) {\n                for (int trial = 0; trial < 12; trial++) {\n                    if (chrono::steady_clock::now() > time_limit) break;\n                    \n                    int idx = gen() % cuts.size();\n                    Line new_cut = generate_random_line(gen, dist);\n                    \n                    vector<Line> test_cuts = cuts;\n                    test_cuts[idx] = new_cut;\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > best_new_score) {\n                        best_new_score = new_score;\n                        best_new_cut = new_cut;\n                        best_idx = idx;\n                        should_add = false;\n                    }\n                }\n            }\n            \n            // Apply best improvement (pure greedy)\n            if (best_new_score > old_score) {\n                no_improve_count = 0;\n                if (should_add) {\n                    cuts.push_back(best_new_cut);\n                } else if (best_idx >= 0) {\n                    cuts[best_idx] = best_new_cut;\n                }\n            } else {\n                no_improve_count++;\n            }\n        }\n        \n        // Phase 3: Remove unnecessary cuts\n        for (int i = (int)cuts.size() - 1; i >= 0; i--) {\n            if (chrono::steady_clock::now() > time_limit) break;\n            \n            vector<Line> test_cuts = cuts;\n            test_cuts.erase(test_cuts.begin() + i);\n            \n            int old_score = calculate_score(strawberries, cuts, a);\n            int new_score = calculate_score(strawberries, test_cuts, a);\n            \n            if (new_score >= old_score) {\n                cuts = test_cuts;\n            }\n        }\n        \n        // Phase 4: Fine-tuning (slightly more iterations)\n        for (int iter = 0; iter < 48 && chrono::steady_clock::now() < time_limit; iter++) {\n            int old_score = calculate_score(strawberries, cuts, a);\n            \n            for (int i = 0; i < (int)cuts.size(); i++) {\n                if (chrono::steady_clock::now() > time_limit) break;\n                \n                Line perturbed = cuts[i];\n                perturbed.px += dist(gen) % 10000 - 5000;\n                perturbed.py += dist(gen) % 10000 - 5000;\n                perturbed.qx += dist(gen) % 10000 - 5000;\n                perturbed.qy += dist(gen) % 10000 - 5000;\n                \n                vector<Line> test_cuts = cuts;\n                test_cuts[i] = perturbed;\n                \n                int new_score = calculate_score(strawberries, test_cuts, a);\n                \n                if (new_score > old_score) {\n                    cuts = test_cuts;\n                    old_score = new_score;\n                }\n            }\n        }\n        \n        // Ensure we never exceed K cuts\n        while ((int)cuts.size() > K) {\n            cuts.pop_back();\n        }\n        \n        // Update best solution\n        int current_score = calculate_score(strawberries, cuts, a);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_cuts = cuts;\n        }\n    }\n    \n    // Phase 5: Final polish on best solution\n    if (!best_cuts.empty() && chrono::steady_clock::now() < time_limit) {\n        auto polish_time = chrono::steady_clock::now() + chrono::milliseconds(150);\n        \n        while (chrono::steady_clock::now() < polish_time) {\n            int old_score = calculate_score(strawberries, best_cuts, a);\n            bool improved = false;\n            \n            // Try perturbations\n            for (int i = 0; i < (int)best_cuts.size(); i++) {\n                for (int trial = 0; trial < 5; trial++) {\n                    Line perturbed = best_cuts[i];\n                    perturbed.px += dist(gen) % 5000 - 2500;\n                    perturbed.py += dist(gen) % 5000 - 2500;\n                    perturbed.qx += dist(gen) % 5000 - 2500;\n                    perturbed.qy += dist(gen) % 5000 - 2500;\n                    \n                    vector<Line> test_cuts = best_cuts;\n                    test_cuts[i] = perturbed;\n                    \n                    int new_score = calculate_score(strawberries, test_cuts, a);\n                    \n                    if (new_score > old_score) {\n                        best_cuts = test_cuts;\n                        old_score = new_score;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Final safety check\n    while ((int)best_cuts.size() > K) {\n        best_cuts.pop_back();\n    }\n    \n    // Output\n    cout << best_cuts.size() << endl;\n    for (const auto& cut : best_cuts) {\n        cout << cut.px << \" \" << cut.py << \" \" << cut.qx << \" \" << cut.qy << endl;\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <unordered_set>\n#include <unordered_map>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct Edge {\n    int x1, y1, x2, y2;\n    int type; // 0: horizontal, 1: vertical, 2: diagonal +1, 3: diagonal -1\n    \n    bool operator<(const Edge& other) const {\n        if (type != other.type) return type < other.type;\n        if (x1 != other.x1) return x1 < other.x1;\n        if (y1 != other.y1) return y1 < other.y1;\n        if (x2 != other.x2) return x2 < other.x2;\n        return y2 < other.y2;\n    }\n};\n\nstruct Operation {\n    Point p1, p2, p3, p4;\n    double score;\n};\n\nclass RectJoinSolver {\nprivate:\n    int N, M;\n    unordered_set<long long> dots;\n    // Group edges by type and line for faster collision detection\n    unordered_map<int, vector<Edge>> horizontalEdges;  // type 0, key = y\n    unordered_map<int, vector<Edge>> verticalEdges;    // type 1, key = x\n    unordered_map<int, vector<Edge>> diagPlusEdges;    // type 2, key = y-x\n    unordered_map<int, vector<Edge>> diagMinusEdges;   // type 3, key = y+x\n    vector<Operation> operations;\n    vector<Point> dotList;\n    int cx, cy;\n    \n    double weight(int x, int y) const {\n        return (double)(x - cx) * (x - cx) + (double)(y - cy) * (y - cy) + 1.0;\n    }\n    \n    bool inGrid(int x, int y) const {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    }\n    \n    bool hasDot(int x, int y) const {\n        return dots.count(((long long)x << 32) | (unsigned int)y) > 0;\n    }\n    \n    Edge normalizeEdge(int x1, int y1, int x2, int y2) const {\n        int dx = x2 - x1, dy = y2 - y1;\n        int type = -1;\n        \n        if (dx == 0) type = 1;\n        else if (dy == 0) type = 0;\n        else if (abs(dx) == abs(dy)) {\n            type = (dx == dy) ? 2 : 3;\n        }\n        \n        if (x1 < x2 || (x1 == x2 && y1 < y2)) {\n            return {x1, y1, x2, y2, type};\n        }\n        return {x2, y2, x1, y1, type};\n    }\n    \n    void addEdge(int x1, int y1, int x2, int y2) {\n        Edge e = normalizeEdge(x1, y1, x2, y2);\n        if (e.type == 0) horizontalEdges[e.y1].push_back(e);\n        else if (e.type == 1) verticalEdges[e.x1].push_back(e);\n        else if (e.type == 2) diagPlusEdges[e.y1 - e.x1].push_back(e);\n        else if (e.type == 3) diagMinusEdges[e.y1 + e.x1].push_back(e);\n    }\n    \n    bool edgesOverlap(const Edge& e1, const Edge& e2) const {\n        if (e1.type != e2.type || e1.type == -1) return false;\n        \n        if (e1.type == 0) { // horizontal\n            if (e1.y1 != e2.y1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        if (e1.type == 1) { // vertical\n            if (e1.x1 != e2.x1) return false;\n            int yMin1 = min(e1.y1, e1.y2), yMax1 = max(e1.y1, e1.y2);\n            int yMin2 = min(e2.y1, e2.y2), yMax2 = max(e2.y1, e2.y2);\n            return max(yMin1, yMin2) < min(yMax1, yMax2);\n        }\n        if (e1.type == 2) { // diagonal +1\n            if (e1.y1 - e1.x1 != e2.y1 - e2.x1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        if (e1.type == 3) { // diagonal -1\n            if (e1.y1 + e1.x1 != e2.y1 + e2.x1) return false;\n            int xMin1 = min(e1.x1, e1.x2), xMax1 = max(e1.x1, e1.x2);\n            int xMin2 = min(e2.x1, e2.x2), xMax2 = max(e2.x1, e2.x2);\n            return max(xMin1, xMin2) < min(xMax1, xMax2);\n        }\n        return false;\n    }\n    \n    bool rectangleOverlaps(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const {\n        Edge edges[4] = {\n            normalizeEdge(x1, y1, x2, y2),\n            normalizeEdge(x2, y2, x3, y3),\n            normalizeEdge(x3, y3, x4, y4),\n            normalizeEdge(x4, y4, x1, y1)\n        };\n        \n        for (int i = 0; i < 4; i++) {\n            if (edges[i].type == -1) return true;\n            \n            // Check only edges on the same line using find() instead of operator[]\n            if (edges[i].type == 0) {\n                auto it = horizontalEdges.find(edges[i].y1);\n                if (it != horizontalEdges.end()) {\n                    for (const auto& existing : it->second) {\n                        if (edgesOverlap(edges[i], existing)) return true;\n                    }\n                }\n            } else if (edges[i].type == 1) {\n                auto it = verticalEdges.find(edges[i].x1);\n                if (it != verticalEdges.end()) {\n                    for (const auto& existing : it->second) {\n                        if (edgesOverlap(edges[i], existing)) return true;\n                    }\n                }\n            } else if (edges[i].type == 2) {\n                auto it = diagPlusEdges.find(edges[i].y1 - edges[i].x1);\n                if (it != diagPlusEdges.end()) {\n                    for (const auto& existing : it->second) {\n                        if (edgesOverlap(edges[i], existing)) return true;\n                    }\n                }\n            } else if (edges[i].type == 3) {\n                auto it = diagMinusEdges.find(edges[i].y1 + edges[i].x1);\n                if (it != diagMinusEdges.end()) {\n                    for (const auto& existing : it->second) {\n                        if (edgesOverlap(edges[i], existing)) return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    bool hasDotsOnPerimeter(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,\n                           const Point& p2, const Point& p3, const Point& p4) const {\n        auto checkEdge = [&](int x1, int y1, int x2, int y2) {\n            int dx = x2 - x1, dy = y2 - y1;\n            int steps = max(abs(dx), abs(dy));\n            for (int i = 1; i < steps; i++) {\n                int x = x1 + dx * i / steps;\n                int y = y1 + dy * i / steps;\n                if ((x == p2.x && y == p2.y) || (x == p3.x && y == p3.y) || \n                    (x == p4.x && y == p4.y)) continue;\n                if (hasDot(x, y)) return true;\n            }\n            return false;\n        };\n        \n        return checkEdge(x1, y1, x2, y2) ||\n               checkEdge(x2, y2, x3, y3) ||\n               checkEdge(x3, y3, x4, y4) ||\n               checkEdge(x4, y4, x1, y1);\n    }\n    \n    bool isValidRectangle(const Point& p1, const Point& p2, const Point& p3, const Point& p4) const {\n        int dx23 = p3.x - p2.x, dy23 = p3.y - p2.y;\n        int dx34 = p4.x - p3.x, dy34 = p4.y - p3.y;\n        int dx41 = p1.x - p4.x, dy41 = p1.y - p4.y;\n        int dx12 = p2.x - p1.x, dy12 = p2.y - p1.y;\n        \n        if (dx23 * dx34 + dy23 * dy34 != 0) return false;\n        if (dx23 != -dx41 || dy23 != -dy41) return false;\n        if (dx34 != -dx12 || dy34 != -dy12) return false;\n        \n        bool axisAligned = (dx23 == 0 || dy23 == 0) && (dx34 == 0 || dy34 == 0);\n        bool diagonal45 = (abs(dx23) == abs(dy23) && abs(dx34) == abs(dy34));\n        \n        if (axisAligned) {\n            if (!((dx23 == 0 || dy23 == 0) && (dx34 == 0 || dy34 == 0) &&\n                  (dx41 == 0 || dy41 == 0) && (dx12 == 0 || dy12 == 0))) {\n                return false;\n            }\n        } else if (diagonal45) {\n            if (!((abs(dx23) == abs(dy23)) && (abs(dx34) == abs(dy34)) &&\n                  (abs(dx41) == abs(dy41)) && (abs(dx12) == abs(dy12)))) {\n                return false;\n            }\n        } else {\n            return false;\n        }\n        \n        return true;\n    }\n    \n    vector<Operation> findValidMoves() {\n        vector<Operation> validMoves;\n        int nDots = dotList.size();\n        \n        for (int i = 0; i < nDots; i++) {\n            for (int j = i + 1; j < nDots; j++) {\n                Point p2 = dotList[i];\n                Point p3 = dotList[j];\n                \n                int dx = p3.x - p2.x, dy = p3.y - p2.y;\n                \n                for (int dir = -1; dir <= 1; dir += 2) {\n                    int perpDx = -dir * dy;\n                    int perpDy = dir * dx;\n                    \n                    for (int len = 1; len <= N; len++) {\n                        int p4x = p3.x + perpDx * len;\n                        int p4y = p3.y + perpDy * len;\n                        \n                        if (!inGrid(p4x, p4y)) break;\n                        if (!hasDot(p4x, p4y)) continue;\n                        \n                        int p1x = p2.x + perpDx * len;\n                        int p1y = p2.y + perpDy * len;\n                        \n                        if (!inGrid(p1x, p1y)) continue;\n                        if (hasDot(p1x, p1y)) continue;\n                        \n                        Point p1 = {p1x, p1y};\n                        Point p4 = {p4x, p4y};\n                        \n                        if (!isValidRectangle(p1, p2, p3, p4)) continue;\n                        \n                        if (rectangleOverlaps(p1x, p1y, p2.x, p2.y, p3.x, p3.y, p4x, p4y)) continue;\n                        \n                        if (hasDotsOnPerimeter(p1x, p1y, p2.x, p2.y, p3.x, p3.y, p4x, p4y,\n                                             p2, p3, p4)) continue;\n                        \n                        Operation op;\n                        op.p1 = p1;\n                        op.p2 = p2;\n                        op.p3 = p3;\n                        op.p4 = p4;\n                        op.score = weight(p1x, p1y);\n                        \n                        validMoves.push_back(op);\n                    }\n                }\n            }\n        }\n        \n        return validMoves;\n    }\n    \n    void executeMove(const Operation& op) {\n        dots.insert(((long long)op.p1.x << 32) | (unsigned int)op.p1.y);\n        dotList.push_back(op.p1);\n        addEdge(op.p1.x, op.p1.y, op.p2.x, op.p2.y);\n        addEdge(op.p2.x, op.p2.y, op.p3.x, op.p3.y);\n        addEdge(op.p3.x, op.p3.y, op.p4.x, op.p4.y);\n        addEdge(op.p4.x, op.p4.y, op.p1.x, op.p1.y);\n        operations.push_back(op);\n    }\n    \npublic:\n    RectJoinSolver(int n, int m, const vector<pair<int,int>>& initial) {\n        N = n; M = m;\n        cx = (N - 1) / 2;\n        cy = (N - 1) / 2;\n        \n        for (const auto& p : initial) {\n            dots.insert(((long long)p.first << 32) | (unsigned int)p.second);\n            dotList.push_back({p.first, p.second});\n        }\n    }\n    \n    void solve() {\n        auto startTime = chrono::steady_clock::now();\n        \n        int iteration = 0;\n        const int maxIterations = 9500;\n        \n        while (iteration < maxIterations) {\n            auto currentTime = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n            if (elapsed >= 4970) break;\n            \n            vector<Operation> moves = findValidMoves();\n            \n            if (moves.empty()) break;\n            \n            sort(moves.begin(), moves.end(), [](const Operation& a, const Operation& b) {\n                return a.score > b.score;\n            });\n            \n            executeMove(moves[0]);\n            iteration++;\n        }\n    }\n    \n    void output() const {\n        cout << operations.size() << endl;\n        for (const auto& op : operations) {\n            cout << op.p1.x << \" \" << op.p1.y << \" \"\n                 << op.p2.x << \" \" << op.p2.y << \" \"\n                 << op.p3.x << \" \" << op.p3.y << \" \"\n                 << op.p4.x << \" \" << op.p4.y << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    \n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initial[i].first >> initial[i].second;\n    }\n    \n    RectJoinSolver solver(N, M, initial);\n    solver.solve();\n    solver.output();\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Board representation: 10x10 grid, 0=empty, 1-3=flavors\nstruct Board {\n    int grid[10][10];\n    \n    Board() {\n        for(int i = 0; i < 10; i++)\n            for(int j = 0; j < 10; j++)\n                grid[i][j] = 0;\n    }\n};\n\n// Count connected components and calculate score\nlong long calculateScore(const Board& b) {\n    int visited[10][10];\n    for(int i = 0; i < 10; i++)\n        for(int j = 0; j < 10; j++)\n            visited[i][j] = 0;\n    \n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n    \n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] != 0 && !visited[i][j]) {\n                // BFS for connected component\n                int flavor = b.grid[i][j];\n                int size = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = 1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    size++;\n                    \n                    for(int d = 0; d < 4; d++) {\n                        int nr = r + dr[d];\n                        int nc = c + dc[d];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10) {\n                            if(!visited[nr][nc] && b.grid[nr][nc] == flavor) {\n                                visited[nr][nc] = 1;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Tilt board in given direction\nvoid tilt(Board& b, char dir) {\n    Board newb = b;\n    \n    if(dir == 'F') { // Forward (up)\n        for(int j = 0; j < 10; j++) {\n            int write = 0;\n            for(int i = 0; i < 10; i++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int i = write; i < 10; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'B') { // Backward (down)\n        for(int j = 0; j < 10; j++) {\n            int write = 9;\n            for(int i = 9; i >= 0; i--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[write][j] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int i = 0; i < write; i++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'L') { // Left\n        for(int i = 0; i < 10; i++) {\n            int write = 0;\n            for(int j = 0; j < 10; j++) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write++;\n                }\n            }\n            for(int j = write; j < 10; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    } else if(dir == 'R') { // Right\n        for(int i = 0; i < 10; i++) {\n            int write = 9;\n            for(int j = 9; j >= 0; j--) {\n                if(b.grid[i][j] != 0) {\n                    newb.grid[i][write] = b.grid[i][j];\n                    write--;\n                }\n            }\n            for(int j = 0; j < write; j++) {\n                newb.grid[i][j] = 0;\n            }\n        }\n    }\n    \n    b = newb;\n}\n\n// Count candies of each flavor\nvoid countFlavors(const Board& b, int& f1, int& f2, int& f3) {\n    f1 = f2 = f3 = 0;\n    for(int i = 0; i < 10; i++) {\n        for(int j = 0; j < 10; j++) {\n            if(b.grid[i][j] == 1) f1++;\n            else if(b.grid[i][j] == 2) f2++;\n            else if(b.grid[i][j] == 3) f3++;\n        }\n    }\n}\n\n// Calculate normalized score\ndouble getNormalizedScore(const Board& b) {\n    int f1, f2, f3;\n    countFlavors(b, f1, f2, f3);\n    long long numerator = calculateScore(b);\n    long long denominator = (long long)f1*f1 + (long long)f2*f2 + (long long)f3*f3;\n    if(denominator == 0) return 0;\n    return (double)numerator / denominator;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read all flavors in advance\n    vector<int> flavors(100);\n    for(int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    Board board;\n    char directions[] = {'F', 'B', 'L', 'R'};\n    \n    // Process each candy placement\n    for(int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Place candy in p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int count = 0;\n        for(int i = 0; i < 10; i++) {\n            for(int j = 0; j < 10; j++) {\n                if(board.grid[i][j] == 0) {\n                    count++;\n                    if(count == p) {\n                        board.grid[i][j] = flavors[t];\n                        break;\n                    }\n                }\n                if(count == p) break;\n            }\n            if(count == p) break;\n        }\n        \n        // Skip output for last step (nothing happens)\n        if(t == 99) {\n            cout << \"F\" << endl;\n            continue;\n        }\n        \n        // Try all 4 directions and pick the best\n        double bestScore = -1;\n        char bestDir = 'F';\n        \n        for(char dir : directions) {\n            Board temp = board;\n            tilt(temp, dir);\n            double score = getNormalizedScore(temp);\n            \n            if(score > bestScore) {\n                bestScore = score;\n                bestDir = dir;\n            }\n        }\n        \n        // Apply the best direction\n        tilt(board, bestDir);\n        cout << bestDir << endl;\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <bitset>\n\nusing namespace std;\n\nconst int MAX_N = 100;\n\nstruct Graph {\n    int n;\n    vector<bitset<MAX_N>> adj;\n\n    Graph(int n = 0) : n(n), adj(n) {}\n\n    static Graph from_string(int n, const string& s) {\n        Graph g(n);\n        size_t idx = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (idx < s.size()) {\n                    if (s[idx] == '1') {\n                        g.adj[i][j] = 1;\n                        g.adj[j][i] = 1;\n                    }\n                }\n                idx++;\n            }\n        }\n        return g;\n    }\n\n    string to_string() const {\n        string s;\n        s.reserve(n * (n - 1) / 2);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                s += (adj[i][j] ? '1' : '0');\n            }\n        }\n        return s;\n    }\n\n    int edge_count() const {\n        int cnt = 0;\n        for (int i = 0; i < n; ++i) cnt += adj[i].count();\n        return cnt / 2;\n    }\n\n    static Graph random(int n, double p, mt19937& gen) {\n        Graph g(n);\n        uniform_real_distribution<double> dist(0.0, 1.0);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (dist(gen) < p) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                }\n            }\n        }\n        return g;\n    }\n\n    static Graph complete(int n) {\n        Graph g(n);\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                g.adj[i][j] = 1;\n                g.adj[j][i] = 1;\n            }\n        }\n        return g;\n    }\n\n    static Graph empty(int n) {\n        return Graph(n);\n    }\n\n    static Graph path(int n) {\n        Graph g(n);\n        for (int i = 0; i < n - 1; ++i) {\n            g.adj[i][i + 1] = 1;\n            g.adj[i + 1][i] = 1;\n        }\n        return g;\n    }\n\n    static Graph cycle(int n) {\n        Graph g(n);\n        for (int i = 0; i < n - 1; ++i) {\n            g.adj[i][i + 1] = 1;\n            g.adj[i + 1][i] = 1;\n        }\n        if (n > 2) {\n            g.adj[0][n - 1] = 1;\n            g.adj[n - 1][0] = 1;\n        }\n        return g;\n    }\n\n    static Graph star(int n) {\n        Graph g(n);\n        for (int i = 1; i < n; ++i) {\n            g.adj[0][i] = 1;\n            g.adj[i][0] = 1;\n        }\n        return g;\n    }\n};\n\nstruct Features {\n    double edge_count;\n    vector<double> sorted_degrees;\n    double sum_sq_deg;\n    double triangle_count;\n\n    Features() : edge_count(0), sum_sq_deg(0), triangle_count(0) {}\n    \n    Features(int n) : edge_count(0), sum_sq_deg(0), triangle_count(0) {\n        sorted_degrees.resize(n);\n    }\n};\n\nFeatures compute_features(const Graph& g) {\n    Features f;\n    f.sorted_degrees.resize(g.n);\n    \n    for (int i = 0; i < g.n; ++i) {\n        f.sorted_degrees[i] = (double)g.adj[i].count();\n        f.sum_sq_deg += f.sorted_degrees[i] * f.sorted_degrees[i];\n    }\n    f.edge_count = g.edge_count();\n    \n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    // Count triangles\n    for (int i = 0; i < g.n; ++i) {\n        for (int j = i + 1; j < g.n; ++j) {\n            if (g.adj[i][j]) {\n                for (int k = j + 1; k < g.n; ++k) {\n                    if (g.adj[i][k] && g.adj[j][k]) {\n                        f.triangle_count++;\n                    }\n                }\n            }\n        }\n    }\n    return f;\n}\n\n// Use theoretical expected features (much faster than simulation)\nFeatures compute_expected_features(const Graph& g, double eps) {\n    Features f;\n    int n = g.n;\n    int total_edges = n * (n - 1) / 2;\n    f.sorted_degrees.resize(n);\n\n    long long e_g = 0;\n    for(int i=0; i<n; ++i) e_g += g.adj[i].count();\n    e_g /= 2;\n    f.edge_count = e_g * (1.0 - 2.0 * eps) + total_edges * eps;\n\n    for (int i = 0; i < n; ++i) {\n        double d_i = (double)g.adj[i].count();\n        f.sorted_degrees[i] = d_i * (1.0 - 2.0 * eps) + (n - 1) * eps;\n    }\n    sort(f.sorted_degrees.begin(), f.sorted_degrees.end());\n\n    double var_deg = (n - 1) * eps * (1.0 - eps);\n    for (int i = 0; i < n; ++i) {\n        double mean_d = f.sorted_degrees[i];\n        f.sum_sq_deg += var_deg + mean_d * mean_d;\n    }\n\n    double p0 = pow(eps, 3);\n    double p1 = pow(eps, 2) * (1.0 - eps);\n    double p2 = eps * pow(1.0 - eps, 2);\n    double p3 = pow(1.0 - eps, 3);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            for (int k = j + 1; k < n; ++k) {\n                int edges = 0;\n                if (g.adj[i][j]) edges++;\n                if (g.adj[i][k]) edges++;\n                if (g.adj[j][k]) edges++;\n                if (edges == 0) f.triangle_count += p0;\n                else if (edges == 1) f.triangle_count += p1;\n                else if (edges == 2) f.triangle_count += p2;\n                else f.triangle_count += p3;\n            }\n        }\n    }\n\n    return f;\n}\n\ndouble feature_distance(const Features& f1, const Features& f2, double eps) {\n    double dist = 0.0;\n    \n    double s_ec = 1.0 / (eps * 100.0 + 1.0);\n    double s_sq = 1.0 / (eps * 1000.0 + 10.0);\n    double s_tc = 1.0 / (eps * 500.0 + 10.0);\n    double s_deg = 1.0 / (eps * 50.0 + 10.0);\n\n    dist += s_ec * (f1.edge_count - f2.edge_count) * (f1.edge_count - f2.edge_count);\n    dist += s_sq * (f1.sum_sq_deg - f2.sum_sq_deg) * (f1.sum_sq_deg - f2.sum_sq_deg);\n    dist += s_tc * (f1.triangle_count - f2.triangle_count) * (f1.triangle_count - f2.triangle_count);\n    \n    for (size_t i = 0; i < f1.sorted_degrees.size(); ++i) {\n        dist += s_deg * (f1.sorted_degrees[i] - f2.sorted_degrees[i]) * \n                (f1.sorted_degrees[i] - f2.sorted_degrees[i]);\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n    int best_N = 40;\n    vector<Graph> best_Gs;\n    vector<Features> best_ExpectedFeatures;\n    double best_score = -1.0;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 4.0;\n\n    // Adaptive N selection based on M\n    vector<int> N_candidates;\n    if (M <= 15) {\n        N_candidates = {20, 30};\n    } else if (M <= 30) {\n        N_candidates = {30, 40};\n    } else if (M <= 50) {\n        N_candidates = {40, 50, 60};\n    } else {\n        N_candidates = {50, 60, 70};\n    }\n\n    for (int N : N_candidates) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        int pool_size = min(100, M * 2);\n        vector<Graph> candidates;\n        candidates.reserve(pool_size + 10);\n        \n        // Add structured graphs\n        candidates.push_back(Graph::empty(N));\n        candidates.push_back(Graph::complete(N));\n        candidates.push_back(Graph::path(N));\n        candidates.push_back(Graph::cycle(N));\n        candidates.push_back(Graph::star(N));\n\n        // Add graphs with different edge counts\n        int total_edges = N * (N - 1) / 2;\n        for (int i = 1; i < M * 2 && i < total_edges; i += max(1, total_edges / (M * 2))) {\n            Graph g(N);\n            int edges_added = 0;\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            for (int u = 0; u < N && edges_added < i; ++u) {\n                for (int v = u + 1; v < N && edges_added < i; ++v) {\n                    if (dist(gen) < 0.5) {\n                        g.adj[u][v] = 1;\n                        g.adj[v][u] = 1;\n                        edges_added++;\n                    }\n                }\n            }\n            candidates.push_back(g);\n        }\n\n        // Add random graphs\n        for (int i = 0; i < pool_size; ++i) {\n            double p = (double)rand() / RAND_MAX;\n            candidates.push_back(Graph::random(N, p, gen));\n        }\n\n        // Compute expected features (theoretical, fast!)\n        vector<Features> cand_expected;\n        cand_expected.reserve(candidates.size());\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            cand_expected.push_back(compute_expected_features(candidates[i], eps));\n        }\n\n        // Greedy selection to maximize minimum distance\n        vector<int> selected_indices;\n        selected_indices.reserve(M);\n        selected_indices.push_back(0);\n        \n        for (int i = 1; i < M; ++i) {\n            int best_idx = -1;\n            double max_min_dist = -1.0;\n            \n            for (size_t j = 0; j < candidates.size(); ++j) {\n                bool found = false;\n                for (int k : selected_indices) {\n                    if (k == (int)j) { found = true; break; }\n                }\n                if (found) continue;\n                \n                double min_d = 1e18;\n                for (int k : selected_indices) {\n                    double d = feature_distance(cand_expected[j], cand_expected[k], eps);\n                    if (d < min_d) min_d = d;\n                }\n                \n                if (min_d > max_min_dist) {\n                    max_min_dist = min_d;\n                    best_idx = (int)j;\n                }\n            }\n            \n            if (best_idx != -1) {\n                selected_indices.push_back(best_idx);\n            } else {\n                int r = rand() % candidates.size();\n                while (true) {\n                    bool found = false;\n                    for (int k : selected_indices) {\n                        if (k == r) { found = true; break; }\n                    }\n                    if (!found) break;\n                    r = rand() % candidates.size();\n                }\n                selected_indices.push_back(r);\n            }\n        }\n\n        // Calculate minimum pairwise distance\n        double min_pair_dist = 1e18;\n        for (size_t i = 0; i < selected_indices.size(); ++i) {\n            for (size_t j = i + 1; j < selected_indices.size(); ++j) {\n                double d = feature_distance(cand_expected[selected_indices[i]], cand_expected[selected_indices[j]], eps);\n                if (d < min_pair_dist) min_pair_dist = d;\n            }\n        }\n\n        // Estimate error rate\n        double E_est = 100.0 * exp(-min_pair_dist / 5000.0);\n        if (E_est < 0.0) E_est = 0.0;\n        if (E_est > 100.0) E_est = 100.0;\n\n        double score = pow(0.9, E_est) / N;\n        \n        if (score > best_score || (abs(score - best_score) < 1e-9 && N < best_N)) {\n            best_score = score;\n            best_N = N;\n            best_Gs.clear();\n            best_ExpectedFeatures.clear();\n            for (int idx : selected_indices) {\n                best_Gs.push_back(candidates[idx]);\n                best_ExpectedFeatures.push_back(cand_expected[idx]);\n            }\n        }\n    }\n\n    // Output\n    cout << best_N << endl;\n    for (const auto& g : best_Gs) {\n        cout << g.to_string() << endl;\n    }\n    cout.flush();\n\n    // Query processing\n    string H_str;\n    for (int q = 0; q < 100; ++q) {\n        cin >> H_str;\n        Graph H = Graph::from_string(best_N, H_str);\n        Features h_feat = compute_features(H);\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double d = feature_distance(h_feat, best_ExpectedFeatures[k], eps);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint N, M, D, K;\nstruct Edge {\n    int u, v, w, id;\n};\nvector<Edge> edges;\nvector<int> edge_day;\nvector<vector<long long>> dist_original;\nvector<vector<pair<int, int>>> adj;\nvector<pair<int, int>> sampled_pairs;\nvector<long long> day_frustration;\nlong long total_frustration;\nmt19937 rng;\nchrono::steady_clock::time_point start_time;\n\nvoid init_rng(unsigned long long seed) {\n    rng.seed(seed);\n}\n\nvoid build_adjacency() {\n    adj.assign(N + 1, vector<pair<int, int>>());\n    for (int i = 0; i < M; i++) {\n        adj[edges[i].u].push_back({edges[i].v, i});\n        adj[edges[i].v].push_back({edges[i].u, i});\n    }\n}\n\nvoid calc_original_distances() {\n    dist_original.assign(N + 1, vector<long long>(N + 1, 1e18));\n    \n    for (int start = 1; start <= N; start++) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        dist_original[start][start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist_original[start][u]) continue;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (dist_original[start][v] > dist_original[start][u] + edges[eid].w) {\n                    dist_original[start][v] = dist_original[start][u] + edges[eid].w;\n                    pq.push({dist_original[start][v], v});\n                }\n            }\n        }\n    }\n}\n\nvoid sample_pairs() {\n    sampled_pairs.clear();\n    int num_samples = min(N * N, 800);\n    \n    vector<pair<int, int>> all_pairs;\n    for (int i = 1; i <= N; i++) {\n        for (int j = 1; j <= N; j++) {\n            if (i != j) all_pairs.push_back({i, j});\n        }\n    }\n    \n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    for (int i = 0; i < min((int)all_pairs.size(), num_samples); i++) {\n        sampled_pairs.push_back(all_pairs[i]);\n    }\n}\n\nlong long calc_frustration_day(int k) {\n    long long total_increase = 0;\n    \n    for (auto& [start, end] : sampled_pairs) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, 1e18);\n        dist[start] = 0;\n        pq.push({0, start});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == end) break;\n            \n            for (auto& [v, eid] : adj[u]) {\n                if (edge_day[eid] == k) continue;\n                \n                if (dist[v] > dist[u] + edges[eid].w) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        if (dist[end] >= 1e9) {\n            total_increase += 1e9;\n        } else {\n            total_increase += max(0LL, dist[end] - dist_original[start][end]);\n        }\n    }\n    \n    return total_increase;\n}\n\nvoid calc_all_frustrations() {\n    day_frustration.assign(D + 1, 0);\n    total_frustration = 0;\n    for (int k = 1; k <= D; k++) {\n        day_frustration[k] = calc_frustration_day(k);\n        total_frustration += day_frustration[k];\n    }\n}\n\nbool check_time() {\n    auto now = chrono::steady_clock::now();\n    auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed < 5500;\n}\n\nvoid init_solution() {\n    edge_day.assign(M, 0);\n    vector<int> day_count(D + 1, 0);\n    \n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    shuffle(edge_order.begin(), edge_order.end(), rng);\n    \n    for (int i : edge_order) {\n        int best_day = 1;\n        for (int d = 2; d <= D; d++) {\n            if (day_count[d] < day_count[best_day]) {\n                best_day = d;\n            }\n        }\n        edge_day[i] = best_day;\n        day_count[best_day]++;\n    }\n}\n\npair<vector<int>, long long> simulated_annealing(int time_budget) {\n    calc_all_frustrations();\n    long long best_frustration = total_frustration;\n    vector<int> best_day = edge_day;\n    vector<long long> best_day_frustration = day_frustration;\n    \n    double temp = 1e12;\n    double cooling_rate = 0.995;\n    \n    chrono::steady_clock::time_point sa_start = chrono::steady_clock::now();\n    \n    while (check_time() && temp > 1) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - sa_start).count();\n        if (elapsed > time_budget) break;\n        \n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) continue;\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        long long old_frustration = total_frustration - day_frustration[d1] - day_frustration[d2];\n        day_frustration[d1] = calc_frustration_day(d1);\n        day_frustration[d2] = calc_frustration_day(d2);\n        long long new_frustration = old_frustration + day_frustration[d1] + day_frustration[d2];\n        \n        long long delta = new_frustration - total_frustration;\n        \n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if ((double)uniform_int_distribution<int>(0, 1000000)(rng) / 1000000.0 < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            total_frustration = new_frustration;\n            if (new_frustration < best_frustration) {\n                best_frustration = new_frustration;\n                best_day = edge_day;\n                best_day_frustration = day_frustration;\n            }\n        } else {\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            day_frustration[d1] = best_day_frustration[d1];\n            day_frustration[d2] = best_day_frustration[d2];\n            total_frustration = best_frustration;\n        }\n        \n        temp *= cooling_rate;\n    }\n    \n    return {best_day, best_frustration};\n}\n\nvoid final_local_search() {\n    calc_all_frustrations();\n    long long best_frustration = total_frustration;\n    vector<int> best_day = edge_day;\n    vector<long long> best_day_frustration = day_frustration;\n    \n    int max_iterations = 10;\n    int iterations = 0;\n    \n    while (check_time() && iterations < max_iterations) {\n        int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n        int e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        while (e2 == e1) {\n            e2 = uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n        \n        if (edge_day[e1] == edge_day[e2]) {\n            iterations++;\n            continue;\n        }\n        \n        int d1 = edge_day[e1];\n        int d2 = edge_day[e2];\n        \n        edge_day[e1] = d2;\n        edge_day[e2] = d1;\n        \n        long long old_frustration = total_frustration - day_frustration[d1] - day_frustration[d2];\n        day_frustration[d1] = calc_frustration_day(d1);\n        day_frustration[d2] = calc_frustration_day(d2);\n        long long new_frustration = old_frustration + day_frustration[d1] + day_frustration[d2];\n        \n        if (new_frustration < best_frustration) {\n            best_frustration = new_frustration;\n            best_day = edge_day;\n            best_day_frustration = day_frustration;\n        } else {\n            edge_day[e1] = d1;\n            edge_day[e2] = d2;\n            day_frustration[d1] = best_day_frustration[d1];\n            day_frustration[d2] = best_day_frustration[d2];\n            total_frustration = best_frustration;\n        }\n        \n        iterations++;\n    }\n    \n    edge_day = best_day;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> D >> K;\n    \n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i;\n    }\n    \n    vector<int> x(N + 1), y(N + 1);\n    for (int i = 1; i <= N; i++) {\n        cin >> x[i] >> y[i];\n    }\n    \n    // Input-based seed for reproducibility\n    unsigned long long base_seed = ((unsigned long long)N << 48) ^ ((unsigned long long)M << 32) ^ \n                                    ((unsigned long long)D << 16) ^ (unsigned long long)K;\n    \n    init_rng(base_seed);\n    build_adjacency();\n    calc_original_distances();\n    sample_pairs();\n    \n    // Multiple restarts\n    vector<int> best_solution(M);\n    long long best_score = -1;\n    \n    for (int restart = 0; restart < 3 && check_time(); restart++) {\n        init_rng(base_seed + restart * 123456789);\n        init_solution();\n        auto [solution, score] = simulated_annealing(1500);\n        \n        if (best_score == -1 || score < best_score) {\n            best_score = score;\n            best_solution = solution;\n        }\n    }\n    \n    edge_day = best_solution;\n    if (check_time()) {\n        final_local_search();\n    }\n    \n    for (int i = 0; i < M; i++) {\n        cout << edge_day[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int MAXD = 15;\n\nint D;\nvector<string> f[2], r[2];\nint b[2][MAXD][MAXD][MAXD];\n\n// Normalize a shape for comparison\nvector<tuple<int,int,int>> normalize_shape(const vector<tuple<int,int,int>>& shape) {\n    if (shape.empty()) return shape;\n    \n    vector<tuple<int,int,int>> s = shape;\n    int min_x = 0, min_y = 0, min_z = 0;\n    \n    for (const auto& cell : s) {\n        min_x = min(min_x, get<0>(cell));\n        min_y = min(min_y, get<1>(cell));\n        min_z = min(min_z, get<2>(cell));\n    }\n    \n    for (auto& cell : s) {\n        get<0>(cell) -= min_x;\n        get<1>(cell) -= min_y;\n        get<2>(cell) -= min_z;\n    }\n    \n    sort(s.begin(), s.end());\n    return s;\n}\n\n// Rotate shape around x-axis\nvector<tuple<int,int,int>> rotate_x(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({x, z, -y});\n    }\n    return normalize_shape(result);\n}\n\n// Rotate shape around y-axis\nvector<tuple<int,int,int>> rotate_y(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({-z, y, x});\n    }\n    return normalize_shape(result);\n}\n\n// Rotate shape around z-axis\nvector<tuple<int,int,int>> rotate_z(const vector<tuple<int,int,int>>& shape) {\n    vector<tuple<int,int,int>> result;\n    for (const auto& cell : shape) {\n        int x = get<0>(cell);\n        int y = get<1>(cell);\n        int z = get<2>(cell);\n        result.push_back({-y, x, z});\n    }\n    return normalize_shape(result);\n}\n\n// Get all 24 rotations of a shape\nvector<vector<tuple<int,int,int>>> get_all_rotations(const vector<tuple<int,int,int>>& shape) {\n    set<vector<tuple<int,int,int>>> seen;\n    queue<vector<tuple<int,int,int>>> q;\n    vector<vector<tuple<int,int,int>>> rotations;\n    \n    vector<tuple<int,int,int>> current = normalize_shape(shape);\n    seen.insert(current);\n    q.push(current);\n    rotations.push_back(current);\n    \n    while (!q.empty()) {\n        auto cur = q.front();\n        q.pop();\n        \n        vector<vector<tuple<int,int,int>>> next_shapes = {\n            rotate_x(cur),\n            rotate_y(cur),\n            rotate_z(cur)\n        };\n        \n        for (const auto& next : next_shapes) {\n            if (seen.find(next) == seen.end()) {\n                seen.insert(next);\n                q.push(next);\n                rotations.push_back(next);\n            }\n        }\n    }\n    \n    return rotations;\n}\n\n// Get canonical form of a shape (minimum among all rotations)\nvector<tuple<int,int,int>> get_canonical_shape(const vector<tuple<int,int,int>>& shape) {\n    auto rotations = get_all_rotations(shape);\n    vector<tuple<int,int,int>> canonical = rotations[0];\n    for (size_t i = 1; i < rotations.size(); i++) {\n        if (rotations[i] < canonical) {\n            canonical = rotations[i];\n        }\n    }\n    return canonical;\n}\n\n// Find connected components\nvector<vector<tuple<int,int,int>>> find_components(int i) {\n    vector<vector<tuple<int,int,int>>> components;\n    bool visited[MAXD][MAXD][MAXD] = {0};\n    \n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (b[i][x][y][z] > 0 && !visited[x][y][z]) {\n                    vector<tuple<int,int,int>> component;\n                    queue<tuple<int,int,int>> q;\n                    \n                    visited[x][y][z] = true;\n                    q.push({x, y, z});\n                    component.push_back({x, y, z});\n                    \n                    int dx[] = {1, -1, 0, 0, 0, 0};\n                    int dy[] = {0, 0, 1, -1, 0, 0};\n                    int dz[] = {0, 0, 0, 0, 1, -1};\n                    \n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front();\n                        q.pop();\n                        \n                        for (int d = 0; d < 6; d++) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                !visited[nx][ny][nz] && b[i][nx][ny][nz] > 0) {\n                                visited[nx][ny][nz] = true;\n                                q.push({nx, ny, nz});\n                                component.push_back({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    components.push_back(component);\n                }\n            }\n        }\n    }\n    \n    return components;\n}\n\n// Create unit blocks (each cell is its own block)\nvector<vector<tuple<int,int,int>>> find_unit_blocks(int i) {\n    vector<vector<tuple<int,int,int>>> components;\n    \n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (b[i][x][y][z] > 0) {\n                    components.push_back({{x, y, z}});\n                }\n            }\n        }\n    }\n    \n    return components;\n}\n\n// Calculate score\nlong long calculate_score(const int final_b[2][MAXD][MAXD][MAXD]) {\n    set<int> blocks_in_1, blocks_in_2;\n    map<int, int> volume;\n    \n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (final_b[0][x][y][z] > 0) {\n                    blocks_in_1.insert(final_b[0][x][y][z]);\n                }\n                if (final_b[1][x][y][z] > 0) {\n                    blocks_in_2.insert(final_b[1][x][y][z]);\n                }\n            }\n        }\n    }\n    \n    for (int blk : blocks_in_1) {\n        int vol = 0;\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (final_b[0][x][y][z] == blk) vol++;\n                }\n            }\n        }\n        volume[blk] = vol;\n    }\n    \n    for (int blk : blocks_in_2) {\n        if (volume.find(blk) == volume.end()) {\n            int vol = 0;\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    for (int z = 0; z < D; z++) {\n                        if (final_b[1][x][y][z] == blk) vol++;\n                    }\n                }\n            }\n            volume[blk] = vol;\n        }\n    }\n    \n    long long r1 = 0, r2 = 0;\n    double shared_penalty = 0;\n    \n    for (int blk : blocks_in_1) {\n        if (blocks_in_2.find(blk) == blocks_in_2.end()) {\n            r1 += volume[blk];\n        } else {\n            shared_penalty += 1.0 / volume[blk];\n        }\n    }\n    \n    for (int blk : blocks_in_2) {\n        if (blocks_in_1.find(blk) == blocks_in_1.end()) {\n            r2 += volume[blk];\n        }\n    }\n    \n    return round(1e9 * (r1 + r2 + shared_penalty));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        r[i].resize(D);\n        for (int z = 0; z < D; z++) {\n            cin >> f[i][z];\n        }\n        for (int z = 0; z < D; z++) {\n            cin >> r[i][z];\n        }\n    }\n    \n    // Initialize block arrays\n    memset(b, 0, sizeof(b));\n    \n    // Phase 1: Initial placement - place unit blocks at all valid positions\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        b[i][x][y][z] = 1;\n                    }\n                }\n            }\n        }\n    }\n    \n    int best_b[2][MAXD][MAXD][MAXD];\n    long long best_score = LLONG_MAX;\n    int best_block_count = 0;\n    \n    // Try different block partitioning strategies\n    for (int strategy = 0; strategy < 2; strategy++) {\n        int temp_b[2][MAXD][MAXD][MAXD];\n        memset(temp_b, 0, sizeof(temp_b));\n        \n        // Strategy 0: Connected components (largest blocks)\n        // Strategy 1: Unit blocks (smallest blocks)\n        for (int i = 0; i < 2; i++) {\n            int component_counter = 0;\n            vector<vector<tuple<int,int,int>>> components;\n            \n            if (strategy == 0) {\n                components = find_components(i);\n            } else {\n                components = find_unit_blocks(i);\n            }\n            \n            for (const auto& component : components) {\n                component_counter++;\n                for (auto& [cx, cy, cz] : component) {\n                    temp_b[i][cx][cy][cz] = component_counter;\n                }\n            }\n        }\n        \n        // Phase 3: Extract blocks and compute canonical shapes\n        map<int, vector<tuple<int,int,int>>> blocks[2];\n        \n        for (int i = 0; i < 2; i++) {\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    for (int z = 0; z < D; z++) {\n                        if (temp_b[i][x][y][z] > 0) {\n                            blocks[i][temp_b[i][x][y][z]].push_back({x, y, z});\n                        }\n                    }\n                }\n            }\n        }\n        \n        map<int, vector<tuple<int,int,int>>> canonical_shapes[2];\n        for (int i = 0; i < 2; i++) {\n            for (auto& [id, cells] : blocks[i]) {\n                canonical_shapes[i][id] = get_canonical_shape(cells);\n            }\n        }\n        \n        // Phase 4: Group blocks by canonical shape\n        map<vector<tuple<int,int,int>>, vector<pair<int,int>>> shape_to_blocks[2]; // (volume, id)\n        for (int i = 0; i < 2; i++) {\n            for (auto& [id, canonical] : canonical_shapes[i]) {\n                shape_to_blocks[i][canonical].push_back({(int)blocks[i][id].size(), id});\n            }\n        }\n        \n        // Sort blocks by volume (larger first) for better matching\n        for (int i = 0; i < 2; i++) {\n            for (auto& [canonical, block_list] : shape_to_blocks[i]) {\n                sort(block_list.begin(), block_list.end(), greater<pair<int,int>>());\n            }\n        }\n        \n        // Phase 5: Assign new IDs with optimized matching\n        map<int, int> old_to_new_id[2];\n        int new_block_counter = 0;\n        \n        // Track: canonical_shape -> list of new IDs assigned for this shape\n        map<vector<tuple<int,int,int>>, vector<int>> shape_to_new_ids;\n        \n        // Process construction 0 - assign IDs to all blocks\n        for (auto& [canonical, block_list] : shape_to_blocks[0]) {\n            for (auto& [vol, id] : block_list) {\n                new_block_counter++;\n                old_to_new_id[0][id] = new_block_counter;\n                shape_to_new_ids[canonical].push_back(new_block_counter);\n            }\n        }\n        \n        // Process construction 1 - reuse IDs from construction 0 when shapes match\n        // Match largest blocks first (since we sorted by volume)\n        for (auto& [canonical, block_list] : shape_to_blocks[1]) {\n            vector<int>& available_ids = shape_to_new_ids[canonical];\n            \n            for (auto& [vol, id] : block_list) {\n                if (!available_ids.empty()) {\n                    // Reuse an ID from construction 0 (LIFO matches largest with largest)\n                    old_to_new_id[1][id] = available_ids.back();\n                    available_ids.pop_back();\n                } else {\n                    // No more IDs available for this shape, assign new ID\n                    new_block_counter++;\n                    old_to_new_id[1][id] = new_block_counter;\n                }\n            }\n        }\n        \n        // Phase 6: Apply the remapping\n        for (int i = 0; i < 2; i++) {\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    for (int z = 0; z < D; z++) {\n                        if (temp_b[i][x][y][z] > 0) {\n                            temp_b[i][x][y][z] = old_to_new_id[i][temp_b[i][x][y][z]];\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Calculate score\n        long long score = calculate_score(temp_b);\n        \n        if (score < best_score) {\n            best_score = score;\n            best_block_count = new_block_counter;\n            memcpy(best_b, temp_b, sizeof(best_b));\n        }\n    }\n    \n    // Output\n    cout << best_block_count << \"\\n\";\n    for (int i = 0; i < 2; i++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    cout << best_b[i][x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \");\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst long long INF_COST = 1e18;\nconst int MAX_P = 5000;\n\nstruct Point {\n    int x, y;\n    long long distSq(const Point& other) const {\n        return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y);\n    }\n};\n\nstruct Resident : public Point {\n    int id;\n};\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nint N, M, K;\nvector<Point> stations;\nvector<Edge> edges;\nvector<Resident> residents;\nvector<int> P, B;\nvector<vector<pair<int, int>>> adj;\nvector<bool> reachable;\n\n// Precomputed distances: station[i].distSq[resident[k]]\nvector<vector<long long>> stationResidentDist;\n\n// Precomputed edge list sorted by weight\nvector<int> sortedEdges;\n\n// Fast reachability check\nvoid computeReachable() {\n    reachable.assign(N, false);\n    static vector<int> q;\n    q.clear();\n    \n    reachable[0] = true;\n    q.push_back(0);\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int edgeIdx = edge.second;\n            if (B[edgeIdx] && !reachable[v]) {\n                reachable[v] = true;\n                q.push_back(v);\n            }\n        }\n    }\n}\n\n// Build MST using Union-Find\nvoid buildNetwork() {\n    fill(B.begin(), B.end(), 0);\n    \n    // Union-Find\n    static vector<int> parent;\n    parent.resize(N);\n    iota(parent.begin(), parent.end(), 0);\n    \n    function<int(int)> find = [&](int x) {\n        int root = x;\n        while (parent[root] != root) root = parent[root];\n        int curr = x;\n        while (curr != root) {\n            int next = parent[curr];\n            parent[curr] = root;\n            curr = next;\n        }\n        return root;\n    };\n    \n    // Connect all vertices (MST)\n    for (int idx : sortedEdges) {\n        int u = edges[idx].u;\n        int v = edges[idx].v;\n        int pu = find(u);\n        int pv = find(v);\n        if (pu != pv) {\n            parent[pu] = pv;\n            B[idx] = 1;\n        }\n    }\n}\n\n// Calculate cost (fast version)\nlong long calculateCost() {\n    long long cost = 0;\n    for (int j = 0; j < M; j++) {\n        if (B[j]) cost += edges[j].w;\n    }\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    return cost;\n}\n\n// Count covered residents (only call when needed)\nint countCovered() {\n    int count = 0;\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (reachable[i] && P[i] > 0) {\n                if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                    count++;\n                    break;\n                }\n            }\n        }\n    }\n    return count;\n}\n\n// Optimize P values\nvoid optimizeP() {\n    for (int i = 0; i < N; i++) {\n        if (!reachable[i]) {\n            P[i] = 0;\n            continue;\n        }\n        \n        long long maxDist = 0;\n        for (int k = 0; k < K; k++) {\n            if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                maxDist = max(maxDist, stationResidentDist[i][k]);\n            }\n        }\n        \n        if (maxDist == 0) {\n            P[i] = 0;\n        } else {\n            P[i] = (int)ceil(sqrt((double)maxDist));\n            if (P[i] > MAX_P) P[i] = MAX_P;\n        }\n    }\n}\n\n// Ensure all residents are covered\nvoid ensureCoverage() {\n    for (int k = 0; k < K; k++) {\n        bool covered = false;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i] && P[i] > 0) {\n                if (stationResidentDist[i][k] <= 1LL * P[i] * P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n        }\n        \n        if (!covered) {\n            int bestStation = -1;\n            long long minDist = INF_COST;\n            \n            for (int i = 0; i < N; i++) {\n                if (reachable[i]) {\n                    if (stationResidentDist[i][k] < minDist) {\n                        minDist = stationResidentDist[i][k];\n                        bestStation = i;\n                    }\n                }\n            }\n            \n            if (bestStation >= 0) {\n                int neededP = (int)ceil(sqrt((double)minDist));\n                if (neededP > MAX_P) neededP = MAX_P;\n                P[bestStation] = max(P[bestStation], neededP);\n            }\n        }\n    }\n}\n\n// Local search with minimal overhead\nvoid localSearch() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int iterations = 5000;\n    double temperature = 3000000.0;\n    double coolingRate = 0.998;\n    \n    computeReachable();\n    long long bestCost = calculateCost();\n    vector<int> bestP = P;\n    vector<int> bestB = B;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int action = (int)(rng() % 4);\n        \n        if (action == 0) {\n            // Activate new station\n            int station = (int)(rng() % N);\n            if (station != 0 && P[station] == 0) {\n                P[station] = 1;\n            }\n        } else if (action == 1) {\n            // Deactivate station\n            int station = (int)(rng() % N);\n            if (station != 0 && P[station] > 0) {\n                P[station] = 0;\n            }\n        } else if (action == 2) {\n            // Increase P\n            int station = (int)(rng() % N);\n            if (P[station] < MAX_P) {\n                P[station] = min(MAX_P, P[station] + (int)(rng() % 150) + 1);\n            }\n        } else {\n            // Decrease P\n            int station = (int)(rng() % N);\n            if (P[station] > 0 && station != 0) {\n                P[station] = max(0, P[station] - (int)(rng() % 150) - 1);\n            }\n        }\n        \n        // Only rebuild network occasionally\n        if (iter % 10 == 0) {\n            buildNetwork();\n            computeReachable();\n        }\n        \n        // Only optimize P occasionally\n        if (iter % 5 == 0) {\n            optimizeP();\n        }\n        \n        // Calculate cost (fast)\n        long long newCost = calculateCost();\n        \n        if (newCost < bestCost || dist(rng) < exp((bestCost - newCost) / temperature)) {\n            bestCost = newCost;\n            bestP = P;\n            bestB = B;\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    P = bestP;\n    B = bestB;\n}\n\n// Initial solution with cluster awareness\nvoid initSolution() {\n    P.assign(N, 0);\n    B.assign(M, 0);\n    \n    // Greedy: assign each resident to nearest station\n    for (int k = 0; k < K; k++) {\n        int bestStation = 0;\n        long long minDist = stationResidentDist[0][k];\n        \n        for (int i = 1; i < N; i++) {\n            if (stationResidentDist[i][k] < minDist) {\n                minDist = stationResidentDist[i][k];\n                bestStation = i;\n            }\n        }\n        \n        int neededP = (int)ceil(sqrt((double)minDist));\n        if (neededP > MAX_P) neededP = MAX_P;\n        P[bestStation] = max(P[bestStation], neededP);\n    }\n    \n    if (P[0] == 0) P[0] = 1;\n    \n    buildNetwork();\n    computeReachable();\n    optimizeP();\n    ensureCoverage();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    stations.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    \n    for (int j = 0; j < M; j++) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n        edges[j].u--;\n        edges[j].v--;\n        edges[j].id = j;\n        adj[edges[j].u].push_back({edges[j].v, j});\n        adj[edges[j].v].push_back({edges[j].u, j});\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n    \n    // Precompute all station-resident distances\n    stationResidentDist.resize(N, vector<long long>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            stationResidentDist[i][k] = stations[i].distSq(residents[k]);\n        }\n    }\n    \n    // Precompute sorted edges\n    sortedEdges.resize(M);\n    iota(sortedEdges.begin(), sortedEdges.end(), 0);\n    sort(sortedEdges.begin(), sortedEdges.end(), [&](int a, int b) {\n        return edges[a].w < edges[b].w;\n    });\n    \n    initSolution();\n    localSearch();\n    \n    // Final validation and repair\n    buildNetwork();\n    computeReachable();\n    optimizeP();\n    ensureCoverage();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\n\nint N = 30;\nvector<vector<int>> grid;\nvector<tuple<int, int, int, int>> operations;\n\n// Get all 6 adjacent positions\nvector<pair<int, int>> get_adj(int x, int y) {\n    vector<pair<int, int>> adj;\n    int dx[] = {-1, -1, 0, 0, 1, 1};\n    int dy[] = {-1, 0, -1, 1, 0, 1};\n    \n    for (int i = 0; i < 6; i++) {\n        int nx = x + dx[i];\n        int ny = y + dy[i];\n        if (nx >= 0 && nx < N && ny >= 0 && ny <= nx) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\n// BFS to find shortest path from (sx, sy) to (tx, ty)\nvector<pair<int, int>> bfs_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {};\n    \n    queue<pair<int, int>> q;\n    map<pair<int, int>, pair<int, int>> parent;\n    \n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        if (x == tx && y == ty) {\n            vector<pair<int, int>> path;\n            auto curr = make_pair(tx, ty);\n            while (curr.first != -1 && curr.second != -1) {\n                path.push_back(curr);\n                curr = parent[curr];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto [nx, ny] : get_adj(x, y)) {\n            if (parent.find({nx, ny}) == parent.end()) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    return {};\n}\n\n// Swap balls at two positions and record operation\nvoid swap_positions(int x1, int y1, int x2, int y2) {\n    int temp = grid[x1][y1];\n    grid[x1][y1] = grid[x2][y2];\n    grid[x2][y2] = temp;\n    operations.emplace_back(x1, y1, x2, y2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    grid.resize(N);\n    for (int x = 0; x < N; x++) {\n        grid[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n        }\n    }\n    \n    // Track which positions are already filled\n    vector<vector<bool>> filled(N);\n    for (int x = 0; x < N; x++) {\n        filled[x].assign(x + 1, false);\n    }\n    \n    // Process positions from top to bottom\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (filled[x][y]) continue;\n            \n            // Find smallest ball among all unfilled positions\n            int best_val = 1e9;\n            int best_x = -1, best_y = -1;\n            \n            for (int px = x; px < N; px++) {\n                for (int py = 0; py <= px; py++) {\n                    if (!filled[px][py] && grid[px][py] < best_val) {\n                        best_val = grid[px][py];\n                        best_x = px;\n                        best_y = py;\n                    }\n                }\n            }\n            \n            // Move the best ball to current position\n            if (best_x != -1 && (best_x != x || best_y != y)) {\n                vector<pair<int, int>> path = bfs_path(best_x, best_y, x, y);\n                \n                // Perform swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); i++) {\n                    auto [x1, y1] = path[i];\n                    auto [x2, y2] = path[i + 1];\n                    swap_positions(x1, y1, x2, y2);\n                }\n            }\n            \n            filled[x][y] = true;\n        }\n    }\n    \n    // Output results\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nconst int D = 9;\nint N;\nvector<pair<int, int>> obstacles;\nvector<vector<int>> grid;\nvector<vector<int>> container_id;\n\nconst int di[] = {-1, 1, 0, 0};\nconst int dj[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// BFS through empty squares only\nmap<pair<int, int>, int> bfs_empty(int start_r, int start_c) {\n    map<pair<int, int>, int> dist;\n    queue<pair<int, int>> q;\n    \n    if (!isValid(start_r, start_c)) return dist;\n    \n    q.push({start_r, start_c});\n    dist[{start_r, start_c}] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n            if (isValid(nr, nc) && grid[nr][nc] == 0 && dist.find({nr, nc}) == dist.end()) {\n                dist[{nr, nc}] = dist[{r, c}] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return dist;\n}\n\n// Count empty neighbors\nint countEmptyNeighbors(int r, int c) {\n    int count = 0;\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + di[k];\n        int nc = c + dj[k];\n        if (isValid(nr, nc) && grid[nr][nc] == 0) {\n            count++;\n        }\n    }\n    return count;\n}\n\n// Check if placing at (r, c) keeps all other empty squares reachable\nbool isSafe(int r, int c, int entrance_r, int entrance_c) {\n    int original = grid[r][c];\n    grid[r][c] = 2;\n    \n    auto dist = bfs_empty(entrance_r, entrance_c);\n    \n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (grid[i][j] == 0 && (i != entrance_r || j != entrance_c)) {\n                if (dist.find({i, j}) == dist.end()) {\n                    grid[r][c] = original;\n                    return false;\n                }\n            }\n        }\n    }\n    \n    grid[r][c] = original;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int D_input;\n    if (!(cin >> D_input >> N)) return 0;\n    \n    obstacles.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    grid.assign(D, vector<int>(D, 0));\n    container_id.assign(D, vector<int>(D, -1));\n    \n    for (auto obs : obstacles) {\n        grid[obs.first][obs.second] = 1;\n    }\n    \n    int entrance_r = 0;\n    int entrance_c = (D - 1) / 2;\n    \n    set<int> used_ids;\n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; ++d) {\n        int t;\n        cin >> t;\n        used_ids.insert(t);\n        \n        // Calculate rank among remaining IDs\n        int smaller_used = 0;\n        for (int u : used_ids) {\n            if (u < t) smaller_used++;\n        }\n        int r = t - smaller_used;\n        \n        auto dist = bfs_empty(entrance_r, entrance_c);\n        \n        vector<pair<int, int>> candidates;\n        for (auto const& [pos, d] : dist) {\n            if (grid[pos.first][pos.second] == 0) {\n                if (pos.first != entrance_r || pos.second != entrance_c) {\n                    candidates.push_back(pos);\n                }\n            }\n        }\n        \n        // Sort by retrieval priority: closer to entrance and more empty neighbors = higher priority\n        // Higher priority positions should get smaller IDs\n        sort(candidates.begin(), candidates.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {\n            int dist_a = dist[a];\n            int dist_b = dist[b];\n            int empty_a = countEmptyNeighbors(a.first, a.second);\n            int empty_b = countEmptyNeighbors(b.first, b.second);\n            \n            // Lower distance and more empty neighbors = higher priority\n            // Score: -distance + empty_neighbors (higher is better)\n            int score_a = -dist_a + empty_a;\n            int score_b = -dist_b + empty_b;\n            \n            if (score_a != score_b) return score_a > score_b;\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n        \n        // Filter to only safe candidates\n        vector<pair<int, int>> safe_candidates;\n        for (auto p : candidates) {\n            if (isSafe(p.first, p.second, entrance_r, entrance_c)) {\n                safe_candidates.push_back(p);\n            }\n        }\n        \n        vector<pair<int, int>> final_candidates = safe_candidates.empty() ? candidates : safe_candidates;\n        \n        int U = final_candidates.size();\n        bool placed = false;\n        \n        if (U > 0) {\n            // Place smaller IDs in higher priority positions (earlier in sorted list)\n            // r is rank among remaining: 0 = smallest, U-1 = largest\n            // So position index k = r (smallest ID gets position 0)\n            int k = r;\n            if (k < 0) k = 0;\n            if (k >= U) k = U - 1;\n            \n            pair<int, int> chosen = final_candidates[k];\n            grid[chosen.first][chosen.second] = 2;\n            container_id[chosen.first][chosen.second] = t;\n            \n            cout << chosen.first << \" \" << chosen.second << \"\\n\";\n            cout.flush();\n            placed = true;\n        }\n        \n        if (!placed) {\n            for (int i = 0; i < D; ++i) {\n                for (int j = 0; j < D; ++j) {\n                    if (grid[i][j] == 0 && (i != entrance_r || j != entrance_c)) {\n                        grid[i][j] = 2;\n                        container_id[i][j] = t;\n                        cout << i << \" \" << j << \"\\n\";\n                        cout.flush();\n                        placed = true;\n                        break;\n                    }\n                }\n                if (placed) break;\n            }\n        }\n    }\n    \n    // Retrieval Phase\n    vector<pair<int, int>> retrieval_order;\n    int remaining = total_containers;\n    \n    while (remaining > 0) {\n        auto dist = bfs_empty(entrance_r, entrance_c);\n        \n        int min_id = 1e9;\n        pair<int, int> best_pos = {-1, -1};\n        \n        // Find reachable containers (adjacent to empty squares reachable from entrance)\n        for (auto const& [pos, d] : dist) {\n            for (int k = 0; k < 4; ++k) {\n                int nr = pos.first + di[k];\n                int nc = pos.second + dj[k];\n                if (isValid(nr, nc) && grid[nr][nc] == 2) {\n                    int id = container_id[nr][nc];\n                    if (id < min_id) {\n                        min_id = id;\n                        best_pos = {nr, nc};\n                    }\n                }\n            }\n        }\n        \n        if (best_pos.first != -1) {\n            retrieval_order.push_back(best_pos);\n            grid[best_pos.first][best_pos.second] = 0;\n            container_id[best_pos.first][best_pos.second] = -1;\n            remaining--;\n        } else {\n            break;\n        }\n    }\n    \n    for (auto p : retrieval_order) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 101;\n\nint n, m;\nint grid[MAXN][MAXN];\nint adj_count[MAXM][MAXM];\nbool required_adj[MAXM][MAXM];\nint num_tiles[MAXM];\nvector<pair<int, int>> tiles[MAXM];\nint pos[MAXN][MAXN];\nvector<pair<int, int>> all_nonzero;\n\nint visited[MAXN][MAXN];\nint visited_cookie = 0;\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < n && c >= 0 && c < n;\n}\n\n// Check connectivity of a specific color\nbool check_connectivity(int color) {\n    if (num_tiles[color] <= 1) return true;\n    \n    visited_cookie++;\n    int start_r = tiles[color][0].first;\n    int start_c = tiles[color][0].second;\n    \n    int count = 0;\n    vector<pair<int, int>> q;\n    q.reserve(num_tiles[color]);\n    q.push_back({start_r, start_c});\n    visited[start_r][start_c] = visited_cookie;\n    count++;\n    \n    int head = 0;\n    while(head < q.size()){\n        auto [r, c] = q[head++];\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_cookie){\n                visited[nr][nc] = visited_cookie;\n                q.push_back({nr, nc});\n                count++;\n            }\n        }\n    }\n    return count == num_tiles[color];\n}\n\n// Try to remove tile at (r, c)\nbool try_remove(int r, int c) {\n    int color = grid[r][c];\n    if(color == 0) return false;\n    \n    // Check adjacency impact\n    bool adj_ok = true;\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != color){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                // If this is the last edge between c1 and c2, and they are required to be adjacent\n                if(adj_count[c1][c2] == 1 && required_adj[c1][c2]){\n                    adj_ok = false;\n                    break;\n                }\n            }\n        }\n    }\n    if(!adj_ok) return false;\n    \n    // Temporarily remove\n    int idx = pos[r][c];\n    tiles[color].erase(tiles[color].begin() + idx);\n    num_tiles[color]--;\n    grid[r][c] = 0;\n    \n    // Update adj_count\n    for(int i=0; i<4; i++){\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if(is_valid(nr, nc)){\n            int ncolor = grid[nr][nc];\n            if(ncolor != 0){\n                int c1 = min(color, ncolor);\n                int c2 = max(color, ncolor);\n                adj_count[c1][c2]--;\n            }\n        }\n    }\n    \n    bool conn_ok = check_connectivity(color);\n    \n    if(!conn_ok){\n        // Revert\n        grid[r][c] = color;\n        num_tiles[color]++;\n        tiles[color].push_back({r, c});\n        pos[r][c] = tiles[color].size() - 1;\n        for(int i=0; i<4; i++){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if(is_valid(nr, nc)){\n                int ncolor = grid[nr][nc];\n                if(ncolor != 0){\n                    int c1 = min(color, ncolor);\n                    int c2 = max(color, ncolor);\n                    adj_count[c1][c2]++;\n                }\n            }\n        }\n        return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> n >> m)) return 0;\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cin >> grid[i][j];\n            if(grid[i][j] != 0){\n                tiles[grid[i][j]].push_back({i, j});\n                pos[i][j] = tiles[grid[i][j]].size() - 1;\n                num_tiles[grid[i][j]]++;\n                all_nonzero.push_back({i, j});\n            }\n        }\n    }\n    \n    memset(required_adj, 0, sizeof(required_adj));\n    memset(adj_count, 0, sizeof(adj_count));\n    \n    // Compute required adjacencies and counts\n    // Count each edge once\n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            int c = grid[i][j];\n            for(int k=0; k<4; k++){\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if(is_valid(ni, nj)){\n                    int nc = grid[ni][nj];\n                    if(c != nc){\n                        int c1 = min(c, nc);\n                        int c2 = max(c, nc);\n                        // Count only once by checking coordinate order\n                        if((i < ni) || (i == ni && j < nj)){\n                             required_adj[c1][c2] = true;\n                             adj_count[c1][c2]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    mt19937 rng(1337);\n    uniform_int_distribution<int> dist_idx(0, (int)all_nonzero.size() - 1);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int no_change = 0;\n    // Run greedy removal\n    while(true){\n        auto now = chrono::steady_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.9) break;\n        \n        if(all_nonzero.empty()) break;\n        \n        int idx = dist_idx((int)all_nonzero.size());\n        auto [r, c] = all_nonzero[idx];\n        \n        if(try_remove(r, c)){\n            // Remove from all_nonzero\n            int last_idx = all_nonzero.size() - 1;\n            all_nonzero[idx] = all_nonzero[last_idx];\n            all_nonzero.pop_back();\n            no_change = 0;\n        } else {\n            no_change++;\n            if(no_change > 5000) break;\n        }\n    }\n    \n    for(int i=0; i<n; i++){\n        for(int j=0; j<n; j++){\n            cout << grid[i][j] << (j == n-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <cmath>\n#include <numeric>\n#include <queue>\n\nusing namespace std;\n\n// Global variables for problem constraints\nint N, D, Q;\nvector<double> estimated_weights;\nvector<int> assignment;\nvector<vector<int>> sets;\nvector<double> set_sums;\n\n// Random number generator\nmt19937 rng(123456);\n\n// Function to output a query\nvoid output_query(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n}\n\n// Function to read query response\nstring read_response() {\n    string res;\n    cin >> res;\n    return res;\n}\n\n// Calculate variance of set sums\ndouble calculate_variance() {\n    double total_sum = 0.0;\n    for (double s : set_sums) total_sum += s;\n    double mean = total_sum / D;\n    double variance = 0.0;\n    for (double s : set_sums) {\n        variance += (s - mean) * (s - mean);\n    }\n    return variance / D;\n}\n\n// Initialize sets using LPT heuristic\nvoid initialize_sets() {\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({estimated_weights[i], i});\n    }\n    sort(items.begin(), items.end(), [](const pair<double, int>& a, const pair<double, int>& b) {\n        return a.first > b.first;\n    });\n\n    sets.assign(D, vector<int>());\n    set_sums.assign(D, 0.0);\n    assignment.assign(N, -1);\n\n    for (int i = 0; i < N; ++i) {\n        int item_idx = items[i].second;\n        double weight = items[i].first;\n        \n        int min_set = 0;\n        for (int j = 1; j < D; ++j) {\n            if (set_sums[j] < set_sums[min_set]) {\n                min_set = j;\n            }\n        }\n        \n        sets[min_set].push_back(item_idx);\n        set_sums[min_set] += weight;\n        assignment[item_idx] = min_set;\n    }\n}\n\n// Local search to improve solution\nvoid local_search(int max_iterations) {\n    bool improved = true;\n    int iterations = 0;\n    \n    while (improved && iterations < max_iterations) {\n        improved = false;\n        iterations++;\n        \n        // Try moving each item to a better set\n        for (int i = 0; i < N; ++i) {\n            int current_set = assignment[i];\n            double w = estimated_weights[i];\n            \n            if (current_set < 0 || current_set >= D) continue;\n            \n            int best_set = current_set;\n            double best_variance = calculate_variance();\n            \n            set_sums[current_set] -= w;\n            \n            for (int s = 0; s < D; ++s) {\n                if (s == current_set) continue;\n                \n                set_sums[s] += w;\n                double var = calculate_variance();\n                \n                if (var < best_variance) {\n                    best_variance = var;\n                    best_set = s;\n                }\n                \n                set_sums[s] -= w;\n            }\n            \n            set_sums[current_set] += w;\n            \n            if (best_set != current_set) {\n                for (auto it = sets[current_set].begin(); it != sets[current_set].end(); ++it) {\n                    if (*it == i) {\n                        sets[current_set].erase(it);\n                        break;\n                    }\n                }\n                sets[best_set].push_back(i);\n                set_sums[current_set] -= w;\n                set_sums[best_set] += w;\n                assignment[i] = best_set;\n                improved = true;\n            }\n        }\n        \n        // Try swapping pairs\n        for (int s1 = 0; s1 < D; ++s1) {\n            for (int s2 = s1 + 1; s2 < D; ++s2) {\n                if (sets[s1].empty() || sets[s2].empty()) continue;\n                \n                for (int i = 0; i < (int)sets[s1].size(); ++i) {\n                    for (int j = 0; j < (int)sets[s2].size(); ++j) {\n                        int u = sets[s1][i];\n                        int v = sets[s2][j];\n                        \n                        double w_u = estimated_weights[u];\n                        double w_v = estimated_weights[v];\n                        \n                        double current_var = calculate_variance();\n                        \n                        set_sums[s1] = set_sums[s1] - w_u + w_v;\n                        set_sums[s2] = set_sums[s2] - w_v + w_u;\n                        \n                        double new_var = calculate_variance();\n                        \n                        if (new_var < current_var - 1e-10) {\n                            sets[s1][i] = v;\n                            sets[s2][j] = u;\n                            assignment[u] = s2;\n                            assignment[v] = s1;\n                            improved = true;\n                        } else {\n                            set_sums[s1] = set_sums[s1] - w_v + w_u;\n                            set_sums[s2] = set_sums[s2] - w_u + w_v;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing for partitioning\nvoid simulate_annealing(int max_time_ms) {\n    initialize_sets();\n    \n    double best_variance = calculate_variance();\n    vector<int> best_assignment = assignment;\n\n    double temperature = 25.0;\n    double cooling_rate = 0.991;\n    int iterations = 0;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    auto end_time = start_time + chrono::milliseconds(max_time_ms);\n\n    while (chrono::high_resolution_clock::now() < end_time && iterations < 250000) {\n        iterations++;\n        \n        int move_type = uniform_int_distribution<int>(0, 1)(rng);\n        \n        if (move_type == 0) {\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            if (sets[s1].empty() || sets[s2].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)sets[s2].size() - 1)(rng);\n            \n            int u = sets[s1][idx1];\n            int v = sets[s2][idx2];\n            \n            double w_u = estimated_weights[u];\n            double w_v = estimated_weights[v];\n            \n            double new_sum_s1 = set_sums[s1] - w_u + w_v;\n            double new_sum_s2 = set_sums[s2] - w_v + w_u;\n            \n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                sets[s1][idx1] = v;\n                sets[s2][idx2] = u;\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                assignment[v] = s1;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        } else {\n            int s1 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (sets[s1].empty()) continue;\n            \n            int idx1 = uniform_int_distribution<int>(0, (int)sets[s1].size() - 1)(rng);\n            int u = sets[s1][idx1];\n            double w_u = estimated_weights[u];\n            \n            int s2 = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (s1 == s2) continue;\n            \n            double new_sum_s1 = set_sums[s1] - w_u;\n            double new_sum_s2 = set_sums[s2] + w_u;\n            \n            double new_variance = 0.0;\n            double total_sum = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                total_sum += s;\n            }\n            double mean = total_sum / D;\n            for (int k = 0; k < D; ++k) {\n                double s = (k == s1) ? new_sum_s1 : (k == s2) ? new_sum_s2 : set_sums[k];\n                new_variance += (s - mean) * (s - mean);\n            }\n            new_variance /= D;\n            \n            double current_variance = calculate_variance();\n            double delta = new_variance - current_variance;\n            double accept_prob = (delta < 0) ? 1.0 : exp(-delta / temperature);\n            \n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < accept_prob) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_sum_s1;\n                set_sums[s2] = new_sum_s2;\n                assignment[u] = s2;\n                \n                double new_var = calculate_variance();\n                if (new_var < best_variance) {\n                    best_variance = new_var;\n                    best_assignment = assignment;\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n        if (temperature < 1e-15) break;\n    }\n\n    assignment = best_assignment;\n}\n\n// Helper function to normalize weights\nvoid normalize_weights() {\n    double total = 0.0;\n    for (double w : estimated_weights) total += w;\n    for (double &w : estimated_weights) w = w / total * N;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    estimated_weights.assign(N, 1.0);\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // Use minimal pairwise queries\n    int pairwise_queries = max(2, min(Q / 15, N * (N - 1) / 2));\n    int queries_used = 0;\n    \n    // Phase 1: Minimal pairwise comparisons\n    for (int i = 0; i < N && queries_used < pairwise_queries; ++i) {\n        for (int j = i + 1; j < N && queries_used < pairwise_queries; ++j) {\n            vector<int> L = {p[i]};\n            vector<int> R = {p[j]};\n            \n            output_query(L, R);\n            string res = read_response();\n            queries_used++;\n            \n            if (res == \"<\") {\n                estimated_weights[p[i]] *= 0.60;\n                estimated_weights[p[j]] *= 1.67;\n            } else if (res == \">\") {\n                estimated_weights[p[i]] *= 1.67;\n                estimated_weights[p[j]] *= 0.60;\n            }\n        }\n    }\n    \n    // Normalize weights\n    normalize_weights();\n    \n    // Phase 2: Balanced group comparisons (most queries)\n    int remaining_queries = Q - queries_used;\n    \n    for (int q = 0; q < remaining_queries; ++q) {\n        shuffle(p.begin(), p.end(), rng);\n        \n        vector<int> L, R;\n        double sum_L = 0.0;\n        double sum_R = 0.0;\n        \n        for (int i = 0; i < N; ++i) {\n            int item = p[i];\n            if (sum_L <= sum_R) {\n                L.push_back(item);\n                sum_L += estimated_weights[item];\n            } else {\n                R.push_back(item);\n                sum_R += estimated_weights[item];\n            }\n        }\n        \n        if (L.empty() && !R.empty()) {\n            L.push_back(R.back());\n            R.pop_back();\n        }\n        if (R.empty() && !L.empty()) {\n            R.push_back(L.back());\n            L.pop_back();\n        }\n        \n        output_query(L, R);\n        string res = read_response();\n        \n        double diff = sum_L - sum_R;\n        // Adaptive learning rate\n        double progress = (double)queries_used / Q;\n        double eta = 0.05 * (1.0 - progress * 0.4);\n        \n        if (res == \"<\") {\n            if (diff > -1e-9) {\n                double adjustment = eta * max(0.0, diff + 1e-9);\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        } else if (res == \">\") {\n            if (diff < 1e-9) {\n                double adjustment = eta * max(0.0, -diff + 1e-9);\n                for (int item : L) estimated_weights[item] += adjustment / L.size();\n                for (int item : R) estimated_weights[item] -= adjustment / R.size();\n            }\n        } else if (res == \"=\") {\n            // \"=\" is very informative - adjust more aggressively\n            if (abs(diff) > 1e-9) {\n                double adjustment = eta * 2.0 * diff;\n                for (int item : L) estimated_weights[item] -= adjustment / L.size();\n                for (int item : R) estimated_weights[item] += adjustment / R.size();\n            }\n        }\n        \n        // Normalize weights periodically to prevent explosion/collapse\n        if (queries_used % 10 == 0) {\n            normalize_weights();\n        }\n        \n        for (double &w : estimated_weights) {\n            if (w < 0.1) w = 0.1;\n            if (w > 1e6) w = 1e6;\n        }\n        \n        queries_used++;\n    }\n\n    // Final normalization\n    normalize_weights();\n\n    // Partitioning Phase with more restarts and better time allocation\n    int num_restarts = 15;\n    int time_per_restart = 130; // ms\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        if (restart > 0) {\n            for (double &w : estimated_weights) {\n                w *= (1.0 + uniform_real_distribution<double>(-0.20, 0.20)(rng));\n            }\n            normalize_weights();\n        }\n        \n        simulate_annealing(time_per_restart);\n    }\n    \n    // Final local search refinement (more aggressive)\n    initialize_sets();\n    local_search(3000);\n\n    // Output final assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n\nusing namespace std;\n\n// Global variables to store state\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // pos[v] = {stack_idx, height} (0-indexed stack, 0-indexed height)\nvector<pair<int, int>> operations;\n\n// Function to calculate inversions between a block S and a stack Dest\n// S is a vector of box values in the block (from bottom to top)\n// Dest is the index of the destination stack\n// Returns the number of pairs (u, d) such that u in S, d in stacks[Dest], u > d\nint count_inversions(const vector<int>& S, int dest_idx) {\n    int count = 0;\n    const auto& dest_stack = stacks[dest_idx];\n    for (int u : S) {\n        for (int d : dest_stack) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to calculate inversions between a block S and boxes below v in Source stack\n// v is the box we want to expose (it is below S in the source stack)\n// S is the block above v\nint count_inversions_below(const vector<int>& S, int source_idx, int v) {\n    int count = 0;\n    const auto& source_stack = stacks[source_idx];\n    // Find position of v\n    int v_pos = -1;\n    for (int i = 0; i < source_stack.size(); ++i) {\n        if (source_stack[i] == v) {\n            v_pos = i;\n            break;\n        }\n    }\n    // Iterate boxes below v\n    for (int i = 0; i < v_pos; ++i) {\n        int d = source_stack[i];\n        for (int u : S) {\n            if (u > d) count++;\n        }\n    }\n    return count;\n}\n\n// Function to execute a move\n// Move block starting at box v (and all above it) to dest_stack_idx\n// Returns the number of boxes moved\nint move_block(int v, int dest_stack_idx) {\n    auto [src_idx, h] = pos[v];\n    if (src_idx == dest_stack_idx) return 0;\n    \n    const auto& src_stack = stacks[src_idx];\n    // Identify the block\n    // The block starts at h and goes to top\n    vector<int> block;\n    for (int i = h; i < src_stack.size(); ++i) {\n        block.push_back(src_stack[i]);\n    }\n    \n    // Move to dest\n    for (int u : block) {\n        stacks[dest_stack_idx].push_back(u);\n        pos[u] = {dest_stack_idx, (int)stacks[dest_stack_idx].size() - 1};\n    }\n    \n    // Remove from src\n    for (int i = 0; i < block.size(); ++i) {\n        stacks[src_idx].pop_back();\n    }\n    \n    operations.push_back({v, dest_stack_idx + 1}); // 1-indexed output\n    return block.size();\n}\n\n// Function to remove box v (Op 2)\nvoid remove_box(int v) {\n    auto [src_idx, h] = pos[v];\n    // It must be at the top\n    if (h != (int)stacks[src_idx].size() - 1) {\n        // Should not happen if logic is correct\n        return;\n    }\n    stacks[src_idx].pop_back();\n    operations.push_back({v, 0});\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    pos.resize(N + 1);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Main loop\n    for (int v = 1; v <= N; ++v) {\n        // Check if v is at the top\n        auto [src_idx, h] = pos[v];\n        while (h != (int)stacks[src_idx].size() - 1) {\n            // v is covered. Identify boxes above v.\n            const auto& src_stack = stacks[src_idx];\n            vector<int> boxes_above;\n            for (int i = h + 1; i < src_stack.size(); ++i) {\n                boxes_above.push_back(src_stack[i]);\n            }\n            \n            int k = boxes_above.size();\n            if (k == 0) break; // Should not happen\n\n            // Generate candidates\n            // We try moving suffixes of boxes_above\n            // Suffixes: top 1, top 2, ..., top k (whole block)\n            // To save time, if k is large, we limit suffixes.\n            \n            vector<int> suffix_lengths;\n            if (k <= 5) {\n                for (int len = 1; len <= k; ++len) suffix_lengths.push_back(len);\n            } else {\n                suffix_lengths.push_back(1);\n                suffix_lengths.push_back(2);\n                suffix_lengths.push_back(k);\n            }\n\n            int best_score = 1e9;\n            int best_move_v = -1;\n            int best_dest = -1;\n\n            // Random seed for tie-breaking\n            static mt19937 rng(1337);\n            vector<pair<int, int>> candidates;\n\n            for (int len : suffix_lengths) {\n                // The block to move is the top 'len' boxes of boxes_above\n                // boxes_above is from bottom to top.\n                // So top 'len' boxes are boxes_above[k-len ... k-1]\n                vector<int> S;\n                for (int i = k - len; i < k; ++i) {\n                    S.push_back(boxes_above[i]);\n                }\n                int v_to_move = S.back(); // The bottom-most box of the block being moved\n\n                for (int dest = 0; dest < M; ++dest) {\n                    if (dest == src_idx) continue;\n\n                    // Cost = len + 1\n                    int cost = len + 1;\n\n                    // Delta Potential = New Inversions - Removed Inversions\n                    // New Inversions: pairs (u, d) with u in S, d in stacks[dest], u > d\n                    int new_inv = count_inversions(S, dest);\n                    \n                    // Removed Inversions: pairs (u, d) with u in S, d in stacks[src_idx] below v, u > d\n                    int removed_inv = count_inversions_below(S, src_idx, v);\n\n                    int score = cost + (new_inv - removed_inv);\n\n                    if (score < best_score) {\n                        best_score = score;\n                        candidates.clear();\n                        candidates.push_back({v_to_move, dest});\n                    } else if (score == best_score) {\n                        candidates.push_back({v_to_move, dest});\n                    }\n                }\n            }\n\n            if (candidates.empty()) {\n                // Fallback: move top 1 box to random stack\n                int top_box = boxes_above.back();\n                int dest = src_idx;\n                while (dest == src_idx) dest = rng() % M;\n                move_block(top_box, dest);\n            } else {\n                int idx = rng() % candidates.size();\n                move_block(candidates[idx].first, candidates[idx].second);\n            }\n            \n            // Update pos[v] and h after move\n            // pos[v] is updated inside move_block\n            // But we need to re-check if v is at top\n            auto [new_src, new_h] = pos[v];\n            src_idx = new_src;\n            h = new_h;\n        }\n\n        // Now v should be at top\n        remove_box(v);\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring route;\nvector<pair<int, int>> dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\nstring dir_chars = \"RDLU\";\n\nbool can_move(int i, int j, int di, int dj) {\n    int ni = i + di, nj = j + dj;\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // h has N-1 rows (0 to N-2), each with N characters\n    // v has N rows (0 to N-1), each with N-1 characters\n    if (di == 1) return h[i][j] == '0';      // moving down: check h[i][j]\n    if (di == -1) return h[ni][j] == '0';    // moving up: check h[i-1][j]\n    if (dj == 1) return v[i][j] == '0';      // moving right: check v[i][j]\n    if (dj == -1) return v[i][nj] == '0';    // moving left: check v[i][j-1]\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    // FIX: h has N-1 rows, v has N rows\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    d.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    visited.assign(N, vector<bool>(N, false));\n    \n    // Sort neighbors by dirtiness (descending) for prioritization\n    auto get_neighbors = [&](int i, int j) {\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !visited[ni][nj]) {\n                if (can_move(i, j, di, dj)) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        return neighbors;\n    };\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        auto neighbors = get_neighbors(i, j);\n        for (auto& [dirt, dir] : neighbors) {\n            int di = dirs[dir].first;\n            int dj = dirs[dir].second;\n            int ni = i + di, nj = j + dj;\n            \n            if (!visited[ni][nj] && can_move(i, j, di, dj)) {\n                route += dir_chars[dir];\n                dfs(ni, nj);\n                route += dir_chars[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Validate the route\n    int cur_i = 0, cur_j = 0;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        \n        if (!can_move(cur_i, cur_j, di, dj)) {\n            cerr << \"Invalid move at position (\" << cur_i << \", \" << cur_j << \") with direction \" << c << endl;\n            return 1;\n        }\n        \n        cur_i += di;\n        cur_j += dj;\n    }\n    \n    // Verify we return to (0, 0)\n    if (cur_i != 0 || cur_j != 0) {\n        cerr << \"Route does not return to (0, 0)\" << endl;\n        return 1;\n    }\n    \n    // Verify all squares are visited\n    visited.assign(N, vector<bool>(N, false));\n    cur_i = 0, cur_j = 0;\n    visited[0][0] = true;\n    for (char c : route) {\n        int dir_idx = -1;\n        if (c == 'U') dir_idx = 3;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 0;\n        \n        if (dir_idx == -1) continue;\n        \n        int di = dirs[dir_idx].first;\n        int dj = dirs[dir_idx].second;\n        cur_i += di;\n        cur_j += dj;\n        visited[cur_i][cur_j] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) {\n                cerr << \"Square (\" << i << \", \" << j << \") not visited\" << endl;\n                return 1;\n            }\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nint N, M;\nint start_i, start_j;\nvector<string> grid(15);\nvector<string> targets;\nvector<pair<int, int>> char_pos[26];\nvector<pair<int, int>> path;\nint total_cost;\n\n// Precomputed costs\nint cost_from_start[200];\nint cost_between[200][200];\nint last_pos_i[200];\nint last_pos_j[200];\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nint move_cost(int i1, int j1, int i2, int j2) {\n    return manhattan(i1, j1, i2, j2) + 1;\n}\n\npair<int, int> find_nearest(char c, int curr_i, int curr_j) {\n    const vector<pair<int, int>>& positions = char_pos[c - 'A'];\n    if (positions.empty()) return {0, 0};\n    \n    int best_dist = 1e9;\n    pair<int, int> best_pos = {-1, -1};\n    for (auto& p : positions) {\n        int d = manhattan(curr_i, curr_j, p.first, p.second);\n        if (d < best_dist) {\n            best_dist = d;\n            best_pos = p;\n        }\n    }\n    return best_pos;\n}\n\nvoid precompute_costs() {\n    for (int i = 0; i < M; i++) {\n        int ci = start_i, cj = start_j;\n        int cost = 0;\n        for (char c : targets[i]) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            cost += move_cost(ci, cj, pos.first, pos.second);\n            ci = pos.first;\n            cj = pos.second;\n        }\n        cost_from_start[i] = cost;\n        last_pos_i[i] = ci;\n        last_pos_j[i] = cj;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int ci = last_pos_i[i], cj = last_pos_j[i];\n            int cost = 0;\n            for (char c : targets[j]) {\n                pair<int, int> pos = find_nearest(c, ci, cj);\n                cost += move_cost(ci, cj, pos.first, pos.second);\n                ci = pos.first;\n                cj = pos.second;\n            }\n            cost_between[i][j] = cost;\n        }\n    }\n}\n\nint calculate_cost(const vector<int>& order) {\n    int cost = cost_from_start[order[0]];\n    for (int i = 1; i < M; i++) {\n        cost += cost_between[order[i-1]][order[i]];\n    }\n    return cost;\n}\n\nvector<pair<int, int>> generate_path(const vector<int>& order) {\n    vector<pair<int, int>> result;\n    int ci = start_i, cj = start_j;\n    \n    for (int idx : order) {\n        const string& s = targets[idx];\n        for (char c : s) {\n            pair<int, int> pos = find_nearest(c, ci, cj);\n            result.push_back(pos);\n            ci = pos.first;\n            cj = pos.second;\n        }\n    }\n    return result;\n}\n\nint calc_swap_delta(const vector<int>& order, int i, int j) {\n    if (i == j) return 0;\n    \n    int delta = 0;\n    \n    if (i > 0) {\n        delta -= cost_between[order[i-1]][order[i]];\n        delta += cost_between[order[i-1]][order[j]];\n    }\n    if (i + 1 < M) {\n        delta -= cost_between[order[i]][order[i+1]];\n        delta += cost_between[order[j]][order[i+1]];\n    }\n    if (j > 0) {\n        delta -= cost_between[order[j-1]][order[j]];\n        delta += cost_between[order[j-1]][order[i]];\n    }\n    if (j + 1 < M) {\n        delta -= cost_between[order[j]][order[j+1]];\n        delta += cost_between[order[i]][order[j+1]];\n    }\n    \n    return delta;\n}\n\nvoid optimize() {\n    precompute_costs();\n    \n    vector<int> best_order(M);\n    int best_cost = 1e9;\n    \n    // Tabu list for swap moves\n    vector<pair<int, int>> tabu_swaps;\n    int tabu_tenure = 10;\n    \n    // Slightly more restarts\n    int restarts = 17;\n    for (int r = 0; r < restarts; r++) {\n        vector<int> order(M);\n        \n        // Different initialization strategies\n        if (r == 0) {\n            // Sequential order\n            iota(order.begin(), order.end(), 0);\n        } else if (r % 4 == 1) {\n            // Random shuffle\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine(r * 1000 + 42));\n        } else if (r % 4 == 2) {\n            // Greedy nearest neighbor\n            vector<bool> used(M, false);\n            int curr = rand() % M;\n            order[0] = curr;\n            used[curr] = true;\n            \n            for (int pos = 1; pos < M; pos++) {\n                int best_next = -1;\n                int best_cost = 1e9;\n                for (int next = 0; next < M; next++) {\n                    if (!used[next]) {\n                        int cost = cost_between[curr][next];\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_next = next;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    order[pos] = best_next;\n                    used[best_next] = true;\n                    curr = best_next;\n                }\n            }\n        } else {\n            // Reverse greedy\n            vector<bool> used(M, false);\n            int curr = rand() % M;\n            order[M-1] = curr;\n            used[curr] = true;\n            \n            for (int pos = M - 2; pos >= 0; pos--) {\n                int best_next = -1;\n                int best_cost = 1e9;\n                for (int next = 0; next < M; next++) {\n                    if (!used[next]) {\n                        int cost = cost_between[next][curr];\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_next = next;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    order[pos] = best_next;\n                    used[best_next] = true;\n                    curr = best_next;\n                }\n            }\n        }\n        \n        int current_cost = calculate_cost(order);\n        \n        // Greedy local search with tabu\n        int greedy_iters = 2200;\n        int no_improve = 0;\n        tabu_swaps.clear();\n        \n        while (greedy_iters-- > 0 && no_improve < 35) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            // Try random swaps\n            for (int iter = 0; iter < 120; iter++) {\n                int i = rand() % M;\n                int j = rand() % M;\n                if (i == j) continue;\n                \n                // Check tabu\n                bool tabu = false;\n                for (auto& t : tabu_swaps) {\n                    if ((t.first == i && t.second == j) || (t.first == j && t.second == i)) {\n                        tabu = true;\n                        break;\n                    }\n                }\n                \n                int delta = calc_swap_delta(order, i, j);\n                if (!tabu && delta < best_delta) {\n                    best_delta = delta;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                tabu_swaps.push_back({best_i, best_j});\n                if (tabu_swaps.size() > tabu_tenure) tabu_swaps.erase(tabu_swaps.begin());\n                current_cost += best_delta;\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        }\n        \n        // Simulated annealing\n        double temp = 100.0;\n        double decay = 0.9978;\n        int sa_iters = 17000;\n        \n        for (int iter = 0; iter < sa_iters; iter++) {\n            int i = rand() % M;\n            int j = rand() % M;\n            if (i == j) continue;\n            \n            int delta = calc_swap_delta(order, i, j);\n            \n            if (delta <= 0 || (double)rand() / RAND_MAX < exp(-delta / temp)) {\n                swap(order[i], order[j]);\n                current_cost += delta;\n            }\n            \n            temp *= decay;\n        }\n        \n        // Final exhaustive local search\n        for (int iter = 0; iter < 350; iter++) {\n            int best_i = -1, best_j = -1;\n            int best_delta = 0;\n            \n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    int delta = calc_swap_delta(order, i, j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            if (best_i != -1 && best_delta < 0) {\n                swap(order[best_i], order[best_j]);\n                current_cost += best_delta;\n            } else {\n                break;\n            }\n        }\n        \n        if (current_cost < best_cost) {\n            best_cost = current_cost;\n            best_order = order;\n        }\n    }\n    \n    path = generate_path(best_order);\n    total_cost = calculate_cost(best_order);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(42);\n    \n    cin >> N >> M >> start_i >> start_j;\n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_pos[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    memset(cost_from_start, 0, sizeof(cost_from_start));\n    memset(cost_between, 0, sizeof(cost_between));\n    memset(last_pos_i, 0, sizeof(last_pos_i));\n    memset(last_pos_j, 0, sizeof(last_pos_j));\n    \n    optimize();\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nint N, M;\ndouble epsilon;\nstruct Shape {\n    int id;\n    int area;\n    vector<pair<int, int>> cells;\n    int max_r, max_c;\n};\nvector<Shape> shapes;\nmap<pair<int, int>, int> drilled_values;\nint operation_count = 0;\nconst int MAX_OPERATIONS = 780;\n\nmt19937 rng(1337);\n\nint drill(int r, int c) {\n    if (operation_count >= MAX_OPERATIONS - 5) return -1;\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    int v;\n    cin >> v;\n    drilled_values[{r, c}] = v;\n    operation_count++;\n    return v;\n}\n\nint divine(const vector<pair<int, int>>& cells) {\n    if (operation_count >= MAX_OPERATIONS - 5) return -1;\n    int k = cells.size();\n    if (k < 2) return -1;\n    cout << \"q \" << k;\n    for (size_t i = 0; i < cells.size(); ++i) {\n        cout << \" \" << cells[i].first << \" \" << cells[i].second;\n    }\n    cout << endl;\n    int v;\n    cin >> v;\n    operation_count++;\n    return v;\n}\n\nvoid submit(const vector<pair<int, int>>& cells) {\n    cout << \"a \" << cells.size();\n    for (size_t i = 0; i < cells.size(); ++i) {\n        cout << \" \" << cells[i].first << \" \" << cells[i].second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) return;\n    operation_count++;\n}\n\nbool covers(const Shape& s, int r, int c, int i, int j) {\n    for (size_t idx = 0; idx < s.cells.size(); ++idx) {\n        if (r + s.cells[idx].first == i && c + s.cells[idx].second == j) return true;\n    }\n    return false;\n}\n\nint predict_v(const vector<pair<int, int>>& config, int i, int j) {\n    int count = 0;\n    for (int k = 0; k < M; ++k) {\n        int r = config[k].first;\n        int c = config[k].second;\n        if (r >= 0 && c >= 0 && r < N && c < N) {\n            if (covers(shapes[k], r, c, i, j)) count++;\n        }\n    }\n    return count;\n}\n\nint calculate_error(const vector<pair<int, int>>& config) {\n    int error = 0;\n    for (auto const& [pos, val] : drilled_values) {\n        int i = pos.first;\n        int j = pos.second;\n        int pred = predict_v(config, i, j);\n        error += abs(pred - val);\n    }\n    return error;\n}\n\nvoid generate_candidates(vector<vector<pair<int, int>>>& candidates) {\n    candidates.clear();\n    candidates.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& s = shapes[k];\n        for (int r = 0; r <= N - 1 - s.max_r; ++r) {\n            for (int c = 0; c <= N - 1 - s.max_c; ++c) {\n                bool ok = true;\n                for (auto const& [pos, val] : drilled_values) {\n                    if (val == 0 && covers(s, r, c, pos.first, pos.second)) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) candidates[k].push_back({r, c});\n            }\n        }\n    }\n}\n\nbool try_solve(vector<pair<int, int>>& config, \n               const vector<vector<pair<int, int>>>& candidates) {\n    if ((int)candidates.size() != M) return false;\n    \n    for (int k = 0; k < M; ++k) {\n        if (candidates[k].empty()) return false;\n    }\n    \n    vector<int> order;\n    order.reserve(M);\n    for (int i = 0; i < M; ++i) order.push_back(i);\n    \n    for (int i = 0; i < M - 1; ++i) {\n        int min_idx = i;\n        for (int j = i + 1; j < M; ++j) {\n            if (candidates[j].size() < candidates[min_idx].size()) {\n                min_idx = j;\n            }\n        }\n        swap(order[i], order[min_idx]);\n    }\n    \n    config.assign(M, make_pair(-1, -1));\n    \n    // Reduced attempts to save time\n    int max_attempts = 400;\n    for (int attempt = 0; attempt < max_attempts; ++attempt) {\n        vector<int> shuffled = order;\n        for (int i = M - 1; i > 0; --i) {\n            int j = rng() % (i + 1);\n            swap(shuffled[i], shuffled[j]);\n        }\n        \n        bool success = true;\n        for (int idx = 0; idx < M; ++idx) {\n            int k = shuffled[idx];\n            if (candidates[k].empty()) {\n                success = false;\n                break;\n            }\n            int pos_idx = rng() % (int)candidates[k].size();\n            config[k] = candidates[k][pos_idx];\n        }\n        \n        if (success && calculate_error(config) == 0) {\n            return true;\n        }\n    }\n    \n    // Greedy\n    for (int idx = 0; idx < M; ++idx) {\n        int k = order[idx];\n        int best_idx = 0;\n        int best_error = 1000000;\n        \n        int num_candidates = candidates[k].size();\n        for (int i = 0; i < num_candidates; ++i) {\n            auto pos = candidates[k][i];\n            config[k] = pos;\n            \n            int error = 0;\n            for (auto const& [p, val] : drilled_values) {\n                int pred = 0;\n                for (int s = 0; s < M; ++s) {\n                    if (config[s].first != -1 && covers(shapes[s], config[s].first, config[s].second, p.first, p.second)) {\n                        pred++;\n                    }\n                }\n                error += abs(pred - val);\n            }\n            \n            if (error < best_error) {\n                best_error = error;\n                best_idx = i;\n            }\n        }\n        \n        config[k] = candidates[k][best_idx];\n    }\n    \n    return calculate_error(config) == 0;\n}\n\nvoid search_region(int r1, int c1, int r2, int c2) {\n    if (operation_count >= MAX_OPERATIONS - 15) return;\n    if (r1 > r2 || c1 > c2) return;\n    \n    int h = r2 - r1 + 1;\n    int w = c2 - c1 + 1;\n    int area = h * w;\n    \n    // Smaller base case\n    if (area <= 2) {\n        for (int r = r1; r <= r2; ++r) {\n            for (int c = c1; c <= c2; ++c) {\n                if (drilled_values.find({r, c}) == drilled_values.end()) {\n                    drill(r, c);\n                }\n            }\n        }\n        return;\n    }\n    \n    vector<pair<int, int>> cells;\n    cells.reserve(area);\n    for (int r = r1; r <= r2; ++r) {\n        for (int c = c1; c <= c2; ++c) {\n            cells.push_back({r, c});\n        }\n    }\n    \n    int k = cells.size();\n    int obs = divine(cells);\n    if (obs < 0) return;\n    \n    // 1 sigma threshold - more reliable\n    double empty_mean = k * epsilon;\n    double empty_std = sqrt(k * epsilon * (1.0 - epsilon));\n    double threshold = empty_mean + empty_std;\n    \n    if (obs < threshold) {\n        // Likely empty, always verify\n        int vr = r1 + (rng() % h);\n        int vc = c1 + (rng() % w);\n        int val = drill(vr, vc);\n        if (val > 0) {\n            // Has oil, recurse\n            int mid_r = (r1 + r2) / 2;\n            int mid_c = (c1 + c2) / 2;\n            search_region(r1, c1, mid_r, mid_c);\n            search_region(r1, mid_c + 1, mid_r, c2);\n            search_region(mid_r + 1, c1, r2, mid_c);\n            search_region(mid_r + 1, mid_c + 1, r2, c2);\n        }\n    } else {\n        // Has oil, recurse\n        int mid_r = (r1 + r2) / 2;\n        int mid_c = (c1 + c2) / 2;\n        search_region(r1, c1, mid_r, mid_c);\n        search_region(r1, mid_c + 1, mid_r, c2);\n        search_region(mid_r + 1, c1, r2, mid_c);\n        search_region(mid_r + 1, mid_c + 1, r2, c2);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> epsilon)) {\n        return 0;\n    }\n    \n    shapes.clear();\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        shapes[k].id = k;\n        int d;\n        cin >> d;\n        shapes[k].area = d;\n        shapes[k].cells.resize(d);\n        shapes[k].max_r = 0;\n        shapes[k].max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n            shapes[k].max_r = max(shapes[k].max_r, shapes[k].cells[i].first);\n            shapes[k].max_c = max(shapes[k].max_c, shapes[k].cells[i].second);\n        }\n    }\n    \n    // Use quadtree search with divination\n    search_region(0, 0, N - 1, N - 1);\n    \n    // Try to solve using shape constraints\n    vector<vector<pair<int, int>>> candidates;\n    generate_candidates(candidates);\n    \n    vector<pair<int, int>> config(M);\n    \n    if (try_solve(config, candidates)) {\n        vector<pair<int, int>> result;\n        set<pair<int, int>> result_set;\n        \n        // Add all drilled cells with v > 0 (required)\n        for (auto const& [pos, val] : drilled_values) {\n            if (val > 0) {\n                result_set.insert(pos);\n            }\n        }\n        \n        // Add all cells covered by config\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (predict_v(config, i, j) > 0) {\n                    result_set.insert({i, j});\n                }\n            }\n        }\n        \n        for (auto p : result_set) {\n            result.push_back(p);\n        }\n        submit(result);\n        return 0;\n    }\n    \n    // Fallback: drill all cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_values.find({i, j}) == drilled_values.end()) {\n                drill(i, j);\n            }\n        }\n    }\n    \n    generate_candidates(candidates);\n    if (try_solve(config, candidates)) {\n        vector<pair<int, int>> result;\n        set<pair<int, int>> result_set;\n        \n        for (auto const& [pos, val] : drilled_values) {\n            if (val > 0) {\n                result_set.insert(pos);\n            }\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (predict_v(config, i, j) > 0) {\n                    result_set.insert({i, j});\n                }\n            }\n        }\n        \n        for (auto p : result_set) {\n            result.push_back(p);\n        }\n        submit(result);\n        return 0;\n    }\n    \n    // Final fallback\n    vector<pair<int, int>> result;\n    set<pair<int, int>> result_set;\n    for (auto const& [pos, val] : drilled_values) {\n        if (val > 0) {\n            result_set.insert(pos);\n        }\n    }\n    for (auto p : result_set) {\n        result.push_back(p);\n    }\n    submit(result);\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\n\nbool checkOverlap(const vector<Rect>& day_rects, const Rect& new_rect, int exclude_idx) {\n    for (int i = 0; i < (int)day_rects.size(); i++) {\n        if (i == exclude_idx) continue;\n        if (!(day_rects[i].i1 <= new_rect.i0 ||\n              day_rects[i].i0 >= new_rect.i1 ||\n              day_rects[i].j1 <= new_rect.j0 ||\n              day_rects[i].j0 >= new_rect.j1)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nbool isValidRect(const Rect& r) {\n    return r.i0 >= 0 && r.i1 <= W && r.j0 >= 0 && r.j1 <= W && \n           r.i0 < r.i1 && r.j0 < r.j1;\n}\n\nlong long calculateAreaCost(int d) {\n    long long cost = 0;\n    for (int k = 0; k < N; k++) {\n        int actual = rects[d][k].area();\n        if (actual < a[d][k]) {\n            cost += 100LL * (a[d][k] - actual);\n        }\n    }\n    return cost;\n}\n\n// Fast partition cost using bitsets for comparison\nlong long calculatePartitionCost(int d) {\n    if (d == 0) return 0;\n    \n    long long cost = 0;\n    \n    // Build segment sets for both days\n    vector<vector<bool>> H_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> H_curr(W, vector<bool>(W, false));\n    vector<vector<bool>> V_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> V_curr(W, vector<bool>(W, false));\n    \n    for (int k = 0; k < N; k++) {\n        // Previous day\n        int i0 = rects[d-1][k].i0, i1 = rects[d-1][k].i1;\n        int j0 = rects[d-1][k].j0, j1 = rects[d-1][k].j1;\n        \n        if (i0 > 0 && i0 < W)\n            for (int j = j0; j < j1; j++) H_prev[i0][j] = true;\n        if (i1 > 0 && i1 < W)\n            for (int j = j0; j < j1; j++) H_prev[i1][j] = true;\n        if (j0 > 0 && j0 < W)\n            for (int i = i0; i < i1; i++) V_prev[i][j0] = true;\n        if (j1 > 0 && j1 < W)\n            for (int i = i0; i < i1; i++) V_prev[i][j1] = true;\n        \n        // Current day\n        i0 = rects[d][k].i0; i1 = rects[d][k].i1;\n        j0 = rects[d][k].j0; j1 = rects[d][k].j1;\n        \n        if (i0 > 0 && i0 < W)\n            for (int j = j0; j < j1; j++) H_curr[i0][j] = true;\n        if (i1 > 0 && i1 < W)\n            for (int j = j0; j < j1; j++) H_curr[i1][j] = true;\n        if (j0 > 0 && j0 < W)\n            for (int i = i0; i < i1; i++) V_curr[i][j0] = true;\n        if (j1 > 0 && j1 < W)\n            for (int i = i0; i < i1; i++) V_curr[i][j1] = true;\n    }\n    \n    for (int i = 1; i < W; i++)\n        for (int j = 0; j < W; j++)\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n    for (int i = 0; i < W; i++)\n        for (int j = 1; j < W; j++)\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n    \n    return cost;\n}\n\nlong long calculateTotalCost() {\n    long long total = 0;\n    for (int d = 0; d < D; d++) {\n        total += calculateAreaCost(d);\n        total += calculatePartitionCost(d);\n    }\n    return total;\n}\n\nvoid initializeSolution() {\n    rects.resize(D);\n    \n    for (int d = 0; d < D; d++) {\n        rects[d].resize(N);\n        \n        // Divide grid into N vertical strips - guaranteed non-overlapping\n        for (int k = 0; k < N; k++) {\n            int desired = a[d][k];\n            \n            int j0 = k * W / N;\n            int j1 = (k + 1) * W / N;\n            if (k == N - 1) j1 = W;\n            \n            // Find best height for desired area\n            int best_h = 1;\n            for (int h = 1; h <= W; h++) {\n                int area = h * (j1 - j0);\n                if (area >= desired) {\n                    best_h = h;\n                    break;\n                }\n            }\n            \n            best_h = min(best_h, W);\n            if (best_h == 0) best_h = 1;\n            rects[d][k] = {0, j0, best_h, j1};\n        }\n    }\n}\n\nvoid optimizeSolution() {\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Very limited optimization - just a few passes\n    int max_iterations = 3000;\n    int iterations = 0;\n    \n    while (iterations < max_iterations) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > 2.6) break;\n        \n        int d = (int)(dist(gen) * D);\n        int k = (int)(dist(gen) * N);\n        \n        Rect original = rects[d][k];\n        int attempts = 0;\n        bool valid = false;\n        Rect new_rect = original;\n        \n        while (attempts < 30 && !valid) {\n            int di = (int)((dist(gen) * 6 - 3));\n            int dj = (int)((dist(gen) * 6 - 3));\n            int dh = (int)((dist(gen) * 3 - 1));\n            int dw = (int)((dist(gen) * 3 - 1));\n            \n            int ni0 = max(0, min(W - 1, original.i0 + di));\n            int nj0 = max(0, min(W - 1, original.j0 + dj));\n            int ni1 = max(ni0 + 1, min(W, original.i1 + dh));\n            int nj1 = max(nj0 + 1, min(W, original.j1 + dw));\n            \n            new_rect = {ni0, nj0, ni1, nj1};\n            \n            if (isValidRect(new_rect) && !checkOverlap(rects[d], new_rect, k)) {\n                valid = true;\n            } else {\n                attempts++;\n            }\n        }\n        \n        if (valid) {\n            // Only accept if area improves (partition cost is secondary)\n            long long old_area = calculateAreaCost(d);\n            rects[d][k] = new_rect;\n            long long new_area = calculateAreaCost(d);\n            \n            // Accept if area improves or stays same\n            if (new_area <= old_area || dist(gen) < 0.1) {\n                // Keep new\n            } else {\n                rects[d][k] = original;\n            }\n        }\n        \n        iterations++;\n    }\n}\n\nvoid improveAreaSatisfaction() {\n    // Priority: satisfy area requirements (100x penalty)\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int current_area = rects[d][k].area();\n            if (current_area < a[d][k]) {\n                // Try to expand in all directions\n                int dirs[8][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, \n                                  {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};\n                \n                for (int dir = 0; dir < 8; dir++) {\n                    int di = dirs[dir][0];\n                    int dj = dirs[dir][1];\n                    \n                    int ni0 = rects[d][k].i0 + di;\n                    int nj0 = rects[d][k].j0 + dj;\n                    int ni1 = rects[d][k].i1 + di;\n                    int nj1 = rects[d][k].j1 + dj;\n                    \n                    if (isValidRect({ni0, nj0, ni1, nj1})) {\n                        Rect test_rect = {ni0, nj0, ni1, nj1};\n                        if (!checkOverlap(rects[d], test_rect, k)) {\n                            rects[d][k] = test_rect;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n    \n    initializeSolution();\n    optimizeSolution();\n    improveAreaSatisfaction();\n    \n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[d][k].i0 << \" \" << rects[d][k].j0 << \" \"\n                 << rects[d][k].i1 << \" \" << rects[d][k].j1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst long long MOD = 998244353;\n\n// Structures\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\n// Global variables\nint initial_board[N][N];\nint board[N][N];\nint stamps[M][3][3];\nlong long best_score;\nvector<Op> best_ops;\n\n// Random number generator\nmt19937_64 rng;\n\n// Function to calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += (board[i][j] % MOD);\n        }\n    }\n    return score;\n}\n\n// Function to apply an operation\nvoid apply_op(const Op& op, int val) {\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            board[op.p + i][op.q + j] += val * stamps[op.m][i][j];\n        }\n    }\n}\n\n// Function to calculate delta score for an operation\nlong long get_delta_score(const Op& op, int val) {\n    long long delta = 0;\n    for (int i = 0; i < 3; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            int r = op.p + i;\n            int c = op.q + j;\n            long long old_val = board[r][c] % MOD;\n            long long new_val = (board[r][c] + val * stamps[op.m][i][j]) % MOD;\n            delta += new_val - old_val;\n        }\n    }\n    return delta;\n}\n\n// Global function to reset board\nvoid reset_board() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = initial_board[i][j];\n        }\n    }\n}\n\n// Solver class to manage state for each restart\nstruct Solver {\n    vector<Op> ops;\n    long long score;\n    double temperature;\n    int iterations;\n    \n    Solver() : temperature(1e9), iterations(0) {}\n    \n    void init_random() {\n        ops.clear();\n        ops.reserve(K);\n        uniform_int_distribution<int> dist_m(0, M - 1);\n        uniform_int_distribution<int> dist_p(0, N - 3);\n        uniform_int_distribution<int> dist_q(0, N - 3);\n        \n        for (int i = 0; i < K; ++i) {\n            ops.push_back({dist_m(rng), dist_p(rng), dist_q(rng)});\n        }\n        \n        reset_board();\n        for (const auto& op : ops) {\n            apply_op(op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void init_greedy() {\n        ops.clear();\n        ops.reserve(K);\n        \n        reset_board();\n        \n        // Greedy initialization\n        for (int iter = 0; iter < K; ++iter) {\n            long long max_delta = -1e18;\n            Op best_op = {0, 0, 0};\n            \n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            \n            for (int sample = 0; sample < 400; ++sample) {\n                Op op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n                long long delta = get_delta_score(op, 1);\n                if (delta > max_delta) {\n                    max_delta = delta;\n                    best_op = op;\n                }\n            }\n            \n            ops.push_back(best_op);\n            apply_op(best_op, 1);\n        }\n        \n        score = calculate_score();\n        temperature = 1e9;\n        iterations = 0;\n    }\n    \n    void step() {\n        iterations++;\n        \n        // Select a random operation index to change\n        uniform_int_distribution<int> dist_idx(0, K - 1);\n        int idx = dist_idx(rng);\n        Op old_op = ops[idx];\n        \n        // Decide move type\n        uniform_real_distribution<double> dist_type(0.0, 1.0);\n        double r = dist_type(rng);\n        \n        Op new_op = old_op;\n        \n        if (r < 0.05) {\n            // 5%: Full random replacement\n            uniform_int_distribution<int> dist_m(0, M - 1);\n            uniform_int_distribution<int> dist_p(0, N - 3);\n            uniform_int_distribution<int> dist_q(0, N - 3);\n            new_op.m = dist_m(rng);\n            new_op.p = dist_p(rng);\n            new_op.q = dist_q(rng);\n        } else if (r < 0.30) {\n            // 25%: Change stamp type\n            uniform_real_distribution<double> dist_m_change(0.0, 1.0);\n            if (dist_m_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_m(0, M - 1);\n                new_op.m = dist_m(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.m = (old_op.m + delta + M) % M;\n            }\n        } else if (r < 0.55) {\n            // 25%: Change p position\n            uniform_real_distribution<double> dist_p_change(0.0, 1.0);\n            if (dist_p_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                new_op.p = dist_p(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta));\n            }\n        } else if (r < 0.80) {\n            // 25%: Change q position\n            uniform_real_distribution<double> dist_q_change(0.0, 1.0);\n            if (dist_q_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta = (rng() % 3) - 1;\n                new_op.q = max(0, min(N - 3, old_op.q + delta));\n            }\n        } else {\n            // 20%: Change both p and q\n            uniform_real_distribution<double> dist_pq_change(0.0, 1.0);\n            if (dist_pq_change(rng) < 0.3) {\n                uniform_int_distribution<int> dist_p(0, N - 3);\n                uniform_int_distribution<int> dist_q(0, N - 3);\n                new_op.p = dist_p(rng);\n                new_op.q = dist_q(rng);\n            } else {\n                int delta_p = (rng() % 3) - 1;\n                int delta_q = (rng() % 3) - 1;\n                new_op.p = max(0, min(N - 3, old_op.p + delta_p));\n                new_op.q = max(0, min(N - 3, old_op.q + delta_q));\n            }\n        }\n        \n        // Calculate delta\n        long long delta = 0;\n        \n        // Remove old op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = old_op.p + i;\n                int c = old_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                if (temp_val < 0) temp_val += MOD;\n                delta += temp_val - old_val;\n            }\n        }\n        \n        // Add new op effect\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int r = new_op.p + i;\n                int c = new_op.q + j;\n                long long old_val = board[r][c] % MOD;\n                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                delta += new_val - old_val;\n            }\n        }\n        \n        // Acceptance probability\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            uniform_real_distribution<double> dist_prob(0.0, 1.0);\n            double prob = exp(delta / temperature);\n            if (dist_prob(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            ops[idx] = new_op;\n            // Apply the change to the board\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = old_op.p + i;\n                    int c = old_op.q + j;\n                    board[r][c] -= stamps[old_op.m][i][j];\n                }\n            }\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int r = new_op.p + i;\n                    int c = new_op.q + j;\n                    board[r][c] += stamps[new_op.m][i][j];\n                }\n            }\n            score += delta;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_ops = ops;\n            }\n        }\n        \n        // Cool down\n        temperature *= 0.9998;\n        if (temperature < 1e-9) temperature = 1e-9;\n    }\n    \n    void local_search(int max_iterations) {\n        // Efficient local search with sampling\n        int improved = 1;\n        int iter_count = 0;\n        \n        while (improved && iter_count < max_iterations) {\n            improved = 0;\n            iter_count++;\n            \n            // Sample random operations to modify\n            for (int sample = 0; sample < 30; ++sample) {\n                uniform_int_distribution<int> dist_idx(0, K - 1);\n                int idx = dist_idx(rng);\n                Op old_op = ops[idx];\n                \n                // Try limited number of changes\n                for (int try_count = 0; try_count < 15; ++try_count) {\n                    uniform_int_distribution<int> dist_m(0, M - 1);\n                    uniform_int_distribution<int> dist_p(0, N - 3);\n                    uniform_int_distribution<int> dist_q(0, N - 3);\n                    \n                    Op new_op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n                    \n                    // Calculate delta\n                    long long delta = 0;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            int r = old_op.p + i;\n                            int c = old_op.q + j;\n                            long long old_val = board[r][c] % MOD;\n                            long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                            if (temp_val < 0) temp_val += MOD;\n                            delta += temp_val - old_val;\n                        }\n                    }\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            int r = new_op.p + i;\n                            int c = new_op.q + j;\n                            long long old_val = board[r][c] % MOD;\n                            long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                            delta += new_val - old_val;\n                        }\n                    }\n                    \n                    if (delta > 0) {\n                        // Apply the change\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = old_op.p + i;\n                                int c = old_op.q + j;\n                                board[r][c] -= stamps[old_op.m][i][j];\n                            }\n                        }\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = new_op.p + i;\n                                int c = new_op.q + j;\n                                board[r][c] += stamps[new_op.m][i][j];\n                            }\n                        }\n                        ops[idx] = new_op;\n                        score += delta;\n                        improved = 1;\n                        iterations++;\n                        \n                        if (score > best_score) {\n                            best_score = score;\n                            best_ops = ops;\n                        }\n                        \n                        // Break and restart search after improvement\n                        goto next_sample;\n                    }\n                }\n                next_sample:;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    // Read board\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> board[i][j];\n            initial_board[i][j] = board[i][j];\n        }\n    }\n\n    // Read stamps\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < 3; ++j) {\n            for (int l = 0; l < 3; ++l) {\n                cin >> stamps[i][j][l];\n            }\n        }\n    }\n\n    best_score = -1;\n    best_ops.clear();\n\n    // Time management\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::milliseconds(1950); // Leave 50ms for output\n    \n    Solver solver;\n    int restart_count = 0;\n    \n    // Multiple restarts with mixed initialization\n    while (chrono::steady_clock::now() < end_time) {\n        restart_count++;\n        \n        // Alternate between random and greedy initialization\n        if (restart_count % 2 == 1) {\n            solver.init_greedy();\n        } else {\n            solver.init_random();\n        }\n        \n        // Run SA for shorter periods\n        int sa_iterations = 0;\n        while (chrono::steady_clock::now() < end_time && \n               solver.temperature > 1e-9 && \n               sa_iterations < 4000) {\n            solver.step();\n            sa_iterations++;\n            if (solver.temperature < 1e-9) break;\n        }\n        \n        // Final local search with limited iterations\n        solver.local_search(150);\n    }\n\n    // Final exhaustive local search on best solution\n    auto final_end = start_time + chrono::milliseconds(1990);\n    \n    // Load best solution\n    reset_board();\n    for (const auto& op : best_ops) {\n        apply_op(op, 1);\n    }\n    \n    // Try to improve each operation - single pass to save time\n    int improved = 1;\n    while (improved && chrono::steady_clock::now() < final_end) {\n        improved = 0;\n        for (int idx = 0; idx < K && chrono::steady_clock::now() < final_end; ++idx) {\n            Op old_op = best_ops[idx];\n            \n            // Try all possible changes for this operation\n            for (int sm = 0; sm < M && chrono::steady_clock::now() < final_end; ++sm) {\n                for (int sp = 0; sp <= N - 3 && chrono::steady_clock::now() < final_end; ++sp) {\n                    for (int sq = 0; sq <= N - 3 && chrono::steady_clock::now() < final_end; ++sq) {\n                        if (sm == old_op.m && sp == old_op.p && sq == old_op.q) continue;\n                        \n                        Op new_op = {sm, sp, sq};\n                        \n                        // Calculate delta\n                        long long delta = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = old_op.p + i;\n                                int c = old_op.q + j;\n                                long long old_val = board[r][c] % MOD;\n                                long long temp_val = (board[r][c] - stamps[old_op.m][i][j]) % MOD;\n                                if (temp_val < 0) temp_val += MOD;\n                                delta += temp_val - old_val;\n                            }\n                        }\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                int r = new_op.p + i;\n                                int c = new_op.q + j;\n                                long long old_val = board[r][c] % MOD;\n                                long long new_val = (board[r][c] + stamps[new_op.m][i][j]) % MOD;\n                                delta += new_val - old_val;\n                            }\n                        }\n                        \n                        if (delta > 0) {\n                            // Apply the change\n                            for (int i = 0; i < 3; ++i) {\n                                for (int j = 0; j < 3; ++j) {\n                                    int r = old_op.p + i;\n                                    int c = old_op.q + j;\n                                    board[r][c] -= stamps[old_op.m][i][j];\n                                }\n                            }\n                            for (int i = 0; i < 3; ++i) {\n                                for (int j = 0; j < 3; ++j) {\n                                    int r = new_op.p + i;\n                                    int c = new_op.q + j;\n                                    board[r][c] += stamps[new_op.m][i][j];\n                                }\n                            }\n                            best_ops[idx] = new_op;\n                            best_score += delta;\n                            improved = 1;\n                            break;\n                        }\n                    }\n                    if (improved) break;\n                }\n                if (improved) break;\n            }\n        }\n    }\n\n    // Output best solution\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int EMPTY = -1;\n\nstruct Crane {\n    int id;\n    int x, y; // x = row, y = column\n    int holding; // Container ID or EMPTY\n    bool is_large;\n    bool active;\n};\n\nstruct State {\n    int grid[N][N];\n    vector<Crane> cranes;\n    vector<vector<int>> input_queue;\n    vector<int> dispatch_count;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = EMPTY;\n            input_queue.push_back({});\n            dispatch_count.push_back(0);\n        }\n        cranes.resize(N);\n        for(int i=0; i<N; ++i) {\n            cranes[i] = {i, i, 0, EMPTY, (i == 0), true};\n        }\n    }\n};\n\n// Fast validity check for single crane action\nbool isActionValid(const Crane& c, char action, const State& s) {\n    if (!c.active) return false;\n    int nx = c.x, ny = c.y;\n    int holding = c.holding;\n\n    if (action == 'P') {\n        return holding == EMPTY && s.grid[c.x][c.y] != EMPTY;\n    }\n    if (action == 'Q') {\n        return holding != EMPTY && s.grid[c.x][c.y] == EMPTY;\n    }\n    if (action == 'B') {\n        return holding == EMPTY;\n    }\n    // x is row (down), y is column (right)\n    if (action == 'U') nx--;\n    else if (action == 'D') nx++;\n    else if (action == 'L') ny--;\n    else if (action == 'R') ny++;\n    else if (action == '.') return true;\n    else return false;\n\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    if (!c.is_large && holding != EMPTY && s.grid[nx][ny] != EMPTY) return false;\n    return true;\n}\n\n// Get next position after action\npair<int,int> getNextPos(const Crane& c, char action) {\n    int nx = c.x, ny = c.y;\n    if (action == 'U') nx--;\n    else if (action == 'D') nx++;\n    else if (action == 'L') ny--;\n    else if (action == 'R') ny++;\n    return {nx, ny};\n}\n\n// Check collision between two cranes\nbool hasCollision(const Crane& c1, char a1, const Crane& c2, char a2) {\n    if (!c1.active || !c2.active) return false;\n    \n    pair<int,int> p1 = getNextPos(c1, a1);\n    pair<int,int> p2 = getNextPos(c2, a2);\n    \n    // Overlap\n    if (p1 == p2) return true;\n    \n    // Swap\n    if (p1 == make_pair(c2.x, c2.y) && p2 == make_pair(c1.x, c1.y)) return true;\n    \n    return false;\n}\n\n// Get priority score for an action (higher is better)\nint getActionPriority(const Crane& c, char action, const State& s) {\n    if (!isActionValid(c, action, s)) return -1e9;\n    \n    int priority = 0;\n    int holding = c.holding;\n    \n    // Picking at receiving gate is very important\n    if (action == 'P' && c.y == 0 && s.grid[c.x][c.y] != EMPTY) {\n        priority += 1000;\n    }\n    \n    // Dropping at dispatch gate is very important\n    if (action == 'Q' && c.y == N-1 && holding != EMPTY) {\n        if (holding / N == c.x) {\n            priority += 1000;\n        } else {\n            priority += 100;\n        }\n    }\n    \n    // Moving towards target\n    if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n        int target_y = (holding != EMPTY) ? N-1 : 0;\n        int dist_before = abs(c.y - target_y);\n        int ny = c.y;\n        if (action == 'L') ny--;\n        else if (action == 'R') ny++;\n        int dist_after = abs(ny - target_y);\n        if (dist_after < dist_before) {\n            priority += 100;\n        }\n        \n        // Move away from receiving gate if blocking\n        if (c.y == 0 && s.input_queue[c.x].empty()) {\n            if (action == 'R') {\n                priority += 50;\n            }\n        }\n    }\n    \n    if (action != '.' && action != 'B') {\n        priority += 10;\n    }\n    \n    return priority;\n}\n\n// Simulate one turn\nvoid simulateTurn(State& s, const vector<char>& actions) {\n    // Step 1: Receiving Gates\n    for(int i=0; i<N; ++i) {\n        if (!s.input_queue[i].empty()) {\n            bool blocked = false;\n            if (s.grid[i][0] != EMPTY) blocked = true;\n            for(const auto& c : s.cranes) {\n                if (c.active && c.x == i && c.y == 0) blocked = true;\n            }\n            if (!blocked) {\n                s.grid[i][0] = s.input_queue[i].front();\n                s.input_queue[i].erase(s.input_queue[i].begin());\n            }\n        }\n    }\n    \n    // Step 2: Crane Actions\n    int next_grid[N][N];\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            next_grid[i][j] = s.grid[i][j];\n        }\n    }\n    \n    // Apply P\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        if (actions[i] == 'P') {\n            next_grid[s.cranes[i].x][s.cranes[i].y] = EMPTY;\n            s.cranes[i].holding = s.grid[s.cranes[i].x][s.cranes[i].y];\n        }\n    }\n    \n    // Apply Q\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        if (actions[i] == 'Q') {\n            next_grid[s.cranes[i].x][s.cranes[i].y] = s.cranes[i].holding;\n            s.cranes[i].holding = EMPTY;\n        }\n    }\n    \n    // Apply Move/Bomb\n    for(int i=0; i<N; ++i) {\n        if (!s.cranes[i].active) continue;\n        char act = actions[i];\n        if (act == 'B') {\n            s.cranes[i].active = false;\n        } else if (act == 'U') s.cranes[i].x--;\n        else if (act == 'D') s.cranes[i].x++;\n        else if (act == 'L') s.cranes[i].y--;\n        else if (act == 'R') s.cranes[i].y++;\n    }\n    \n    // Update grid\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            s.grid[i][j] = next_grid[i][j];\n        }\n    }\n    \n    // Step 3: Dispatch\n    for(int i=0; i<N; ++i) {\n        int container = s.grid[i][4];\n        if (container != EMPTY) {\n            int expected = N * i + s.dispatch_count[i];\n            if (container == expected) {\n                s.dispatch_count[i]++;\n                s.grid[i][4] = EMPTY;\n            }\n        }\n    }\n}\n\n// Get all valid actions for a crane\nvector<char> getValidActions(const Crane& c, const State& s) {\n    vector<char> actions;\n    if (!c.active) {\n        actions.push_back('.');\n        return actions;\n    }\n    \n    vector<char> candidates = {'P', 'Q', 'U', 'D', 'L', 'R', '.'};\n    for(char a : candidates) {\n        if (isActionValid(c, a, s)) {\n            actions.push_back(a);\n        }\n    }\n    return actions;\n}\n\n// Check if a set of actions has any collisions\nbool hasAnyCollision(const vector<char>& actions, const State& s) {\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if (hasCollision(s.cranes[i], actions[i], s.cranes[j], actions[j])) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int N_in;\n    if (!(cin >> N_in)) return 0;\n    \n    State s;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int val;\n            cin >> val;\n            s.input_queue[i].push_back(val);\n        }\n    }\n    \n    vector<string> result(N, \"\");\n    \n    auto start_time = chrono::steady_clock::now();\n    int time_limit_ms = 2800;\n    \n    for(int t=0; t<MAX_TURNS; ++t) {\n        auto current_time = chrono::steady_clock::now();\n        int elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n        \n        bool all_dispatched = true;\n        for(int i=0; i<N; ++i) {\n            if (s.dispatch_count[i] < N) {\n                all_dispatched = false;\n                break;\n            }\n        }\n        if (all_dispatched) break;\n        \n        // Get valid actions for each crane\n        vector<vector<char>> valid_actions(N);\n        for(int i=0; i<N; ++i) {\n            valid_actions[i] = getValidActions(s.cranes[i], s);\n        }\n        \n        // Find best collision-free action combination\n        // Use greedy approach with backtracking for small N\n        vector<char> best_actions(N, '.');\n        int best_score = -1e9;\n        \n        // Try all combinations (at most 7^5 = 16807, but usually much less)\n        // Use recursive search with pruning\n        auto search = [&](auto&& self, int idx, vector<char>& current, int& score) -> void {\n            if (idx == N) {\n                if (!hasAnyCollision(current, s)) {\n                    // Calculate score\n                    int sc = 0;\n                    for(int i=0; i<N; ++i) {\n                        sc += getActionPriority(s.cranes[i], current[i], s);\n                    }\n                    if (sc > best_score) {\n                        best_score = sc;\n                        best_actions = current;\n                    }\n                }\n                return;\n            }\n            \n            for(char a : valid_actions[idx]) {\n                current[idx] = a;\n                self(self, idx + 1, current, score);\n            }\n        };\n        \n        vector<char> current(N);\n        int dummy = 0;\n        search(search, 0, current, dummy);\n        \n        // Apply actions\n        for(int i=0; i<N; ++i) {\n            result[i] += best_actions[i];\n        }\n        \n        simulateTurn(s, best_actions);\n    }\n    \n    for(int i=0; i<N; ++i) {\n        cout << result[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nint dist(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nstruct Solution {\n    vector<vector<pair<int, int>>> requests;\n    vector<int> source_order;\n    vector<vector<int>> sink_orders;\n    long long cost = -1;\n    int num_sources;\n    \n    void calculate_cost(const vector<Point>& sources, const vector<Point>& sinks) {\n        long long total_cost = 0;\n        int cx = 0, cy = 0;\n        int cur_load = 0;\n        \n        for (int src_idx : source_order) {\n            if (sink_orders[src_idx].empty()) continue;\n            \n            int d = dist({cx, cy}, sources[src_idx]);\n            total_cost += d * 100;\n            cx = sources[src_idx].x;\n            cy = sources[src_idx].y;\n            \n            int total_load = 0;\n            for (int sink_idx : sink_orders[src_idx]) {\n                total_load += requests[src_idx][sink_idx].second;\n            }\n            total_cost += total_load;\n            cur_load = total_load;\n            \n            for (int sink_idx : sink_orders[src_idx]) {\n                int v_idx = requests[src_idx][sink_idx].first;\n                int amount = requests[src_idx][sink_idx].second;\n                int tx = sinks[v_idx].x;\n                int ty = sinks[v_idx].y;\n                \n                d = dist({cx, cy}, {tx, ty});\n                total_cost += d * (100 + cur_load);\n                cx = tx;\n                cy = ty;\n                total_cost += amount;\n                cur_load -= amount;\n            }\n        }\n        cost = total_cost;\n    }\n};\n\nSolution solve_with_matching(const vector<Point>& sources, const vector<Point>& sinks,\n                             vector<int> remaining_supply, vector<int> remaining_demand,\n                             bool weighted = false) {\n    Solution sol;\n    sol.requests.resize(sources.size());\n    sol.sink_orders.resize(sources.size());\n    sol.num_sources = sources.size();\n    \n    // Matching\n    vector<int> temp_supply = remaining_supply;\n    vector<int> temp_demand = remaining_demand;\n    \n    while (true) {\n        int best_u = -1, best_v = -1;\n        int min_val = 1e9;\n        \n        for (int i = 0; i < (int)sources.size(); ++i) {\n            if (temp_supply[i] <= 0) continue;\n            for (int j = 0; j < (int)sinks.size(); ++j) {\n                if (temp_demand[j] <= 0) continue;\n                int d = dist(sources[i], sinks[j]);\n                int val = weighted ? d * min(temp_supply[i], temp_demand[j]) : d;\n                if (val < min_val) {\n                    min_val = val;\n                    best_u = i;\n                    best_v = j;\n                }\n            }\n        }\n        \n        if (best_u == -1) break;\n        \n        int amount = min(temp_supply[best_u], temp_demand[best_v]);\n        temp_supply[best_u] -= amount;\n        temp_demand[best_v] -= amount;\n        sol.requests[best_u].push_back({best_v, amount});\n    }\n    \n    // Optimize sink ordering with nearest neighbor + 2-opt\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        if (sol.requests[i].empty()) continue;\n        \n        sol.sink_orders[i].resize(sol.requests[i].size());\n        vector<bool> sink_done(sol.requests[i].size(), false);\n        int cur_x = sources[i].x, cur_y = sources[i].y;\n        \n        for (size_t k = 0; k < sol.requests[i].size(); ++k) {\n            int best_v = -1;\n            int min_d = 1e9;\n            for (size_t idx = 0; idx < sol.requests[i].size(); ++idx) {\n                if (!sink_done[idx]) {\n                    int v_idx = sol.requests[i][idx].first;\n                    int d = dist({cur_x, cur_y}, sinks[v_idx]);\n                    if (d < min_d) {\n                        min_d = d;\n                        best_v = (int)idx;\n                    }\n                }\n            }\n            if (best_v != -1) {\n                sink_done[best_v] = true;\n                sol.sink_orders[i][k] = best_v;\n                int v_idx = sol.requests[i][best_v].first;\n                cur_x = sinks[v_idx].x;\n                cur_y = sinks[v_idx].y;\n            }\n        }\n        \n        // 2-opt for sink ordering\n        bool sink_improved = true;\n        while (sink_improved) {\n            sink_improved = false;\n            for (size_t a = 0; a < sol.sink_orders[i].size() - 1; ++a) {\n                for (size_t b = a + 1; b < sol.sink_orders[i].size(); ++b) {\n                    auto calc = [&]() {\n                        int cost = 0;\n                        int cx = sources[i].x, cy = sources[i].y;\n                        for (size_t k = 0; k < sol.sink_orders[i].size(); ++k) {\n                            int v_idx = sol.requests[i][sol.sink_orders[i][k]].first;\n                            cost += dist({cx, cy}, sinks[v_idx]);\n                            cx = sinks[v_idx].x;\n                            cy = sinks[v_idx].y;\n                        }\n                        return cost;\n                    };\n                    \n                    int old_cost = calc();\n                    reverse(sol.sink_orders[i].begin() + a, sol.sink_orders[i].begin() + b + 1);\n                    int new_cost = calc();\n                    \n                    if (new_cost >= old_cost) {\n                        reverse(sol.sink_orders[i].begin() + a, sol.sink_orders[i].begin() + b + 1);\n                    } else {\n                        sink_improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Calculate end positions\n    vector<Point> source_end(sources.size());\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        if (sol.sink_orders[i].empty()) {\n            source_end[i] = sources[i];\n        } else {\n            int last_sink = sol.requests[i][sol.sink_orders[i].back()].first;\n            source_end[i] = sinks[last_sink];\n        }\n    }\n    \n    // Source ordering with nearest neighbor\n    sol.source_order.resize(sources.size());\n    for (int i = 0; i < (int)sources.size(); ++i) {\n        sol.source_order[i] = i;\n    }\n    \n    vector<bool> visited(sources.size(), false);\n    int cur_x = 0, cur_y = 0;\n    for (int iter = 0; iter < (int)sources.size(); ++iter) {\n        int best = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); ++i) {\n            if (!visited[i] && !sol.requests[i].empty()) {\n                int d = dist({cur_x, cur_y}, sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best = i;\n                }\n            }\n        }\n        if (best != -1) {\n            visited[best] = true;\n            sol.source_order[iter] = best;\n            cur_x = source_end[best].x;\n            cur_y = source_end[best].y;\n        }\n    }\n    \n    // 2-opt for source ordering\n    bool src_improved = true;\n    while (src_improved) {\n        src_improved = false;\n        for (int i = 0; i < (int)sources.size() - 1; ++i) {\n            for (int j = i + 1; j < (int)sources.size(); ++j) {\n                auto calc = [&]() {\n                    int cost = 0;\n                    int cx = 0, cy = 0;\n                    for (int idx : sol.source_order) {\n                        cost += dist({cx, cy}, sources[idx]);\n                        cx = source_end[idx].x;\n                        cy = source_end[idx].y;\n                    }\n                    return cost;\n                };\n                \n                int old_cost = calc();\n                reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                int new_cost = calc();\n                \n                if (new_cost >= old_cost) {\n                    reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                } else {\n                    src_improved = true;\n                }\n            }\n        }\n    }\n    \n    sol.calculate_cost(sources, sinks);\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<vector<int>> h(N, vector<int>(N));\n    vector<Point> sources, sinks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n            }\n        }\n    }\n\n    int num_sources = sources.size();\n    int num_sinks = sinks.size();\n\n    vector<int> remaining_supply(num_sources);\n    vector<int> remaining_demand(num_sinks, 0);\n    \n    for (int i = 0; i < num_sources; ++i) {\n        remaining_supply[i] = h[sources[i].x][sources[i].y];\n    }\n    for (int i = 0; i < num_sinks; ++i) {\n        remaining_demand[i] = abs(h[sinks[i].x][sinks[i].y]);\n    }\n\n    Solution best_sol;\n    best_sol.num_sources = num_sources;\n    \n    // Try greedy matching\n    Solution sol1 = solve_with_matching(sources, sinks, remaining_supply, remaining_demand, false);\n    if (sol1.cost < best_sol.cost || best_sol.cost == -1) {\n        best_sol = sol1;\n    }\n    \n    // Try weighted matching\n    Solution sol2 = solve_with_matching(sources, sinks, remaining_supply, remaining_demand, true);\n    if (sol2.cost < best_sol.cost || best_sol.cost == -1) {\n        best_sol = sol2;\n    }\n    \n    // Try random perturbations of source order\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int trial = 0; trial < 10; ++trial) {\n        Solution sol = best_sol;\n        shuffle(sol.source_order.begin(), sol.source_order.end(), rng);\n        \n        // Re-optimize with 2-opt\n        vector<Point> source_end(num_sources);\n        for (int i = 0; i < num_sources; ++i) {\n            if (sol.sink_orders[i].empty()) {\n                source_end[i] = sources[i];\n            } else {\n                int last_sink = sol.requests[i][sol.sink_orders[i].back()].first;\n                source_end[i] = sinks[last_sink];\n            }\n        }\n        \n        bool src_improved = true;\n        while (src_improved) {\n            src_improved = false;\n            for (int i = 0; i < num_sources - 1; ++i) {\n                for (int j = i + 1; j < num_sources; ++j) {\n                    auto calc = [&]() {\n                        int cost = 0;\n                        int cx = 0, cy = 0;\n                        for (int idx : sol.source_order) {\n                            cost += dist({cx, cy}, sources[idx]);\n                            cx = source_end[idx].x;\n                            cy = source_end[idx].y;\n                        }\n                        return cost;\n                    };\n                    \n                    int old_cost = calc();\n                    reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                    int new_cost = calc();\n                    \n                    if (new_cost >= old_cost) {\n                        reverse(sol.source_order.begin() + i, sol.source_order.begin() + j + 1);\n                    } else {\n                        src_improved = true;\n                    }\n                }\n            }\n        }\n        \n        sol.calculate_cost(sources, sinks);\n        if (sol.cost < best_sol.cost || best_sol.cost == -1) {\n            best_sol = sol;\n        }\n    }\n\n    // Routing\n    int cx = 0, cy = 0;\n    vector<string> ops;\n    \n    auto move_to = [&](int tx, int ty) {\n        while (cx < tx) {\n            cx++;\n            ops.push_back(\"D\");\n        }\n        while (cx > tx) {\n            cx--;\n            ops.push_back(\"U\");\n        }\n        while (cy < ty) {\n            cy++;\n            ops.push_back(\"R\");\n        }\n        while (cy > ty) {\n            cy--;\n            ops.push_back(\"L\");\n        }\n    };\n\n    auto load = [&](int amount) {\n        ops.push_back(\"+\" + to_string(amount));\n    };\n\n    auto unload = [&](int amount) {\n        ops.push_back(\"-\" + to_string(amount));\n    };\n\n    // Execute optimized tour\n    for (int src_idx : best_sol.source_order) {\n        if (best_sol.sink_orders[src_idx].empty()) continue;\n        \n        move_to(sources[src_idx].x, sources[src_idx].y);\n\n        int total_load = 0;\n        for (int sink_idx : best_sol.sink_orders[src_idx]) {\n            total_load += best_sol.requests[src_idx][sink_idx].second;\n        }\n        if (total_load > 0) {\n            load(total_load);\n        }\n\n        for (int sink_idx : best_sol.sink_orders[src_idx]) {\n            int v_idx = best_sol.requests[src_idx][sink_idx].first;\n            int amount = best_sol.requests[src_idx][sink_idx].second;\n            int tx = sinks[v_idx].x;\n            int ty = sinks[v_idx].y;\n            \n            move_to(tx, ty);\n            unload(amount);\n        }\n    }\n\n    // Output\n    for (const string &s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\nint N, M, T;\nint seed_count;\nvector<vector<int>> seeds;\nvector<int> seed_val;\nvector<vector<int>> adj;\nvector<int> pos_neighbors;\nvector<int> grid;\nlong long current_score;\n\n// Random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\n// Enhanced complementarity metric with better diversity scoring\ninline long long calc_complementarity(int u, int v) {\n    long long s = 0;\n    int diversity = 0;\n    int strong_diff = 0;\n    \n    for (int l = 0; l < M; ++l) {\n        int a = seeds[u][l];\n        int b = seeds[v][l];\n        s += (a > b ? a : b);\n        \n        // Bonus for complementary patterns\n        if (a > 60 && b < 35) { diversity += 4; strong_diff++; }\n        else if (a > 55 && b < 30) { diversity += 3; strong_diff++; }\n        else if (a > 50 && b < 25) { diversity += 2; strong_diff++; }\n        else if (abs(a - b) > 30) { diversity += 2; }\n        else if (abs(a - b) > 20) { diversity += 1; }\n    }\n    \n    // Extra bonus if seeds have different strong criteria\n    if (strong_diff >= 3) diversity += 5;\n    \n    return s + diversity;\n}\n\n// Calculate total score for current grid configuration\ninline long long calc_grid_score() {\n    long long total = 0;\n    for (int i = 0; i < N * N; ++i) {\n        for (int n : adj[i]) {\n            if (i < n) {\n                total += calc_complementarity(grid[i], grid[n]) * pos_neighbors[i];\n            }\n        }\n    }\n    return total;\n}\n\nvoid init_adj() {\n    adj.assign(N * N, vector<int>());\n    pos_neighbors.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (i > 0) { adj[u].push_back((i - 1) * N + j); pos_neighbors[u]++; }\n            if (i < N - 1) { adj[u].push_back((i + 1) * N + j); pos_neighbors[u]++; }\n            if (j > 0) { adj[u].push_back(i * N + (j - 1)); pos_neighbors[u]++; }\n            if (j < N - 1) { adj[u].push_back(i * N + (j + 1)); pos_neighbors[u]++; }\n        }\n    }\n}\n\n// Initialize grid with different strategies\nvoid init_grid(int strategy) {\n    vector<int> p(seed_count);\n    iota(p.begin(), p.end(), 0);\n    \n    if (strategy == 0) {\n        // Sort by total value\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            return seed_val[a] > seed_val[b];\n        });\n    } else if (strategy == 1) {\n        // Sort by max criterion value\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            int max_a = 0, max_b = 0;\n            for (int l = 0; l < M; ++l) {\n                max_a = max(max_a, seeds[a][l]);\n                max_b = max(max_b, seeds[b][l]);\n            }\n            return max_a > max_b;\n        });\n    } else if (strategy == 2) {\n        // Sort by diversity (number of high-value criteria)\n        sort(p.begin(), p.end(), [&](int a, int b) {\n            int div_a = 0, div_b = 0;\n            for (int l = 0; l < M; ++l) {\n                div_a += (seeds[a][l] > 50 ? 1 : 0);\n                div_b += (seeds[b][l] > 50 ? 1 : 0);\n            }\n            return div_a > div_b;\n        });\n    } else {\n        // Random order\n        shuffle(p.begin(), p.end(), gen);\n    }\n    \n    vector<int> pos_order(N * N);\n    iota(pos_order.begin(), pos_order.end(), 0);\n    sort(pos_order.begin(), pos_order.end(), [&](int a, int b) {\n        return pos_neighbors[a] > pos_neighbors[b];\n    });\n    \n    for (int k = 0; k < N * N; ++k) {\n        grid[pos_order[k]] = p[k];\n    }\n    \n    current_score = calc_grid_score();\n}\n\nvoid sa_optimize(int iterations) {\n    uniform_int_distribution<int> dist_pos(0, N * N - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n    \n    double temp = 5000.0;\n    double cooling = 0.998;\n    \n    for (int iter = 0; iter < iterations; ++iter) {\n        int u = dist_pos(gen);\n        int v = dist_pos(gen);\n        if (u == v) continue;\n        \n        long long old_score = current_score;\n        \n        long long delta = 0;\n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta -= calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta -= calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n        }\n        \n        swap(grid[u], grid[v]);\n        \n        for (int n : adj[u]) {\n            if (n == v) continue;\n            delta += calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n        }\n        for (int n : adj[v]) {\n            if (n == u) continue;\n            delta += calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n        }\n        \n        if (delta >= 0 || dist_prob(gen) < exp(delta / temp)) {\n            current_score += delta;\n        } else {\n            swap(grid[u], grid[v]);\n            current_score = old_score;\n        }\n        \n        temp *= cooling;\n    }\n}\n\nvoid local_refinement() {\n    // Quick local search - try swapping each pair once\n    for (int u = 0; u < N * N; ++u) {\n        for (int v = u + 1; v < N * N; ++v) {\n            long long old_score = current_score;\n            \n            long long delta = 0;\n            for (int n : adj[u]) {\n                if (n == v) continue;\n                delta -= calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n            }\n            for (int n : adj[v]) {\n                if (n == u) continue;\n                delta -= calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n            }\n            \n            swap(grid[u], grid[v]);\n            \n            for (int n : adj[u]) {\n                if (n == v) continue;\n                delta += calc_complementarity(grid[u], grid[n]) * pos_neighbors[u];\n            }\n            for (int n : adj[v]) {\n                if (n == u) continue;\n                delta += calc_complementarity(grid[v], grid[n]) * pos_neighbors[v];\n            }\n            \n            if (delta > 0) {\n                current_score += delta;\n            } else {\n                swap(grid[u], grid[v]);\n                current_score = old_score;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> T;\n    seed_count = 2 * N * (N - 1);\n    seeds.resize(seed_count, vector<int>(M));\n    seed_val.resize(seed_count);\n    \n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n            seed_val[i] += seeds[i][j];\n        }\n    }\n    \n    init_adj();\n    grid.resize(N * N);\n    \n    for (int t = 0; t < T; ++t) {\n        for (int i = 0; i < seed_count; ++i) {\n            seed_val[i] = 0;\n            for (int j = 0; j < M; ++j) {\n                seed_val[i] += seeds[i][j];\n            }\n        }\n        \n        // Multiple restarts with different strategies\n        long long best_score = -1;\n        vector<int> best_grid;\n        \n        // Full optimizations with different strategies\n        for (int restart = 0; restart < 3; ++restart) {\n            init_grid(restart);\n            sa_optimize(40000);\n            local_refinement();\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_grid = grid;\n            }\n        }\n        \n        // Quick random restart\n        init_grid(3);\n        sa_optimize(20000);\n        local_refinement();\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_grid = grid;\n        }\n        \n        grid = best_grid;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << grid[i * N + j] << (j == N - 1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n        \n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Takoyaki {\n    Point src, tgt;\n    int id;\n    bool done = false;\n};\n\nint N, M, V;\nvector<string> s_grid, t_grid;\nvector<Takoyaki> takoyakis;\nvector<int> edge_len;\nint root_x, root_y;\nint dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // R, D, L, U\nchar dir_char[4] = {'R', 'D', 'L', 'U'};\n\n// Current state\nint arm_dir[16]; // direction of each edge (0-3)\nbool holding[16]; // whether each fingertip is holding\nPoint fingertip_pos[16]; // current position of each fingertip\n\n// Calculate fingertip positions based on root and directions\nvoid update_fingertip_positions() {\n    for (int i = 1; i < edge_len.size() + 1; i++) {\n        int fx = root_x + dir[arm_dir[i]][0] * edge_len[i];\n        int fy = root_y + dir[arm_dir[i]][1] * edge_len[i];\n        fingertip_pos[i] = {fx, fy};\n    }\n}\n\n// Check if position is valid\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there's a takoyaki at position\nbool has_takoyaki(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1';\n}\n\n// Check if position is a target\nbool is_target(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return t_grid[x][y] == '1';\n}\n\n// Check if position has been filled (target completed)\nbool is_filled(int x, int y) {\n    if (!is_valid(x, y)) return false;\n    return s_grid[x][y] == '1' && t_grid[x][y] == '1';\n}\n\n// Find nearest available source for a fingertip\nPoint find_nearest_source(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].src.x) + abs(fp.y - takoyakis[i].src.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].src;\n        }\n    }\n    return best;\n}\n\n// Find nearest available target for a fingertip\nPoint find_nearest_target(Point fp) {\n    Point best = {-1, -1};\n    int best_dist = 1e9;\n    \n    for (int i = 0; i < M; i++) {\n        if (takoyakis[i].done) continue;\n        int d = abs(fp.x - takoyakis[i].tgt.x) + abs(fp.y - takoyakis[i].tgt.y);\n        if (d < best_dist) {\n            best_dist = d;\n            best = takoyakis[i].tgt;\n        }\n    }\n    return best;\n}\n\n// Get direction to move towards a target\nint get_direction(Point current, Point target) {\n    if (current.x < target.x) return 1; // D\n    if (current.x > target.x) return 3; // U\n    if (current.y < target.y) return 0; // R\n    if (current.y > target.y) return 2; // L\n    return 0; // Default\n}\n\n// Get rotation to achieve desired direction\nchar get_rotation(int current_dir, int target_dir) {\n    int diff = (target_dir - current_dir + 4) % 4;\n    if (diff == 0) return '.';\n    if (diff == 1 || diff == 3) return 'R'; // clockwise\n    return 'L'; // counterclockwise\n}\n\n// Check if all takoyaki are delivered\nbool all_delivered() {\n    for (int i = 0; i < M; i++) {\n        if (!takoyakis[i].done) return false;\n    }\n    return true;\n}\n\n// Check if a source still has takoyaki\nbool source_has_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return s_grid[p.x][p.y] == '1' && t_grid[p.x][p.y] == '0';\n}\n\n// Check if a target needs takoyaki\nbool target_needs_takoyaki(Point p) {\n    if (!is_valid(p.x, p.y)) return false;\n    return t_grid[p.x][p.y] == '1' && s_grid[p.x][p.y] == '0';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> V;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    \n    for (int i = 0; i < N; i++) cin >> s_grid[i];\n    for (int i = 0; i < N; i++) cin >> t_grid[i];\n    \n    // Parse takoyaki positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                takoyakis.push_back({{i, j}, {0, 0}, (int)takoyakis.size()});\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (t_grid[i][j] == '1' && s_grid[i][j] == '0') {\n                // Find matching source\n                for (auto& t : takoyakis) {\n                    if (t.tgt.x == 0 && t.tgt.y == 0) {\n                        t.tgt = {i, j};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Design star topology robot\n    int num_fingertips = min(V - 1, M); // Each fingertip handles one takoyaki\n    \n    // Output robot design\n    cout << num_fingertips + 1 << \"\\n\";\n    edge_len.resize(num_fingertips + 1);\n    \n    // Use different edge lengths for better coverage\n    for (int i = 1; i <= num_fingertips; i++) {\n        edge_len[i] = min(i * 2, N - 1);\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Initial position: center of grid\n    root_x = N / 2;\n    root_y = N / 2;\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Initialize directions (all pointing right initially)\n    for (int i = 0; i <= num_fingertips; i++) {\n        arm_dir[i] = 0;\n        holding[i] = false;\n    }\n    \n    update_fingertip_positions();\n    \n    // Main operation loop\n    int turn = 0;\n    int max_turns = 80000; // Leave margin for system test\n    \n    while (turn < max_turns && !all_delivered()) {\n        string cmd = \"\";\n        \n        // Step 1: Decide arm movement\n        // Find average direction to move towards pending sources/targets\n        int total_dx = 0, total_dy = 0;\n        int count = 0;\n        \n        for (int i = 0; i < M; i++) {\n            if (takoyakis[i].done) continue;\n            if (holding[i % (num_fingertips + 1)]) {\n                // Moving towards target\n                total_dx += takoyakis[i].tgt.x - root_x;\n                total_dy += takoyakis[i].tgt.y - root_y;\n            } else {\n                // Moving towards source\n                total_dx += takoyakis[i].src.x - root_x;\n                total_dy += takoyakis[i].src.y - root_y;\n                count++;\n            }\n        }\n        \n        // Determine movement direction\n        char move = '.';\n        if (count > 0) {\n            if (abs(total_dx) > abs(total_dy)) {\n                if (total_dx > 0) move = 'D';\n                else if (total_dx < 0) move = 'U';\n            } else {\n                if (total_dy > 0) move = 'R';\n                else if (total_dy < 0) move = 'L';\n            }\n        }\n        \n        // Check if movement is valid\n        int nx = root_x, ny = root_y;\n        if (move == 'D') nx++;\n        else if (move == 'U') nx--;\n        else if (move == 'R') ny++;\n        else if (move == 'L') ny--;\n        \n        if (!is_valid(nx, ny)) move = '.';\n        else { root_x = nx; root_y = ny; }\n        \n        cmd += move;\n        \n        // Step 2: Decide rotations for each fingertip\n        for (int i = 1; i <= num_fingertips; i++) {\n            char rot = '.';\n            \n            // Find what this fingertip should do\n            Point fp = fingertip_pos[i];\n            \n            if (holding[i]) {\n                // Try to drop at target\n                Point tgt = find_nearest_target(fp);\n                if (tgt.x >= 0 && target_needs_takoyaki(tgt)) {\n                    // Calculate direction to reach target\n                    int dx = tgt.x - root_x;\n                    int dy = tgt.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            } else {\n                // Try to pick from source\n                Point src = find_nearest_source(fp);\n                if (src.x >= 0 && source_has_takoyaki(src)) {\n                    // Calculate direction to reach source\n                    int dx = src.x - root_x;\n                    int dy = src.y - root_y;\n                    int target_dir = 0;\n                    \n                    if (abs(dx) > abs(dy)) {\n                        target_dir = (dx > 0) ? 1 : 3;\n                    } else {\n                        target_dir = (dy > 0) ? 0 : 2;\n                    }\n                    \n                    rot = get_rotation(arm_dir[i], target_dir);\n                    if (rot != '.') {\n                        arm_dir[i] = target_dir;\n                    }\n                }\n            }\n            \n            cmd += rot;\n        }\n        \n        // Step 3: Decide pick/place actions\n        for (int i = 1; i <= num_fingertips; i++) {\n            update_fingertip_positions();\n            Point fp = fingertip_pos[i];\n            char action = '.';\n            \n            if (is_valid(fp.x, fp.y)) {\n                if (holding[i] && target_needs_takoyaki(fp.x, fp.y)) {\n                    // Drop takoyaki\n                    action = 'P';\n                    holding[i] = false;\n                    s_grid[fp.x][fp.y] = '1';\n                    \n                    // Mark as done\n                    for (int j = 0; j < M; j++) {\n                        if (!takoyakis[j].done && \n                            takoyakis[j].tgt.x == fp.x && \n                            takoyakis[j].tgt.y == fp.y) {\n                            takoyakis[j].done = true;\n                            break;\n                        }\n                    }\n                } else if (!holding[i] && source_has_takoyaki(fp.x, fp.y)) {\n                    // Pick takoyaki\n                    action = 'P';\n                    holding[i] = true;\n                    s_grid[fp.x][fp.y] = '0';\n                }\n            }\n            \n            cmd += action;\n        }\n        \n        // Add '.' for root (not a fingertip)\n        cmd += '.';\n        \n        cout << cmd << \"\\n\";\n        turn++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nlong long distSq(Point p1, Point p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\nstruct SimpleDSU {\n    vector<int> parent;\n    SimpleDSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx != ry) parent[rx] = ry;\n    }\n};\n\nstruct ClusterInfo {\n    long long minX, maxX, minY, maxY;\n    int m_count, s_count;\n    long long score;\n};\n\nbool isInside(const vector<Point>& poly, Point p) {\n    int n = poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        bool cond1 = ((poly[i].y > p.y) != (poly[j].y > p.y));\n        if (poly[j].y != poly[i].y) {\n            bool cond2 = (p.x < (poly[j].x - poly[i].x) * (p.y - poly[i].y) / (double)(poly[j].y - poly[i].y) + poly[i].x);\n            if (cond1 && cond2) inside = !inside;\n        }\n    }\n    if (!inside) {\n        for (int i = 0; i < n; ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % n];\n            if (p1.x == p2.x) {\n                if (p.x == p1.x && min(p1.y, p2.y) <= p.y && p.y <= max(p1.y, p2.y)) return true;\n            } else {\n                if (p.y == p1.y && min(p1.x, p2.x) <= p.x && p.x <= max(p1.x, p2.x)) return true;\n            }\n        }\n    }\n    return inside;\n}\n\nlong long calculateScore(const vector<Point>& poly) {\n    int m_cnt = 0, s_cnt = 0;\n    for (const auto& m : mackerels) {\n        if (isInside(poly, m)) m_cnt++;\n    }\n    for (const auto& s : sardines) {\n        if (isInside(poly, s)) s_cnt++;\n    }\n    return (long long)m_cnt - s_cnt;\n}\n\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4) return false;\n    for (int i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x != p2.x && p1.y != p2.y) return false;\n        if (p1.x == p2.x && p1.y == p2.y) return false;\n    }\n    return true;\n}\n\nvector<Point> removeDuplicates(const vector<Point>& poly) {\n    vector<Point> result;\n    for (int i = 0; i < poly.size(); ++i) {\n        if (i > 0 && poly[i].x == poly[i-1].x && poly[i].y == poly[i-1].y) continue;\n        result.push_back(poly[i]);\n    }\n    if (result.size() > 1 && result.front().x == result.back().x && result.front().y == result.back().y) {\n        result.pop_back();\n    }\n    return result;\n}\n\nvector<Point> buildPolygon(long long cur_minX, long long cur_maxX, long long cur_minY, long long cur_maxY,\n                           const vector<vector<pair<long long, long long>>>& used_intervals, int notch_depth) {\n    vector<Point> final_poly;\n    final_poly.push_back({cur_minX, cur_minY});\n    \n    long long curr_x = cur_minX;\n    for (auto& interval : used_intervals[0]) {\n        if (curr_x < interval.first) final_poly.push_back({interval.first, cur_minY});\n        final_poly.push_back({interval.first, cur_minY + notch_depth});\n        final_poly.push_back({interval.second, cur_minY + notch_depth});\n        final_poly.push_back({interval.second, cur_minY});\n        curr_x = interval.second;\n    }\n    if (curr_x < cur_maxX) final_poly.push_back({cur_maxX, cur_minY});\n\n    long long curr_y = cur_minY;\n    for (auto& interval : used_intervals[3]) {\n        if (curr_y < interval.first) final_poly.push_back({cur_maxX, interval.first});\n        final_poly.push_back({cur_maxX - notch_depth, interval.first});\n        final_poly.push_back({cur_maxX - notch_depth, interval.second});\n        final_poly.push_back({cur_maxX, interval.second});\n        curr_y = interval.second;\n    }\n    if (curr_y < cur_maxY) final_poly.push_back({cur_maxX, cur_maxY});\n\n    curr_x = cur_maxX;\n    for (auto& interval : used_intervals[1]) {\n        if (curr_x > interval.second) final_poly.push_back({interval.second, cur_maxY});\n        final_poly.push_back({interval.second, cur_maxY - notch_depth});\n        final_poly.push_back({interval.first, cur_maxY - notch_depth});\n        final_poly.push_back({interval.first, cur_maxY});\n        curr_x = interval.first;\n    }\n    if (curr_x > cur_minX) final_poly.push_back({cur_minX, cur_maxY});\n\n    curr_y = cur_maxY;\n    for (auto& interval : used_intervals[2]) {\n        if (curr_y > interval.second) final_poly.push_back({cur_minX, interval.second});\n        final_poly.push_back({cur_minX + notch_depth, interval.second});\n        final_poly.push_back({cur_minX + notch_depth, interval.first});\n        final_poly.push_back({cur_minX, interval.first});\n        curr_y = interval.first;\n    }\n    if (curr_y > cur_minY) final_poly.push_back({cur_minX, cur_minY});\n\n    return removeDuplicates(final_poly);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    const long long CLUSTER_DIST_SQ = 6000LL * 6000LL;\n    SimpleDSU dsu_m(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (distSq(mackerels[i], mackerels[j]) <= CLUSTER_DIST_SQ) {\n                dsu_m.unite(i, j);\n            }\n        }\n    }\n\n    vector<vector<int>> m_clusters(N);\n    for (int i = 0; i < N; ++i) {\n        m_clusters[dsu_m.find(i)].push_back(i);\n    }\n\n    vector<ClusterInfo> all_clusters;\n    for (int i = 0; i < N; ++i) {\n        if (m_clusters[i].empty()) continue;\n        \n        long long minX = 1e9, maxX = -1e9, minY = 1e9, maxY = -1e9;\n        for (int idx : m_clusters[i]) {\n            minX = min(minX, mackerels[idx].x);\n            maxX = max(maxX, mackerels[idx].x);\n            minY = min(minY, mackerels[idx].y);\n            maxY = max(maxY, mackerels[idx].y);\n        }\n\n        int m_cnt = m_clusters[i].size();\n        int s_cnt = 0;\n        for (const auto& s : sardines) {\n            if (s.x >= minX && s.x <= maxX && s.y >= minY && s.y <= maxY) s_cnt++;\n        }\n\n        long long sc = (long long)m_cnt - s_cnt;\n        if (sc > 0) {\n            all_clusters.push_back({minX, maxX, minY, maxY, m_cnt, s_cnt, sc});\n        }\n    }\n\n    // Try multiple merge thresholds\n    vector<vector<ClusterInfo>> all_final_clusters;\n    for (int threshold : {2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000}) {\n        sort(all_clusters.begin(), all_clusters.end(), [](const ClusterInfo& a, const ClusterInfo& b) {\n            return a.score > b.score;\n        });\n\n        vector<int> used(all_clusters.size(), 0);\n        vector<ClusterInfo> merged;\n        \n        auto distBox = [](const ClusterInfo& a, const ClusterInfo& b) {\n            long long dx = max(0LL, max(a.minX, b.minX) - min(a.maxX, b.maxX));\n            long long dy = max(0LL, max(a.minY, b.minY) - min(a.maxY, b.maxY));\n            return dx * dx + dy * dy;\n        };\n\n        for (int i = 0; i < (int)all_clusters.size(); ++i) {\n            if (used[i]) continue;\n            \n            ClusterInfo current = all_clusters[i];\n            used[i] = 1;\n            \n            bool changed = true;\n            while (changed) {\n                changed = false;\n                for (int j = 0; j < (int)all_clusters.size(); ++j) {\n                    if (i == j || used[j]) continue;\n                    \n                    long long d2 = distBox(current, all_clusters[j]);\n                    if (d2 <= (long long)threshold * threshold) { \n                        current.minX = min(current.minX, all_clusters[j].minX);\n                        current.maxX = max(current.maxX, all_clusters[j].maxX);\n                        current.minY = min(current.minY, all_clusters[j].minY);\n                        current.maxY = max(current.maxY, all_clusters[j].maxY);\n                        \n                        int m_cnt = 0, s_cnt = 0;\n                        for (const auto& m : mackerels) {\n                            if (m.x >= current.minX && m.x <= current.maxX && m.y >= current.minY && m.y <= current.maxY) m_cnt++;\n                        }\n                        for (const auto& s : sardines) {\n                            if (s.x >= current.minX && s.x <= current.maxX && s.y >= current.minY && s.y <= current.maxY) s_cnt++;\n                        }\n                        current.m_count = m_cnt;\n                        current.s_count = s_cnt;\n                        current.score = (long long)m_cnt - s_cnt;\n                        \n                        used[j] = 1;\n                        changed = true;\n                    }\n                }\n            }\n            if (current.score > 0) {\n                merged.push_back(current);\n            }\n        }\n        all_final_clusters.push_back(merged);\n    }\n\n    vector<Point> best_poly;\n    long long best_score = -1e18;\n\n    // Helper function to process a box\n    auto processBox = [&](long long cur_minX, long long cur_maxX, long long cur_minY, long long cur_maxY) {\n        // Try shrunken box\n        long long sh_minX = cur_minX, sh_maxX = cur_maxX;\n        long long sh_minY = cur_minY, sh_maxY = cur_maxY;\n        \n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (const auto& s : sardines) {\n                if (s.y >= sh_minY && s.y <= sh_maxY && s.x == sh_minX) {\n                    sh_minX = s.x + 1; changed = true;\n                }\n                if (s.y >= sh_minY && s.y <= sh_maxY && s.x == sh_maxX) {\n                    sh_maxX = s.x - 1; changed = true;\n                }\n                if (s.x >= sh_minX && s.x <= sh_maxX && s.y == sh_minY) {\n                    sh_minY = s.y + 1; changed = true;\n                }\n                if (s.x >= sh_minX && s.x <= sh_maxX && s.y == sh_maxY) {\n                    sh_maxY = s.y - 1; changed = true;\n                }\n            }\n        }\n\n        if (sh_minX <= sh_maxX && sh_minY <= sh_maxY) {\n            vector<Point> box_poly;\n            box_poly.push_back({sh_minX, sh_minY});\n            box_poly.push_back({sh_maxX, sh_minY});\n            box_poly.push_back({sh_maxX, sh_maxY});\n            box_poly.push_back({sh_minX, sh_maxY});\n            \n            if (validatePolygon(box_poly)) {\n                long long sc = calculateScore(box_poly);\n                if (sc > best_score) {\n                    best_score = sc;\n                    best_poly = box_poly;\n                }\n            }\n\n            // Try notches on shrunken box\n            struct SideSardine {\n                long long pos;\n                int side;\n            };\n            vector<SideSardine> sardines_on_sides;\n\n            for (const auto& s : sardines) {\n                if (s.y == sh_minY && s.x > sh_minX && s.x < sh_maxX) sardines_on_sides.push_back({s.x, 0});\n                if (s.y == sh_maxY && s.x > sh_minX && s.x < sh_maxX) sardines_on_sides.push_back({s.x, 1});\n                if (s.x == sh_minX && s.y > sh_minY && s.y < sh_maxY) sardines_on_sides.push_back({s.y, 2});\n                if (s.x == sh_maxX && s.y > sh_minY && s.y < sh_maxY) sardines_on_sides.push_back({s.y, 3});\n            }\n\n            for (int notch_depth : {1, 2, 3, 4, 5, 6, 7, 8}) {\n                for (int notch_width : {1, 3, 5, 7, 9}) {\n                    vector<vector<pair<long long, long long>>> used_intervals(4);\n\n                    // Calculate net gain for each sardine and sort by it\n                    struct SardineInfo {\n                        long long pos;\n                        int side;\n                        int net_gain;\n                    };\n                    vector<SardineInfo> sardine_info;\n\n                    for (const auto& ss : sardines_on_sides) {\n                        int side = ss.side;\n                        long long pos = ss.pos;\n                        long long half_width = notch_width / 2;\n                        long long start = pos - half_width;\n                        long long end = pos + half_width;\n                        \n                        int m_removed = 0, s_removed = 0;\n                        \n                        if (side == 0) {\n                            for (const auto& m : mackerels) {\n                                if (m.x >= start && m.x <= end && m.y >= sh_minY && m.y <= sh_minY + notch_depth) m_removed++;\n                            }\n                            for (const auto& s : sardines) {\n                                if (s.x >= start && s.x <= end && s.y >= sh_minY && s.y <= sh_minY + notch_depth) s_removed++;\n                            }\n                        } else if (side == 1) {\n                            for (const auto& m : mackerels) {\n                                if (m.x >= start && m.x <= end && m.y >= sh_maxY - notch_depth && m.y <= sh_maxY) m_removed++;\n                            }\n                            for (const auto& s : sardines) {\n                                if (s.x >= start && s.x <= end && s.y >= sh_maxY - notch_depth && s.y <= sh_maxY) s_removed++;\n                            }\n                        } else if (side == 2) {\n                            for (const auto& m : mackerels) {\n                                if (m.x >= sh_minX && m.x <= sh_minX + notch_depth && m.y >= start && m.y <= end) m_removed++;\n                            }\n                            for (const auto& s : sardines) {\n                                if (s.x >= sh_minX && s.x <= sh_minX + notch_depth && s.y >= start && s.y <= end) s_removed++;\n                            }\n                        } else {\n                            for (const auto& m : mackerels) {\n                                if (m.x >= sh_maxX - notch_depth && m.x <= sh_maxX && m.y >= start && m.y <= end) m_removed++;\n                            }\n                            for (const auto& s : sardines) {\n                                if (s.x >= sh_maxX - notch_depth && s.x <= sh_maxX && s.y >= start && s.y <= end) s_removed++;\n                            }\n                        }\n                        \n                        sardine_info.push_back({pos, side, s_removed - m_removed});\n                    }\n\n                    // Sort by net gain descending\n                    sort(sardine_info.begin(), sardine_info.end(), [](const SardineInfo& a, const SardineInfo& b) {\n                        return a.net_gain > b.net_gain;\n                    });\n\n                    for (const auto& si : sardine_info) {\n                        int side = si.side;\n                        long long pos = si.pos;\n                        \n                        long long half_width = notch_width / 2;\n                        long long start = pos - half_width;\n                        long long end = pos + half_width;\n                        \n                        if (side == 0 || side == 1) {\n                            if (start <= sh_minX || end >= sh_maxX) continue;\n                        } else {\n                            if (start <= sh_minY || end >= sh_maxY) continue;\n                        }\n                        \n                        bool overlap = false;\n                        for (auto& interval : used_intervals[side]) {\n                            if (start < interval.second && end > interval.first) {\n                                overlap = true; break;\n                            }\n                        }\n                        if (overlap) continue;\n\n                        if (si.net_gain <= 0) continue;\n                        used_intervals[side].push_back({start, end});\n                    }\n\n                    vector<Point> final_poly = buildPolygon(sh_minX, sh_maxX, sh_minY, sh_maxY, used_intervals, notch_depth);\n\n                    if (final_poly.size() < 4) continue;\n                    if (!validatePolygon(final_poly)) continue;\n\n                    long long sc = calculateScore(final_poly);\n                    if (sc > best_score) {\n                        best_score = sc;\n                        best_poly = final_poly;\n                    }\n                }\n            }\n        }\n\n        // Also try notches on original box\n        struct SideSardine {\n            long long pos;\n            int side;\n        };\n        vector<SideSardine> sardines_on_sides_orig;\n\n        for (const auto& s : sardines) {\n            if (s.y == cur_minY && s.x > cur_minX && s.x < cur_maxX) sardines_on_sides_orig.push_back({s.x, 0});\n            if (s.y == cur_maxY && s.x > cur_minX && s.x < cur_maxX) sardines_on_sides_orig.push_back({s.x, 1});\n            if (s.x == cur_minX && s.y > cur_minY && s.y < cur_maxY) sardines_on_sides_orig.push_back({s.y, 2});\n            if (s.x == cur_maxX && s.y > cur_minY && s.y < cur_maxY) sardines_on_sides_orig.push_back({s.y, 3});\n        }\n\n        for (int notch_depth : {1, 2, 3, 4, 5, 6, 7, 8}) {\n            for (int notch_width : {1, 3, 5, 7, 9}) {\n                vector<vector<pair<long long, long long>>> used_intervals(4);\n\n                struct SardineInfo {\n                    long long pos;\n                    int side;\n                    int net_gain;\n                };\n                vector<SardineInfo> sardine_info;\n\n                for (const auto& ss : sardines_on_sides_orig) {\n                    int side = ss.side;\n                    long long pos = ss.pos;\n                    long long half_width = notch_width / 2;\n                    long long start = pos - half_width;\n                    long long end = pos + half_width;\n                    \n                    int m_removed = 0, s_removed = 0;\n                    \n                    if (side == 0) {\n                        for (const auto& m : mackerels) {\n                            if (m.x >= start && m.x <= end && m.y >= cur_minY && m.y <= cur_minY + notch_depth) m_removed++;\n                        }\n                        for (const auto& s : sardines) {\n                            if (s.x >= start && s.x <= end && s.y >= cur_minY && s.y <= cur_minY + notch_depth) s_removed++;\n                        }\n                    } else if (side == 1) {\n                        for (const auto& m : mackerels) {\n                            if (m.x >= start && m.x <= end && m.y >= cur_maxY - notch_depth && m.y <= cur_maxY) m_removed++;\n                        }\n                        for (const auto& s : sardines) {\n                            if (s.x >= start && s.x <= end && s.y >= cur_maxY - notch_depth && s.y <= cur_maxY) s_removed++;\n                        }\n                    } else if (side == 2) {\n                        for (const auto& m : mackerels) {\n                            if (m.x >= cur_minX && m.x <= cur_minX + notch_depth && m.y >= start && m.y <= end) m_removed++;\n                        }\n                        for (const auto& s : sardines) {\n                            if (s.x >= cur_minX && s.x <= cur_minX + notch_depth && s.y >= start && s.y <= end) s_removed++;\n                        }\n                    } else {\n                        for (const auto& m : mackerels) {\n                            if (m.x >= cur_maxX - notch_depth && m.x <= cur_maxX && m.y >= start && m.y <= end) m_removed++;\n                        }\n                        for (const auto& s : sardines) {\n                            if (s.x >= cur_maxX - notch_depth && s.x <= cur_maxX && s.y >= start && s.y <= end) s_removed++;\n                        }\n                    }\n                    \n                    sardine_info.push_back({pos, side, s_removed - m_removed});\n                }\n\n                sort(sardine_info.begin(), sardine_info.end(), [](const SardineInfo& a, const SardineInfo& b) {\n                    return a.net_gain > b.net_gain;\n                });\n\n                for (const auto& si : sardine_info) {\n                    int side = si.side;\n                    long long pos = si.pos;\n                    \n                    long long half_width = notch_width / 2;\n                    long long start = pos - half_width;\n                    long long end = pos + half_width;\n                    \n                    if (side == 0 || side == 1) {\n                        if (start <= cur_minX || end >= cur_maxX) continue;\n                    } else {\n                        if (start <= cur_minY || end >= cur_maxY) continue;\n                    }\n                    \n                    bool overlap = false;\n                    for (auto& interval : used_intervals[side]) {\n                        if (start < interval.second && end > interval.first) {\n                            overlap = true; break;\n                        }\n                    }\n                    if (overlap) continue;\n\n                    if (si.net_gain <= 0) continue;\n                    used_intervals[side].push_back({start, end});\n                }\n\n                vector<Point> final_poly = buildPolygon(cur_minX, cur_maxX, cur_minY, cur_maxY, used_intervals, notch_depth);\n\n                if (final_poly.size() < 4) continue;\n                if (!validatePolygon(final_poly)) continue;\n\n                long long sc = calculateScore(final_poly);\n                if (sc > best_score) {\n                    best_score = sc;\n                    best_poly = final_poly;\n                }\n            }\n        }\n    };\n\n    // Process merged clusters\n    for (const auto& cluster_list : all_final_clusters) {\n        for (const auto& cluster : cluster_list) {\n            processBox(cluster.minX, cluster.maxX, cluster.minY, cluster.maxY);\n        }\n    }\n\n    // Process individual clusters\n    for (const auto& cluster : all_clusters) {\n        processBox(cluster.minX, cluster.maxX, cluster.minY, cluster.maxY);\n    }\n\n    if (best_poly.empty()) {\n        cout << 4 << \"\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Placement {\n    int p, r;\n    char d;\n    int b;\n};\n\nclass Solver {\nprivate:\n    int N, T;\n    double sigma;\n    vector<pair<int, int>> wh;\n    mt19937 rng;\n    \n    pair<int, int> calculatePosition(const vector<pair<int, int>>& placed_wh, \n                                     const vector<pair<int, int>>& placed_xy,\n                                     int rw, int rh, char dir, int ref) {\n        int x = 0, y = 0;\n        \n        if (dir == 'U') {\n            x = (ref == -1) ? 0 : placed_xy[ref].first + placed_wh[ref].first;\n            y = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (x < px + pw && x + rw > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            y = (ref == -1) ? 0 : placed_xy[ref].second + placed_wh[ref].second;\n            x = 0;\n            for (size_t i = 0; i < placed_wh.size(); i++) {\n                int pw = placed_wh[i].first;\n                int ph = placed_wh[i].second;\n                int px = placed_xy[i].first;\n                int py = placed_xy[i].second;\n                if (y < py + ph && y + rh > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        return {x, y};\n    }\n    \n    vector<Placement> greedyPlacement(int seed, int strategy) {\n        vector<Placement> placements;\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        mt19937 local_rng(seed);\n        \n        for (int i = 0; i < N; i++) {\n            int best_score = 2e9;\n            Placement best_p = {i, 0, 'U', -1};\n            \n            int w = wh[i].first;\n            int h = wh[i].second;\n            \n            // Different strategies for rotation preference\n            bool prefer_horizontal = (w >= h);\n            if (strategy == 1) prefer_horizontal = (w <= h);\n            if (strategy == 2) prefer_horizontal = (local_rng() % 2 == 0);\n            \n            for (int rot = 0; rot < 2; rot++) {\n                int rw = rot ? h : w;\n                int rh = rot ? w : h;\n                int rot_penalty = (rot != prefer_horizontal) ? 500 : 0;\n                \n                for (char dir : {'U', 'L'}) {\n                    // Try -1 and last 5 rectangles (conservative)\n                    int max_refs = min(i, 5);\n                    for (int ref = -1; ref < i; ref++) {\n                        if (ref != -1 && ref < i - max_refs) continue;\n                        \n                        auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, dir, ref);\n                        \n                        int W = 0, H = 0;\n                        for (size_t j = 0; j < placed_wh.size(); j++) {\n                            W = max(W, placed_xy[j].first + placed_wh[j].first);\n                            H = max(H, placed_xy[j].second + placed_wh[j].second);\n                        }\n                        W = max(W, x + rw);\n                        H = max(H, y + rh);\n                        \n                        int score = W + H + rot_penalty;\n                        if (score < best_score) {\n                            best_score = score;\n                            best_p = {i, rot, dir, ref};\n                        }\n                    }\n                }\n            }\n            \n            placements.push_back(best_p);\n            int rw = best_p.r ? h : w;\n            int rh = best_p.r ? w : h;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, best_p.d, best_p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        return placements;\n    }\n    \n    int calculateScore(const vector<Placement>& placements) {\n        vector<pair<int, int>> placed_wh;\n        vector<pair<int, int>> placed_xy;\n        \n        for (const auto& p : placements) {\n            int rw = p.r ? wh[p.p].second : wh[p.p].first;\n            int rh = p.r ? wh[p.p].first : wh[p.p].second;\n            auto [x, y] = calculatePosition(placed_wh, placed_xy, rw, rh, p.d, p.b);\n            placed_wh.push_back({rw, rh});\n            placed_xy.push_back({x, y});\n        }\n        \n        int W = 0, H = 0;\n        for (size_t i = 0; i < placed_wh.size(); i++) {\n            W = max(W, placed_xy[i].first + placed_wh[i].first);\n            H = max(H, placed_xy[i].second + placed_wh[i].second);\n        }\n        \n        return W + H;\n    }\n    \n    vector<Placement> localSearch(const vector<Placement>& placements) {\n        vector<Placement> cur = placements;\n        int best_score = calculateScore(cur);\n        \n        // Try rotation flips\n        for (int i = 0; i < N; i++) {\n            cur[i].r ^= 1;\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].r ^= 1;\n            } else {\n                best_score = score;\n            }\n        }\n        \n        // Try direction flips\n        for (int i = 0; i < N; i++) {\n            char orig_d = cur[i].d;\n            cur[i].d = (orig_d == 'U' ? 'L' : 'U');\n            int score = calculateScore(cur);\n            if (score >= best_score) {\n                cur[i].d = orig_d;\n            } else {\n                best_score = score;\n            }\n        }\n        \n        return cur;\n    }\n    \npublic:\n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void solve() {\n        cin >> N >> T >> sigma;\n        wh.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> wh[i].first >> wh[i].second;\n        }\n        \n        auto startTime = chrono::steady_clock::now();\n        const double MAX_TIME = 2.3;  // Conservative for system test\n        \n        for (int t = 0; t < T; t++) {\n            auto currentTime = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(currentTime - startTime).count();\n            if (elapsed > MAX_TIME) break;\n            \n            int best_score = 2e9;\n            vector<Placement> best_placements;\n            \n            // Adaptive strategies - 3-4 strategies max\n            int progress = (double)t / T;\n            int num_strategies = max(2, (int)(4 * (1 - progress * 0.25)));\n            \n            for (int s = 0; s < num_strategies; s++) {\n                currentTime = chrono::steady_clock::now();\n                elapsed = chrono::duration<double>(currentTime - startTime).count();\n                if (elapsed > MAX_TIME) break;\n                \n                // Try different strategy types (3 types)\n                int strategy_type = s % 3;\n                vector<Placement> placements = greedyPlacement(t * 1000 + s, strategy_type);\n                placements = localSearch(placements);\n                \n                int score = calculateScore(placements);\n                if (score < best_score) {\n                    best_score = score;\n                    best_placements = placements;\n                }\n            }\n            \n            cout << best_placements.size() << \"\\n\";\n            for (const auto& p : best_placements) {\n                cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n            }\n            cout.flush();\n            \n            int W, H;\n            cin >> W >> H;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Solver solver;\n    solver.solve();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int MAXN = 1005;\nvector<int> adj[MAXN];\nint A[MAXN];\nint L[MAXN];\nint p[MAXN];\nint x[MAXN], y[MAXN];\n\nvoid solve() {\n    int N, M, H;\n    while (cin >> N >> M >> H) {\n        // Clear adj BEFORE reading edges\n        for (int i = 0; i < N; ++i) {\n            adj[i].clear();\n            L[i] = 0;\n            p[i] = -1;\n        }\n        \n        // Read input\n        for (int i = 0; i < N; ++i) cin >> A[i];\n        for (int i = 0; i < M; ++i) {\n            int u, v;\n            cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n        \n        // Create vertex ordering by beauty value (descending)\n        vector<int> order(N);\n        for (int i = 0; i < N; ++i) order[i] = i;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        \n        // Greedy level building with priority-based processing\n        for (int iter = 0; iter < 10000; ++iter) {\n            bool improved = false;\n            for (int idx = 0; idx < N; ++idx) {\n                int v = order[idx];\n                if (L[v] >= H) continue;\n                \n                int new_L = L[v] + 1;\n                \n                // Check if v has a parent at new_L - 1\n                bool has_parent = false;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) {\n                        has_parent = true;\n                        break;\n                    }\n                }\n                if (!has_parent) continue;\n                \n                // Apply the move\n                L[v] = new_L;\n                improved = true;\n            }\n            if (!improved) break;\n        }\n        \n        // Simulated Annealing refinement\n        static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_int_distribution<int> dist_idx(0, N - 1);\n        uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        \n        int iterations = 20000;\n        double T = 1000.0;\n        double decay = 0.9997;\n        \n        for (int iter = 0; iter < iterations; ++iter) {\n            int v = dist_idx(rng);\n            int old_L = L[v];\n            \n            // Try increasing level first\n            if (old_L < H) {\n                int new_L = old_L + 1;\n                \n                // Check if v has a parent at new_L - 1\n                bool has_parent = false;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) {\n                        has_parent = true;\n                        break;\n                    }\n                }\n                \n                if (has_parent) {\n                    L[v] = new_L;\n                }\n            }\n            \n            T *= decay;\n        }\n        \n        // Build parent array\n        for (int i = 0; i < N; ++i) {\n            if (L[i] == 0) {\n                p[i] = -1;\n            } else {\n                int parent = -1;\n                for (int u : adj[i]) {\n                    if (L[u] == L[i] - 1) {\n                        parent = u;\n                        break;\n                    }\n                }\n                p[i] = parent;\n            }\n            cout << p[i] << (i == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Move {\n    char d;\n    int p;\n};\n\nstruct OniInfo {\n    int r, c;\n    int safe_dirs;\n};\n\nint N;\nvector<string> board;\nvector<Move> moves;\n\nint count_oni() {\n    int c = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (board[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\nvoid apply_move(char d, int p, int k) {\n    for (int step = 0; step < k; ++step) {\n        if (d == 'L') {\n            moves.push_back({'L', p});\n            for (int j = 0; j < N - 1; ++j) {\n                board[p][j] = board[p][j + 1];\n            }\n            board[p][N - 1] = '.';\n        } else if (d == 'R') {\n            moves.push_back({'R', p});\n            for (int j = N - 1; j > 0; --j) {\n                board[p][j] = board[p][j - 1];\n            }\n            board[p][0] = '.';\n        } else if (d == 'U') {\n            moves.push_back({'U', p});\n            for (int i = 0; i < N - 1; ++i) {\n                board[i][p] = board[i + 1][p];\n            }\n            board[N - 1][p] = '.';\n        } else if (d == 'D') {\n            moves.push_back({'D', p});\n            for (int i = N - 1; i > 0; --i) {\n                board[i][p] = board[i - 1][p];\n            }\n            board[0][p] = '.';\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n    board.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> board[i];\n    }\n\n    while (count_oni() > 0) {\n        vector<OniInfo> oni_list;\n        \n        // Find all Oni and count safe directions for each\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] == 'x') {\n                    OniInfo oni;\n                    oni.r = i;\n                    oni.c = j;\n                    oni.safe_dirs = 0;\n                    \n                    // Check left\n                    bool safe_left = true;\n                    for (int jj = 0; jj < j; ++jj) {\n                        if (board[i][jj] == 'o') {\n                            safe_left = false;\n                            break;\n                        }\n                    }\n                    if (safe_left) oni.safe_dirs++;\n                    \n                    // Check right\n                    bool safe_right = true;\n                    for (int jj = j + 1; jj < N; ++jj) {\n                        if (board[i][jj] == 'o') {\n                            safe_right = false;\n                            break;\n                        }\n                    }\n                    if (safe_right) oni.safe_dirs++;\n                    \n                    // Check up\n                    bool safe_up = true;\n                    for (int ii = 0; ii < i; ++ii) {\n                        if (board[ii][j] == 'o') {\n                            safe_up = false;\n                            break;\n                        }\n                    }\n                    if (safe_up) oni.safe_dirs++;\n                    \n                    // Check down\n                    bool safe_down = true;\n                    for (int ii = i + 1; ii < N; ++ii) {\n                        if (board[ii][j] == 'o') {\n                            safe_down = false;\n                            break;\n                        }\n                    }\n                    if (safe_down) oni.safe_dirs++;\n                    \n                    oni_list.push_back(oni);\n                }\n            }\n        }\n\n        // Sort Oni by safe_dirs (ascending) - most constrained first\n        sort(oni_list.begin(), oni_list.end(), [](const OniInfo& a, const OniInfo& b) {\n            return a.safe_dirs < b.safe_dirs;\n        });\n\n        // Try to remove the most constrained Oni first\n        bool found = false;\n        for (const auto& oni : oni_list) {\n            int r = oni.r;\n            int c = oni.c;\n            \n            // Try each direction, prioritizing by number of Oni removed\n            int best_oni_removed = 0;\n            char best_d = 0;\n            int best_p = -1;\n            int best_k = 0;\n            \n            // Left\n            bool safe_left = true;\n            for (int jj = 0; jj < c; ++jj) {\n                if (board[r][jj] == 'o') {\n                    safe_left = false;\n                    break;\n                }\n            }\n            if (safe_left) {\n                int k = c + 1;\n                int oni_removed = 0;\n                for (int jj = 0; jj < k; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'L';\n                    best_p = r;\n                    best_k = k;\n                }\n            }\n            \n            // Right\n            bool safe_right = true;\n            for (int jj = c + 1; jj < N; ++jj) {\n                if (board[r][jj] == 'o') {\n                    safe_right = false;\n                    break;\n                }\n            }\n            if (safe_right) {\n                int k = N - c;\n                int oni_removed = 0;\n                for (int jj = N - k; jj < N; ++jj) {\n                    if (board[r][jj] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'R';\n                    best_p = r;\n                    best_k = k;\n                }\n            }\n            \n            // Up\n            bool safe_up = true;\n            for (int ii = 0; ii < r; ++ii) {\n                if (board[ii][c] == 'o') {\n                    safe_up = false;\n                    break;\n                }\n            }\n            if (safe_up) {\n                int k = r + 1;\n                int oni_removed = 0;\n                for (int ii = 0; ii < k; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'U';\n                    best_p = c;\n                    best_k = k;\n                }\n            }\n            \n            // Down\n            bool safe_down = true;\n            for (int ii = r + 1; ii < N; ++ii) {\n                if (board[ii][c] == 'o') {\n                    safe_down = false;\n                    break;\n                }\n            }\n            if (safe_down) {\n                int k = N - r;\n                int oni_removed = 0;\n                for (int ii = N - k; ii < N; ++ii) {\n                    if (board[ii][c] == 'x') oni_removed++;\n                }\n                if (oni_removed > best_oni_removed || (oni_removed == best_oni_removed && k < best_k)) {\n                    best_oni_removed = oni_removed;\n                    best_d = 'D';\n                    best_p = c;\n                    best_k = k;\n                }\n            }\n            \n            if (best_p != -1) {\n                apply_move(best_d, best_p, best_k);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) break;\n    }\n\n    for (const auto& m : moves) {\n        cout << m.d << \" \" << m.p << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\nint N, L;\nint T[105];\nint A[105], B[105];\nint current_cnt[105];\n\n// Fast simulation\ninline long long evaluate() {\n    memset(current_cnt, 0, sizeof(current_cnt));\n    int cur = 0;\n    for(int w = 0; w < L; ++w) {\n        current_cnt[cur]++;\n        if (current_cnt[cur] & 1) cur = A[cur];\n        else cur = B[cur];\n    }\n    long long err = 0;\n    for(int i = 0; i < N; ++i) {\n        err += abs(current_cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    for(int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_node(0, N - 1);\n    uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    // Flow-based initialization (from first successful attempt)\n    // Distribute 2*N edges such that in-degree of i is proportional to T[i]\n    vector<int> targets;\n    targets.reserve(2 * N);\n    vector<int> base_counts(N, 0);\n    long long distributed = 0;\n    for(int i = 0; i < N; ++i) {\n        long long k = (2LL * N * T[i]) / L;\n        base_counts[i] = k;\n        distributed += k;\n    }\n    long long remainder = 2 * N - distributed;\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    // Sort indices by T[i] descending to distribute remainder\n    sort(p.begin(), p.end(), [&](int i, int j){\n        return T[i] > T[j];\n    });\n    for(int i = 0; i < remainder && i < N; ++i) {\n        base_counts[p[i]]++;\n    }\n    for(int i = 0; i < N; ++i) {\n        for(int k = 0; k < base_counts[i]; ++k) {\n            targets.push_back(i);\n        }\n    }\n    // Shuffle to avoid deterministic structure\n    shuffle(targets.begin(), targets.end(), rng);\n    // Assign A and B\n    for(int i = 0; i < N; ++i) {\n        A[i] = targets[2 * i];\n        B[i] = targets[2 * i + 1];\n    }\n\n    // Initial evaluation\n    long long current_err = evaluate();\n    long long best_err = current_err;\n    vector<int> best_A(N), best_B(N);\n    for(int i = 0; i < N; ++i) {\n        best_A[i] = A[i];\n        best_B[i] = B[i];\n    }\n\n    // Simulated Annealing parameters (from first successful attempt)\n    double temp = 1e7;\n    double cooling = 0.999;\n    \n    // Time limit handling (use more time)\n    auto start_time = chrono::steady_clock::now();\n    auto end_time = start_time + chrono::seconds(1) + chrono::milliseconds(950);\n\n    while (chrono::steady_clock::now() < end_time) {\n        // Save current counts for potential revert\n        vector<int> saved_cnt(N);\n        for(int i = 0; i < N; ++i) saved_cnt[i] = current_cnt[i];\n        \n        // Pick node u to modify (biased by error)\n        int u = dist_node(rng);\n        long long total_err = 0;\n        for(int i = 0; i < N; ++i) total_err += abs(current_cnt[i] - T[i]);\n        if (total_err > 0) {\n            long long r = rng() % total_err;\n            long long sum = 0;\n            for(int i = 0; i < N; ++i) {\n                long long w = abs(current_cnt[i] - T[i]);\n                sum += w;\n                if (sum > r) {\n                    u = i;\n                    break;\n                }\n            }\n        }\n\n        // Pick target node v (biased by need)\n        int v = dist_node(rng);\n        long long total_need = 0;\n        for(int i = 0; i < N; ++i) {\n            if (T[i] > current_cnt[i]) total_need += (T[i] - current_cnt[i]);\n        }\n        if (total_need > 0) {\n            long long r = rng() % total_need;\n            long long sum = 0;\n            for(int i = 0; i < N; ++i) {\n                long long w = max(0, T[i] - current_cnt[i]);\n                sum += w;\n                if (sum > r) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n\n        // Propose change: modify A[u] or B[u]\n        int edge_type = dist_node(rng) % 2;\n        int old_target = (edge_type == 0) ? A[u] : B[u];\n        \n        if (edge_type == 0) A[u] = v;\n        else B[u] = v;\n\n        // Evaluate new state\n        long long new_err = evaluate();\n        \n        // Acceptance probability\n        double delta = new_err - current_err;\n        double prob = exp(-delta / temp);\n        \n        if (delta < 0 || dist_prob(rng) < prob) {\n            current_err = new_err;\n            if (current_err < best_err) {\n                best_err = current_err;\n                for(int i = 0; i < N; ++i) {\n                    best_A[i] = A[i];\n                    best_B[i] = B[i];\n                }\n            }\n        } else {\n            // Revert change\n            if (edge_type == 0) A[u] = old_target;\n            else B[u] = old_target;\n            // Restore counts\n            for(int i = 0; i < N; ++i) current_cnt[i] = saved_cnt[i];\n        }\n        \n        // Cool down\n        temp *= cooling;\n        if (temp < 1e-3) temp = 1e-3;\n    }\n\n    // Output best solution\n    for(int i = 0; i < N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    double cx, cy;\n};\n\nstruct Edge {\n    int u, v;\n    int dist;\n    bool queried;\n    bool operator<(const Edge& other) const {\n        if (dist != other.dist) return dist < other.dist;\n        if (queried != other.queried) return queried > other.queried;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\nclass DSU {\npublic:\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) {\n            parent[rootX] = rootY;\n            return true;\n        }\n        return false;\n    }\n};\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<City> cities;\nvector<vector<int>> groups;\nint query_cnt = 0;\nvector<vector<int>> dist_cache;\nvector<vector<bool>> edge_queried;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nint calc_dist(int i, int j) {\n    double dx = cities[i].cx - cities[j].cx;\n    double dy = cities[i].cy - cities[j].cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\nint get_dist(int i, int j) {\n    if (i > j) swap(i, j);\n    return dist_cache[i][j];\n}\n\nvoid perform_query(const vector<int>& subset) {\n    if (query_cnt >= Q) return;\n    cout << \"? \" << subset.size();\n    for (int id : subset) {\n        cout << \" \" << id;\n    }\n    cout << endl;\n    query_cnt++;\n}\n\nvector<pair<int, int>> read_query_response(int size) {\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < size - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.push_back({u, v});\n        dist_cache[u][v] = 0;\n        edge_queried[u][v] = true;\n    }\n    return edges;\n}\n\nvector<pair<int, int>> build_mst(const vector<int>& group) {\n    vector<Edge> all_edges;\n    int sz = (int)group.size();\n    \n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            bool queried = edge_queried[u][v];\n            all_edges.push_back({u, v, d, queried});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n\n    DSU dsu(sz);\n    vector<pair<int, int>> mst_edges;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        if (u_idx != -1 && v_idx != -1) {\n            if (dsu.unite(u_idx, v_idx)) {\n                mst_edges.push_back({e.u, e.v});\n                if ((int)mst_edges.size() == sz - 1) break;\n            }\n        }\n    }\n    return mst_edges;\n}\n\nint calc_estimated_cost(const vector<int>& group) {\n    int sz = (int)group.size();\n    if (sz <= 1) return 0;\n    \n    vector<Edge> all_edges;\n    for (int i = 0; i < sz; ++i) {\n        for (int j = i + 1; j < sz; ++j) {\n            int u = group[i];\n            int v = group[j];\n            int d = get_dist(u, v);\n            all_edges.push_back({u, v, d, false});\n        }\n    }\n    sort(all_edges.begin(), all_edges.end());\n    \n    DSU dsu(sz);\n    int cost = 0;\n    \n    vector<int> id_to_idx(N, -1);\n    for (int i = 0; i < sz; ++i) {\n        id_to_idx[group[i]] = i;\n    }\n    \n    for (const auto& e : all_edges) {\n        int u_idx = id_to_idx[e.u];\n        int v_idx = id_to_idx[e.v];\n        \n        if (u_idx != -1 && v_idx != -1 && dsu.unite(u_idx, v_idx)) {\n            cost += e.dist;\n        }\n    }\n    return cost;\n}\n\nvoid optimize_boundary_only(chrono::milliseconds time_budget) {\n    auto start = chrono::high_resolution_clock::now();\n    auto deadline = start + time_budget;\n    \n    while (chrono::high_resolution_clock::now() < deadline) {\n        bool improved = false;\n        \n        for (int i = 0; i < M - 1; ++i) {\n            if (groups[i].empty() || groups[i+1].empty()) continue;\n            \n            int cost_before = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            swap(groups[i].back(), groups[i+1].front());\n            \n            int cost_after = calc_estimated_cost(groups[i]) + calc_estimated_cost(groups[i+1]);\n            \n            if (cost_after < cost_before) {\n                improved = true;\n            } else {\n                swap(groups[i].back(), groups[i+1].front());\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\nvoid optimize_random_swaps(chrono::milliseconds time_budget, double start_temp = 10000.0) {\n    auto start = chrono::high_resolution_clock::now();\n    auto deadline = start + time_budget;\n    \n    int no_improve = 0;\n    double temp = start_temp;\n    \n    while (chrono::high_resolution_clock::now() < deadline) {\n        int g1 = uniform_int_distribution<int>(0, M-1)(rng);\n        int g2 = uniform_int_distribution<int>(0, M-1)(rng);\n        if (g1 == g2) continue;\n        \n        if (groups[g1].empty() || groups[g2].empty()) continue;\n        \n        int c1_idx = uniform_int_distribution<int>(0, (int)groups[g1].size()-1)(rng);\n        int c2_idx = uniform_int_distribution<int>(0, (int)groups[g2].size()-1)(rng);\n        \n        int cost_before = calc_estimated_cost(groups[g1]) + calc_estimated_cost(groups[g2]);\n        \n        swap(groups[g1][c1_idx], groups[g2][c2_idx]);\n        \n        int cost_after = calc_estimated_cost(groups[g1]) + calc_estimated_cost(groups[g2]);\n        \n        if (cost_after < cost_before) {\n            no_improve = 0;\n            temp = min(temp, start_temp);\n        } else {\n            double prob = exp(-(cost_after - cost_before) / max(temp, 1.0));\n            if ((double)uniform_int_distribution<int>(0, 1000000)(rng) / 1000000.0 < prob) {\n                no_improve++;\n                temp = max(temp * 0.99, 100.0);\n            } else {\n                swap(groups[g1][c1_idx], groups[g2][c2_idx]);\n                no_improve++;\n            }\n        }\n        \n        if (no_improve > 300) break;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2.0;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2.0;\n    }\n\n    // Pre-calculate all distances\n    dist_cache.assign(N, vector<int>(N, 0));\n    edge_queried.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            dist_cache[i][j] = calc_dist(i, j);\n        }\n    }\n\n    // Sort cities by X then Y for initial grouping\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (cities[a].cx != cities[b].cx) return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n\n    // Assign cities to groups\n    groups.resize(M);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(p[current_idx++]);\n        }\n    }\n\n    // Initial optimization\n    optimize_boundary_only(chrono::milliseconds(200));\n\n    // Calculate costs for each group to prioritize queries\n    vector<pair<int, int>> group_costs(M);\n    for (int i = 0; i < M; ++i) {\n        group_costs[i] = {calc_estimated_cost(groups[i]), i};\n    }\n    sort(group_costs.rbegin(), group_costs.rend());\n\n    // Query Phase\n    vector<vector<pair<int, int>>> group_queried_edges(M);\n\n    // Separate small and large groups\n    vector<int> small_groups, large_groups;\n    for (int i = 0; i < M; ++i) {\n        if (G[i] >= 3 && G[i] <= L) {\n            small_groups.push_back(i);\n        } else if (G[i] > L) {\n            large_groups.push_back(i);\n        }\n    }\n    \n    auto cmp = [&](int a, int b) {\n        return calc_estimated_cost(groups[a]) > calc_estimated_cost(groups[b]);\n    };\n    sort(small_groups.begin(), small_groups.end(), cmp);\n    sort(large_groups.begin(), large_groups.end(), cmp);\n\n    // Query small groups first\n    for (int group_idx : small_groups) {\n        if (query_cnt >= Q) break;\n        perform_query(groups[group_idx]);\n        group_queried_edges[group_idx] = read_query_response(G[group_idx]);\n    }\n\n    // Query large groups with L/4 step\n    for (int group_idx : large_groups) {\n        if (query_cnt >= Q) break;\n        \n        int step = max(2, L / 4);\n        for (int start = 0; start < G[group_idx]; start += step) {\n            if (query_cnt >= Q) break;\n            int end = min(start + L, G[group_idx]);\n            if (end - start < 2) continue;\n            \n            vector<int> subset;\n            for (int k = start; k < end; ++k) {\n                subset.push_back(groups[group_idx][k]);\n            }\n            \n            perform_query(subset);\n            vector<pair<int, int>> sub_edges = read_query_response(end - start);\n            \n            for (auto& e : sub_edges) {\n                group_queried_edges[group_idx].push_back(e);\n            }\n        }\n    }\n\n    // Post-query optimization - proven effective configuration with final fine-tuning\n    optimize_boundary_only(chrono::milliseconds(250));\n    optimize_random_swaps(chrono::milliseconds(800), 10000.0);\n    optimize_boundary_only(chrono::milliseconds(150));\n    optimize_random_swaps(chrono::milliseconds(400), 5000.0);\n    \n    // Final fine-tuning pass with very low temperature\n    optimize_boundary_only(chrono::milliseconds(100));\n    optimize_random_swaps(chrono::milliseconds(200), 1000.0);\n\n    // Final Output\n    cout << \"!\" << endl;\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            cout << groups[i][j] << (j == G[i] - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n\n        if (G[i] <= 1) continue;\n\n        vector<pair<int, int>> final_edges = build_mst(groups[i]);\n        \n        for (const auto& e : final_edges) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\n// Directions: U, D, L, R\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dirChar[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nclass SkatingSolver {\nprivate:\n    int n;\n    vector<Point> targets;\n    Point currentPos;\n    vector<vector<bool>> blocks;\n    vector<pair<char, char>> actions;\n    int actionCount = 0;\n    \n    bool isValid(int x, int y) const {\n        return x >= 0 && x < n && y >= 0 && y < n;\n    }\n    \n    bool hasBlock(int x, int y) const {\n        return isValid(x, y) && blocks[x][y];\n    }\n    \n    // Find where we would stop if we slide from (sx, sy) in direction d\n    Point slideDestination(int sx, int sy, int d) const {\n        int x = sx;\n        int y = sy;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                break;\n            }\n            x = nx;\n            y = ny;\n        }\n        \n        return {x, y};\n    }\n    \n    // Check if we can slide from (sx, sy) in direction d and reach target\n    bool canSlideToPoint(Point target, int sx, int sy, int d) const {\n        int x = sx;\n        int y = sy;\n        \n        while (true) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (!isValid(nx, ny)) return false;\n            if (nx == target.x && ny == target.y) return true;\n            if (hasBlock(nx, ny)) return false;\n            \n            x = nx;\n            y = ny;\n        }\n    }\n    \n    // Safe action execution with validation\n    bool executeAction(char action, char dir) {\n        if (actionCount >= 2 * N * M) return false;\n        \n        int d = 0;\n        if (dir == 'U') d = 0;\n        else if (dir == 'D') d = 1;\n        else if (dir == 'L') d = 2;\n        else if (dir == 'R') d = 3;\n        \n        if (action == 'M') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny) || hasBlock(nx, ny)) {\n                return false;\n            }\n            currentPos = {nx, ny};\n        } else if (action == 'S') {\n            Point dest = slideDestination(currentPos.x, currentPos.y, d);\n            if (dest == currentPos) {\n                return false;\n            }\n            currentPos = dest;\n        } else if (action == 'A') {\n            int nx = currentPos.x + dx[d];\n            int ny = currentPos.y + dy[d];\n            if (!isValid(nx, ny)) {\n                return false;\n            }\n            blocks[nx][ny] = !blocks[nx][ny];\n        }\n        \n        actions.push_back({action, dir});\n        actionCount++;\n        return true;\n    }\n    \n    // BFS to find path using Move actions (more reliable than A*)\n    bool bfsPath(Point target) {\n        using State = tuple<int, int, int>; // x, y, dist\n        queue<State> q;\n        vector<vector<int>> dist(n, vector<int>(n, INT_MAX));\n        vector<vector<int>> parentDir(n, vector<int>(n, -1));\n        vector<vector<pair<int, int>>> parent(n, vector<pair<int, int>>(n, {-1, -1}));\n        \n        q.push({currentPos.x, currentPos.y, 0});\n        dist[currentPos.x][currentPos.y] = 0;\n        \n        while (!q.empty()) {\n            auto [x, y, d] = q.front();\n            q.pop();\n            \n            if (x == target.x && y == target.y) {\n                // Reconstruct path\n                int cx = x, cy = y;\n                vector<int> dirs;\n                while (cx != currentPos.x || cy != currentPos.y) {\n                    dirs.push_back(parentDir[cx][cy]);\n                    auto [px, py] = parent[cx][cy];\n                    cx = px;\n                    cy = py;\n                }\n                \n                // Execute moves in correct order\n                for (int i = dirs.size() - 1; i >= 0; i--) {\n                    executeAction('M', dirChar[dirs[i]]);\n                }\n                \n                return true;\n            }\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                \n                if (isValid(nx, ny) && !hasBlock(nx, ny) && dist[nx][ny] == INT_MAX) {\n                    dist[nx][ny] = d + 1;\n                    parentDir[nx][ny] = dir;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny, d + 1});\n                }\n            }\n        }\n        \n        return false;\n    }\n    \n    // Check if placing a block would help future targets\n    bool blockWouldHelp(int bx, int by, int currentTargetIdx) const {\n        if (!isValid(bx, by)) return false;\n        \n        for (int i = currentTargetIdx + 1; i < min((int)targets.size(), currentTargetIdx + 4); i++) {\n            Point target = targets[i];\n            \n            // Check if this block can stop a slide to this target\n            for (int d = 0; d < 4; d++) {\n                if (bx == target.x + dx[d] && by == target.y + dy[d]) {\n                    // Check if we could potentially slide to target\n                    // from current position or nearby\n                    for (int checkX = target.x - 3; checkX <= target.x + 3; checkX++) {\n                        for (int checkY = target.y - 3; checkY <= target.y + 3; checkY++) {\n                            if (isValid(checkX, checkY)) {\n                                if (canSlideToPoint(target, checkX, checkY, d)) {\n                                    return true;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        return false;\n    }\n    \n    // Try to reach target using sliding with block placement\n    bool trySlideToTarget(Point target, int targetIdx) {\n        // Try all 4 directions for sliding\n        for (int d = 0; d < 4; d++) {\n            if (canSlideToPoint(target, currentPos.x, currentPos.y, d)) {\n                // Check if we need to place a block after target\n                int stopX = target.x + dx[d];\n                int stopY = target.y + dy[d];\n                \n                // If there's already a block or we're at boundary, we can slide directly\n                if (!isValid(stopX, stopY) || hasBlock(stopX, stopY)) {\n                    executeAction('S', dirChar[d]);\n                    return true;\n                }\n                \n                // Need to place block after target to stop the slide\n                if (executeAction('A', dirChar[d])) {\n                    executeAction('S', dirChar[d]);\n                    \n                    // Check if we should keep the block for future targets\n                    bool shouldKeep = blockWouldHelp(stopX, stopY, targetIdx);\n                    \n                    if (!shouldKeep) {\n                        executeAction('A', dirChar[d]);  // Remove block\n                    }\n                    \n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n    \n    // Try to position for next target while reaching current target\n    bool tryPositionForNextTarget(Point currentTarget, int targetIdx) {\n        if (targetIdx + 1 >= targets.size()) return false;\n        \n        Point nextTarget = targets[targetIdx + 1];\n        \n        // After reaching currentTarget, check if we can slide to nextTarget\n        for (int d = 0; d < 4; d++) {\n            if (canSlideToPoint(nextTarget, currentTarget.x, currentTarget.y, d)) {\n                // This is good - we'll be in position for next slide\n                return true;\n            }\n        }\n        \n        return false;\n    }\n    \n    // Find path to target with smart strategies\n    bool findPathToTarget(Point target, int targetIdx) {\n        // Check if we're already on the target\n        if (currentPos == target) {\n            return true;\n        }\n        \n        // Strategy 1: Try direct sliding (most efficient)\n        if (trySlideToTarget(target, targetIdx)) {\n            return true;\n        }\n        \n        // Strategy 2: Fall back to BFS with Move actions\n        if (bfsPath(target)) {\n            return true;\n        }\n        \n        return false;\n    }\n\npublic:\n    SkatingSolver(int n) : n(n) {\n        blocks.assign(n, vector<bool>(n, false));\n    }\n    \n    void setInitialPosition(int x, int y) {\n        currentPos = {x, y};\n    }\n    \n    void addTarget(int x, int y) {\n        targets.push_back({x, y});\n    }\n    \n    void solve() {\n        for (int i = 0; i < targets.size(); i++) {\n            if (actionCount >= 2 * N * M) break;\n            \n            Point target = targets[i];\n            \n            if (!findPathToTarget(target, i)) {\n                // If we can't reach the target, we're stuck\n                break;\n            }\n        }\n    }\n    \n    void output() const {\n        for (const auto& action : actions) {\n            cout << action.first << \" \" << action.second << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    SkatingSolver solver(n);\n    \n    int x, y;\n    cin >> x >> y;\n    solver.setInitialPosition(x, y);\n    \n    for (int i = 0; i < m; i++) {\n        cin >> x >> y;\n        solver.addTarget(x, y);\n    }\n    \n    solver.solve();\n    solver.output();\n    \n    return 0;\n}"}}}