{"model_name":"qwen3.5-plus","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n    double satisfaction;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\ndouble calc_satisfaction(int r, int s, bool contains) {\n    if (!contains) return 0.0;\n    double ratio = min(r, s) / (double)max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Recursive space partitioning\nvoid partition(vector<int>& indices, const vector<Company>& companies, \n               Rect region, vector<Rect>& result) {\n    if (indices.empty()) return;\n    \n    if (indices.size() == 1) {\n        result[companies[indices[0]].id] = region;\n        return;\n    }\n    \n    // Calculate total area needed\n    long long total_area = 0;\n    for (int idx : indices) {\n        total_area += companies[idx].r;\n    }\n    \n    // Find split point that balances area\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        // Sort by x then y for vertical split, or y then x for horizontal\n        long long region_w = region.x2 - region.x1;\n        long long region_h = region.y2 - region.y1;\n        if (region_w > region_h) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        } else {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        }\n    });\n    \n    // Find best split point\n    long long left_area = 0;\n    int split_idx = 0;\n    long long best_diff = LLONG_MAX;\n    \n    for (int i = 0; i < (int)indices.size() - 1; i++) {\n        left_area += companies[indices[i]].r;\n        long long diff = abs(2 * left_area - total_area);\n        if (diff < best_diff) {\n            best_diff = diff;\n            split_idx = i + 1;\n        }\n    }\n    \n    // Create split\n    long long left_sum = 0;\n    for (int i = 0; i < split_idx; i++) {\n        left_sum += companies[indices[i]].r;\n    }\n    \n    Rect left_region = region, right_region = region;\n    \n    if (region.x2 - region.x1 > region.y2 - region.y1) {\n        // Vertical split\n        int split_x = region.x1 + (int)((left_sum * (region.x2 - region.x1) + total_area/2) / total_area);\n        split_x = max(region.x1 + 1, min(region.x2 - 1, split_x));\n        left_region.x2 = split_x;\n        right_region.x1 = split_x;\n    } else {\n        // Horizontal split\n        int split_y = region.y1 + (int)((left_sum * (region.y2 - region.y1) + total_area/2) / total_area);\n        split_y = max(region.y1 + 1, min(region.y2 - 1, split_y));\n        left_region.y2 = split_y;\n        right_region.y1 = split_y;\n    }\n    \n    vector<int> left_indices(indices.begin(), indices.begin() + split_idx);\n    vector<int> right_indices(indices.begin() + split_idx, indices.end());\n    \n    partition(left_indices, companies, left_region, result);\n    partition(right_indices, companies, right_region, result);\n}\n\n// Adjust rectangle to contain point and match area\nvoid adjust_rectangle(Company& comp, Rect& rect) {\n    int target_area = comp.r;\n    int px = comp.x, py = comp.y;\n    \n    // Ensure point is contained\n    if (rect.x1 > px) rect.x1 = px;\n    if (rect.x2 <= px) rect.x2 = px + 1;\n    if (rect.y1 > py) rect.y1 = py;\n    if (rect.y2 <= py) rect.y2 = py + 1;\n    \n    // Adjust to match area\n    long long current_area = rect.area();\n    \n    if (current_area < target_area) {\n        // Expand\n        int need = target_area - current_area;\n        int width = rect.x2 - rect.x1;\n        int height = rect.y2 - rect.y1;\n        \n        // Prefer expanding in direction with more space\n        int can_expand_left = rect.x1;\n        int can_expand_right = 10000 - rect.x2;\n        int can_expand_bottom = rect.y1;\n        int can_expand_top = 10000 - rect.y2;\n        \n        while (rect.area() < target_area) {\n            int best_dir = 0;\n            int best_gain = 0;\n            \n            if (can_expand_left > 0) {\n                int gain = height;\n                if (gain > best_gain) { best_gain = gain; best_dir = 1; }\n            }\n            if (can_expand_right > 0) {\n                int gain = height;\n                if (gain > best_gain) { best_gain = gain; best_dir = 2; }\n            }\n            if (can_expand_bottom > 0) {\n                int gain = width;\n                if (gain > best_gain) { best_gain = gain; best_dir = 3; }\n            }\n            if (can_expand_top > 0) {\n                int gain = width;\n                if (gain > best_gain) { best_gain = gain; best_dir = 4; }\n            }\n            \n            if (best_dir == 0) break;\n            if (best_dir == 1) { rect.x1--; can_expand_left--; }\n            else if (best_dir == 2) { rect.x2++; can_expand_right--; }\n            else if (best_dir == 3) { rect.y1--; can_expand_bottom--; }\n            else if (best_dir == 4) { rect.y2++; can_expand_top--; }\n            \n            width = rect.x2 - rect.x1;\n            height = rect.y2 - rect.y1;\n        }\n    } else if (current_area > target_area) {\n        // Shrink\n        while (rect.area() > target_area && rect.x2 - rect.x1 > 1 && rect.y2 - rect.y1 > 1) {\n            // Shrink from side opposite to point\n            int dist_left = px - rect.x1;\n            int dist_right = rect.x2 - 1 - px;\n            int dist_bottom = py - rect.y1;\n            int dist_top = rect.y2 - 1 - py;\n            \n            int max_dist = max({dist_left, dist_right, dist_bottom, dist_top});\n            \n            if (max_dist == dist_left && rect.x2 - rect.x1 > 1) rect.x1++;\n            else if (max_dist == dist_right && rect.x2 - rect.x1 > 1) rect.x2--;\n            else if (max_dist == dist_bottom && rect.y2 - rect.y1 > 1) rect.y1++;\n            else if (max_dist == dist_top && rect.y2 - rect.y1 > 1) rect.y2--;\n            else break;\n        }\n    }\n    \n    // Final bounds check\n    rect.x1 = max(0, min(9999, rect.x1));\n    rect.y1 = max(0, min(9999, rect.y1));\n    rect.x2 = max(1, min(10000, rect.x2));\n    rect.y2 = max(1, min(10000, rect.y2));\n    if (rect.x1 >= rect.x2) rect.x2 = rect.x1 + 1;\n    if (rect.y1 >= rect.y2) rect.y2 = rect.y1 + 1;\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    }\n    \n    // Sort by position for better spatial locality\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (companies[i].x != companies[j].x)\n            return companies[i].x < companies[j].x;\n        return companies[i].y < companies[j].y;\n    });\n    \n    // Initial partitioning\n    vector<Rect> rects(n);\n    Rect full_region = {0, 0, 10000, 10000};\n    partition(order, companies, full_region, rects);\n    \n    // Adjust each rectangle to contain point and match area\n    for (int i = 0; i < n; i++) {\n        adjust_rectangle(companies[i], rects[i]);\n        companies[i].a = rects[i].x1;\n        companies[i].b = rects[i].y1;\n        companies[i].c = rects[i].x2;\n        companies[i].d = rects[i].y2;\n    }\n    \n    // Local optimization: try to swap boundaries between adjacent rectangles\n    // Simple greedy improvement\n    for (int iter = 0; iter < 100; iter++) {\n        bool improved = false;\n        \n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                // Check if rectangles are adjacent\n                Rect& ri = rects[i];\n                Rect& rj = rects[j];\n                \n                // Simple adjacency check\n                bool adjacent = false;\n                if (ri.x2 == rj.x1 || rj.x2 == ri.x1) {\n                    if (max(ri.y1, rj.y1) < min(ri.y2, rj.y2)) adjacent = true;\n                }\n                if (ri.y2 == rj.y1 || rj.y2 == ri.y1) {\n                    if (max(ri.x1, rj.x1) < min(ri.x2, rj.x2)) adjacent = true;\n                }\n                \n                if (!adjacent) continue;\n                \n                // Try small adjustments\n                double current_score = calc_satisfaction(companies[i].r, ri.area(), ri.contains(companies[i].x, companies[i].y)) +\n                                      calc_satisfaction(companies[j].r, rj.area(), rj.contains(companies[j].x, companies[j].y));\n                \n                double best_score = current_score;\n                int best_ri = ri.x1, best_ri2 = ri.x2, best_ri3 = ri.y1, best_ri4 = ri.y2;\n                int best_rj = rj.x1, best_rj2 = rj.x2, best_rj3 = rj.y1, best_rj4 = rj.y2;\n                \n                // Try moving boundary by 1 pixel\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        if (dx == 0 && dy == 0) continue;\n                        \n                        Rect test_ri = ri, test_rj = rj;\n                        \n                        // Simple boundary adjustment\n                        if (ri.x2 == rj.x1 && dx != 0) {\n                            test_ri.x2 += dx;\n                            test_rj.x1 += dx;\n                        } else if (rj.x2 == ri.x1 && dx != 0) {\n                            test_rj.x2 += dx;\n                            test_ri.x1 += dx;\n                        } else if (ri.y2 == rj.y1 && dy != 0) {\n                            test_ri.y2 += dy;\n                            test_rj.y1 += dy;\n                        } else if (rj.y2 == ri.y1 && dy != 0) {\n                            test_rj.y2 += dy;\n                            test_ri.y1 += dy;\n                        }\n                        \n                        // Validate\n                        if (test_ri.x1 >= test_ri.x2 || test_ri.y1 >= test_ri.y2) continue;\n                        if (test_rj.x1 >= test_rj.x2 || test_rj.y1 >= test_rj.y2) continue;\n                        if (test_ri.x1 < 0 || test_ri.x2 > 10000 || test_ri.y1 < 0 || test_ri.y2 > 10000) continue;\n                        if (test_rj.x1 < 0 || test_rj.x2 > 10000 || test_rj.y1 < 0 || test_rj.y2 > 10000) continue;\n                        \n                        double new_score = calc_satisfaction(companies[i].r, test_ri.area(), test_ri.contains(companies[i].x, companies[i].y)) +\n                                          calc_satisfaction(companies[j].r, test_rj.area(), test_rj.contains(companies[j].x, companies[j].y));\n                        \n                        if (new_score > best_score) {\n                            best_score = new_score;\n                            best_ri = test_ri.x1; best_ri2 = test_ri.x2; best_ri3 = test_ri.y1; best_ri4 = test_ri.y2;\n                            best_rj = test_rj.x1; best_rj2 = test_rj.x2; best_rj3 = test_rj.y1; best_rj4 = test_rj.y2;\n                        }\n                    }\n                }\n                \n                if (best_score > current_score) {\n                    ri.x1 = best_ri; ri.x2 = best_ri2; ri.y1 = best_ri3; ri.y2 = best_ri4;\n                    rj.x1 = best_rj; rj.x2 = best_rj2; rj.y1 = best_rj3; rj.y2 = best_rj4;\n                    companies[i].a = ri.x1; companies[i].b = ri.y1; companies[i].c = ri.x2; companies[i].d = ri.y2;\n                    companies[j].a = rj.x1; companies[j].b = rj.y1; companies[j].c = rj.x2; companies[j].d = rj.y2;\n                    improved = true;\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" \n             << companies[i].c << \" \" << 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\nusing namespace std;\n\n// Global grid data\nconst int H = 50;\nconst int W = 50;\nvector<vector<int>> tile_id;\nvector<vector<int>> score_val;\nint max_tile = 0;\n\n// Search state\nvector<char> visited_tiles;\nmt19937 rng;\n\n// Heuristic extension of the path\nvoid extend_path(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    // Directions: U, D, L, R\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    \n    while (true) {\n        // Collect valid neighbors\n        struct Cand {\n            int r, c, score, degree;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    int s = score_val[nr][nc];\n                    int deg = 0;\n                    // Lookahead 1 step: count available moves from neighbor\n                    for(int k=0; k<4; ++k) {\n                        int nnr = nr + dr[k];\n                        int nnc = nc + dc[k];\n                        if(nnr >= 0 && nnr < H && nnc >= 0 && nnc < W) {\n                            if(!visited_tiles[tile_id[nnr][nnc]]) deg++;\n                        }\n                    }\n                    cands[count++] = {nr, nc, s, deg};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort candidates: higher (score + degree) first\n        // Since count <= 4, simple sort is very fast\n        for(int i=0; i<count-1; ++i) {\n            for(int j=0; j<count-1-i; ++j) {\n                int val1 = cands[j].score + cands[j].degree;\n                int val2 = cands[j+1].score + cands[j+1].degree;\n                if(val1 < val2) {\n                    swap(cands[j], cands[j+1]);\n                }\n            }\n        }\n        \n        // Pick from top min(3, count) to add randomness\n        int K = (count < 3) ? count : 3;\n        int idx = (int)(rng() % K);\n        \n        int nr = cands[idx].r;\n        int nc = cands[idx].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    tile_id.assign(H, vector<int>(W));\n    max_tile = 0;\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> tile_id[i][j];\n            if (tile_id[i][j] > max_tile) max_tile = tile_id[i][j];\n        }\n    }\n    \n    score_val.assign(H, vector<int>(W));\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> score_val[i][j];\n        }\n    }\n    \n    visited_tiles.assign(max_tile + 1, 0);\n    \n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Initial Solution\n    vector<pair<int, int>> current_path;\n    current_path.reserve(2500);\n    current_path.push_back({si, sj});\n    visited_tiles[tile_id[si][sj]] = 1;\n    long long current_score = score_val[si][sj];\n    \n    extend_path(current_path, current_score);\n    \n    vector<pair<int, int>> best_path = current_path;\n    long long best_score = current_score;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    double temperature = 500.0; \n    \n    // Main Search Loop (Simulated Annealing / Iterated Local Search)\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto ms = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (ms > 1900) break; // Stop at 1.9s to ensure output within 2.0s\n        \n        // Cooling schedule\n        temperature *= 0.9995;\n        if (temperature < 1.0) temperature = 1.0;\n        \n        // Backup current state to allow rollback if move is rejected\n        vector<pair<int, int>> path_backup = current_path;\n        long long score_backup = current_score;\n        \n        // Select a cut point uniformly\n        int cut_idx = (int)(rng() % current_path.size());\n        \n        // Rollback visited tiles for the part we are cutting\n        for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n            int r = current_path[i].first;\n            int c = current_path[i].second;\n            visited_tiles[tile_id[r][c]] = 0;\n        }\n        current_path.resize(cut_idx + 1);\n        \n        // Recalculate score for the prefix\n        long long temp_score = 0;\n        for(const auto& p : current_path) temp_score += score_val[p.first][p.second];\n        \n        // Extend path from cut point\n        extend_path(current_path, temp_score);\n        \n        // Simulated Annealing Acceptance Criterion\n        bool accept = false;\n        if (temp_score > current_score) {\n            accept = true;\n        } else {\n            double diff = (double)(temp_score - current_score);\n            double prob = exp(diff / temperature);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = temp_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n            }\n        } else {\n            // Revert to backup state\n            \n            // 1. Unmark the tiles added in the failed extension\n            for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 0;\n            }\n            \n            // 2. Restore path and score\n            current_path = path_backup;\n            current_score = score_backup;\n            \n            // 3. Re-mark the tiles of the original suffix that were unmarked at the start\n            for (size_t i = cut_idx + 1; i < current_path.size(); ++i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 1;\n            }\n        }\n    }\n    \n    // Construct Output String\n    string res;\n    if (best_path.size() > 1) {\n        res.reserve(best_path.size() - 1);\n        for (size_t i = 1; i < best_path.size(); ++i) {\n            int dr = best_path[i].first - best_path[i-1].first;\n            int dc = best_path[i].second - best_path[i-1].second;\n            if (dr == -1) res += 'U';\n            else if (dr == 1) res += 'D';\n            else if (dc == -1) res += 'L';\n            else if (dc == 1) res += 'R';\n        }\n    }\n    cout << res << endl;\n    \n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Solver {\n    double h[N][N-1];  // horizontal edges: h[i][j] = edge from (i,j) to (i,j+1)\n    double v[N-1][N];  // vertical edges: v[i][j] = edge from (i,j) to (i+1,j)\n    int h_cnt[N][N-1];\n    int v_cnt[N-1][N];\n    \n    Solver() {\n        for(int i = 0; i < N; i++) {\n            for(int j = 0; j < N-1; j++) {\n                h[i][j] = 5000.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for(int i = 0; i < N-1; i++) {\n            for(int j = 0; j < N; j++) {\n                v[i][j] = 5000.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n    \n    // Get edge weight with bounds checking\n    double get_weight(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v[i-1][j] : 1e9;\n        if(dir == 'D') return (i < N-1) ? v[i][j] : 1e9;\n        if(dir == 'L') return (j > 0) ? h[i][j-1] : 1e9;\n        if(dir == 'R') return (j < N-1) ? h[i][j] : 1e9;\n        return 1e9;\n    }\n    \n    // Get visit count for an edge\n    int get_count(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v_cnt[i-1][j] : 0;\n        if(dir == 'D') return (i < N-1) ? v_cnt[i][j] : 0;\n        if(dir == 'L') return (j > 0) ? h_cnt[i][j-1] : 0;\n        if(dir == 'R') return (j < N-1) ? h_cnt[i][j] : 0;\n        return 0;\n    }\n    \n    pair<string, double> dijkstra(int si, int sj, int ti, int tj, double temp) {\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<char>> move(N, vector<char>(N, 0));\n        \n        dist[si][sj] = 0;\n        pq.push({0.0, si, sj});\n        \n        const char dirs[] = {'U', 'D', 'L', 'R'};\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while(!pq.empty()) {\n            auto [d, i, j] = pq.top();\n            pq.pop();\n            \n            if(d > dist[i][j] + 1e-9) continue;\n            if(i == ti && j == tj) break;\n            \n            for(int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                \n                if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double w = get_weight(i, j, dirs[dir]);\n                if(w >= 1e9) continue;\n                \n                // Exploration bonus: prefer less-visited edges\n                int cnt = get_count(i, j, dirs[dir]);\n                double bonus = temp / (cnt + 1);\n                double new_dist = d + w + bonus;\n                \n                if(new_dist < dist[ni][nj]) {\n                    dist[ni][nj] = new_dist;\n                    prev[ni][nj] = {i, j};\n                    move[ni][nj] = dirs[dir];\n                    pq.push({new_dist, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path;\n        int ci = ti, cj = tj;\n        while(ci != si || cj != sj) {\n            path += move[ci][cj];\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        \n        return {path, dist[ti][tj]};\n    }\n    \n    void update(const string& path, int si, int sj, int observed, int query_num) {\n        if(path.empty()) return;\n        \n        // Calculate estimated cost and track vertices\n        double estimated = 0;\n        int ci = si, cj = sj;\n        vector<tuple<int, int, char>> edges;\n        \n        for(char c : path) {\n            double w = get_weight(ci, cj, c);\n            estimated += w;\n            edges.push_back({ci, cj, c});\n            \n            if(c == 'U') ci--;\n            else if(c == 'D') ci++;\n            else if(c == 'L') cj--;\n            else if(c == 'R') cj++;\n        }\n        \n        if(estimated < 1) estimated = 1;\n        double ratio = (double)observed / estimated;\n        \n        // Learning rate decreases over time\n        double lr = 0.30 * pow(0.992, query_num);\n        lr = max(lr, 0.01);\n        \n        // Update edges on path\n        for(auto& [i, j, c] : edges) {\n            if(c == 'U') {\n                v[i-1][j] = (1-lr) * v[i-1][j] + lr * v[i-1][j] * ratio;\n                v_cnt[i-1][j]++;\n            } else if(c == 'D') {\n                v[i][j] = (1-lr) * v[i][j] + lr * v[i][j] * ratio;\n                v_cnt[i][j]++;\n            } else if(c == 'L') {\n                h[i][j-1] = (1-lr) * h[i][j-1] + lr * h[i][j-1] * ratio;\n                h_cnt[i][j-1]++;\n            } else if(c == 'R') {\n                h[i][j] = (1-lr) * h[i][j] + lr * h[i][j] * ratio;\n                h_cnt[i][j]++;\n            }\n        }\n        \n        // Smoothing: propagate information to same row/column\n        smooth(query_num);\n    }\n    \n    void smooth(int query_num) {\n        double smooth_lr = 0.05 * pow(0.995, query_num);\n        \n        // Smooth horizontal edges within each row\n        for(int i = 0; i < N; i++) {\n            double row_avg = 0;\n            int row_cnt = 0;\n            for(int j = 0; j < N-1; j++) {\n                if(h_cnt[i][j] > 0) {\n                    row_avg += h[i][j];\n                    row_cnt++;\n                }\n            }\n            if(row_cnt > 0) {\n                row_avg /= row_cnt;\n                for(int j = 0; j < N-1; j++) {\n                    if(h_cnt[i][j] > 0) {\n                        h[i][j] = (1-smooth_lr) * h[i][j] + smooth_lr * row_avg;\n                    }\n                }\n            }\n        }\n        \n        // Smooth vertical edges within each column\n        for(int j = 0; j < N; j++) {\n            double col_avg = 0;\n            int col_cnt = 0;\n            for(int i = 0; i < N-1; i++) {\n                if(v_cnt[i][j] > 0) {\n                    col_avg += v[i][j];\n                    col_cnt++;\n                }\n            }\n            if(col_cnt > 0) {\n                col_avg /= col_cnt;\n                for(int i = 0; i < N-1; i++) {\n                    if(v_cnt[i][j] > 0) {\n                        v[i][j] = (1-smooth_lr) * v[i][j] + smooth_lr * col_avg;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    mt19937 rng(42);\n    Solver solver;\n    \n    for(int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Exploration temperature decreases over time\n        // Higher early for exploration, lower later for exploitation\n        double temp = 300.0 * pow(0.994, k);\n        \n        auto [path, est_cost] = solver.dijkstra(si, sj, ti, tj, temp);\n        \n        cout << path << \"\\n\";\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        solver.update(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n\nusing namespace std;\n\nint main() {\n    const int N = 20;\n    int M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> S[i];\n    }\n\n    vector<string> grid(N, string(N, '.'));\n    vector<int> indices(M);\n    for (int i = 0; i < M; ++i) indices[i] = i;\n\n    // Process longer strings first to lock in more constrained placements\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return S[a].size() > S[b].size();\n    });\n\n    for (int idx : indices) {\n        const string& s = S[idx];\n        int k = s.size();\n        int best_orient = -1;\n        int best_start_i = -1;\n        int best_start_j = -1;\n        int max_dot = -1;\n\n        // Check all horizontal placements\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int col = (j + p) % N;\n                    if (grid[i][col] != '.' && grid[i][col] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[i][col] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 0;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        // Check all vertical placements\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ++i) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int row = (i + p) % N;\n                    if (grid[row][j] != '.' && grid[row][j] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[row][j] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 1;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        if (max_dot >= 0) {\n            for (int p = 0; p < k; ++p) {\n                int i, j;\n                if (best_orient == 0) {\n                    i = best_start_i;\n                    j = (best_start_j + p) % N;\n                } else {\n                    i = (best_start_i + p) % N;\n                    j = best_start_j;\n                }\n                if (grid[i][j] == '.') {\n                    grid[i][j] = s[p];\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << grid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <map>\n#include <functional>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> h_id, v_id;\nint h_count = 0, v_count = 0;\n\nint flatten(int r, int c) {\n    return r * N + c;\n}\n\nPoint unflatten(int idx) {\n    return {idx / N, idx % N};\n}\n\nint get_cost(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N || grid[r][c] == '#') return 1e9;\n    return grid[r][c] - '0';\n}\n\n// Reconstruct path from parents\nstring reconstruct_path(int start_node, int end_node, const vector<int>& parent) {\n    if (start_node == end_node) return \"\";\n    vector<int> path;\n    int curr = end_node;\n    while (curr != start_node) {\n        if (curr == -1) return \"\"; // Should not happen in connected graph\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    \n    string res = \"\";\n    int curr_r = start_node / N;\n    int curr_c = start_node % N;\n    \n    for (int node : path) {\n        int nr = node / N;\n        int nc = node % N;\n        if (nr < curr_r) res += 'U';\n        else if (nr > curr_r) res += 'D';\n        else if (nc < curr_c) res += 'L';\n        else if (nc > curr_c) res += 'R';\n        curr_r = nr;\n        curr_c = nc;\n    }\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // 1. Identify Segments\n    h_id.assign(N, vector<int>(N, -1));\n    v_id.assign(N, vector<int>(N, -1));\n\n    // Horizontal\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            int start = j;\n            while (j < N && grid[i][j] != '#') j++;\n            for (int k = start; k < j; ++k) {\n                h_id[i][k] = h_count;\n            }\n            h_count++;\n        }\n    }\n\n    // Vertical\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            int start = i;\n            while (i < N && grid[i][j] != '#') i++;\n            for (int k = start; k < i; ++k) {\n                v_id[k][j] = v_count;\n            }\n            v_count++;\n        }\n    }\n\n    // 2. Build Bipartite Graph\n    vector<pair<int, int>> edges; \n    vector<Point> edge_to_point;\n    map<pair<int, int>, int> edge_index;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                int h = h_id[i][j];\n                int v = v_id[i][j];\n                if (edge_index.find({h, v}) == edge_index.end()) {\n                    edge_index[{h, v}] = edges.size();\n                    edges.push_back({h, v});\n                    edge_to_point.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> bip_adj(h_count);\n    for (auto& e : edges) {\n        bip_adj[e.first].push_back(e.second);\n    }\n\n    // 3. Max Bipartite Matching (DFS)\n    vector<int> match_h(h_count, -1), match_v(v_count, -1);\n\n    function<bool(int, vector<bool>&)> dfs = [&](int u, vector<bool>& visited) {\n        for (int v : bip_adj[u]) {\n            if (visited[v]) continue;\n            visited[v] = true;\n            if (match_v[v] < 0 || dfs(match_v[v], visited)) {\n                match_h[u] = v;\n                match_v[v] = u;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    for (int i = 0; i < h_count; ++i) {\n        vector<bool> visited(v_count, false);\n        dfs(i, visited);\n    }\n\n    // 4. Construct Edge Cover\n    vector<bool> h_covered(h_count, false);\n    vector<bool> v_covered(v_count, false);\n    vector<bool> edge_in_cover(edges.size(), false);\n    vector<Point> selected_points;\n\n    // Add matching edges\n    for (int i = 0; i < h_count; ++i) {\n        if (match_h[i] != -1) {\n            auto it = edge_index.find({i, match_h[i]});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[match_h[i]] = true;\n            }\n        }\n    }\n\n    // Cover unmatched H\n    for (int i = 0; i < h_count; ++i) {\n        if (!h_covered[i] && !bip_adj[i].empty()) {\n            int v = bip_adj[i][0];\n            auto it = edge_index.find({i, v});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[v] = true;\n            }\n        }\n    }\n    // Cover unmatched V\n    for (int i = 0; i < v_count; ++i) {\n        if (!v_covered[i]) {\n            for (int j = 0; j < edges.size(); ++j) {\n                if (edges[j].second == i) {\n                    edge_in_cover[j] = true;\n                    v_covered[i] = true;\n                    h_covered[edges[j].first] = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < edges.size(); ++i) {\n        if (edge_in_cover[i]) {\n            selected_points.push_back(edge_to_point[i]);\n        }\n    }\n\n    // Add start point\n    Point start_p = {si, sj};\n    bool start_present = false;\n    for (auto& p : selected_points) {\n        if (p == start_p) {\n            start_present = true;\n            break;\n        }\n    }\n    if (!start_present) selected_points.push_back(start_p);\n\n    int K = selected_points.size();\n    vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n    vector<vector<vector<int>>> parents(K, vector<vector<int>>(N * N, -1));\n\n    // 5. All-Pairs Shortest Paths\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < K; ++i) {\n        int sr = selected_points[i].r;\n        int sc = selected_points[i].c;\n        int start_node = flatten(sr, sc);\n        \n        vector<long long> d(N * N, -1);\n        vector<int> p(N * N, -1);\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n\n        d[start_node] = 0;\n        pq.push({0, start_node});\n\n        while (!pq.empty()) {\n            auto [dist_val, u] = pq.top();\n            pq.pop();\n\n            if (d[u] != -1 && dist_val > d[u]) continue;\n\n            Point pu = unflatten(u);\n            for (int k = 0; k < 4; ++k) {\n                int nr = pu.r + dr[k];\n                int nc = pu.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                    int v = flatten(nr, nc);\n                    long long new_dist = dist_val + get_cost(nr, nc);\n                    if (d[v] == -1 || new_dist < d[v]) {\n                        d[v] = new_dist;\n                        p[v] = u;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n        \n        for (int j = 0; j < K; ++j) {\n            int tr = selected_points[j].r;\n            int tc = selected_points[j].c;\n            int t_node = flatten(tr, tc);\n            dist_mat[i][j] = d[t_node];\n            parents[i] = p;\n        }\n    }\n\n    // 6. TSP\n    int start_idx = -1;\n    for(int i=0; i<K; ++i) {\n        if(selected_points[i] == start_p) {\n            start_idx = i;\n            break;\n        }\n    }\n    \n    // Nearest Neighbor\n    vector<int> tour;\n    vector<bool> visited(K, false);\n    int curr = start_idx;\n    tour.push_back(curr);\n    visited[curr] = true;\n    \n    for (int i = 0; i < K - 1; ++i) {\n        int next = -1;\n        long long min_d = -1;\n        for (int j = 0; j < K; ++j) {\n            if (!visited[j]) {\n                if (next == -1 || dist_mat[curr][j] < min_d) {\n                    min_d = dist_mat[curr][j];\n                    next = j;\n                }\n            }\n        }\n        if (next != -1) {\n            tour.push_back(next);\n            visited[next] = true;\n            curr = next;\n        }\n    }\n    \n    // 2-opt\n    bool improved = true;\n    int iterations = 0;\n    while (improved && iterations < 2000) {\n        improved = false;\n        iterations++;\n        for (int i = 0; i < K - 1; ++i) {\n            for (int j = i + 1; j < K; ++j) {\n                if (i + 1 >= j) continue;\n                \n                int u = tour[i];\n                int v = tour[i+1];\n                int x = tour[j];\n                int y = tour[(j+1)%K];\n                \n                // Check for overflow or unreachable\n                if (dist_mat[u][x] == -1 || dist_mat[v][y] == -1) continue;\n                if (dist_mat[u][v] == -1 || dist_mat[x][y] == -1) continue;\n\n                long long old_cost = dist_mat[u][v] + dist_mat[x][y];\n                long long new_cost = dist_mat[u][x] + dist_mat[v][y];\n                \n                if (new_cost < old_cost) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Reconstruct Full Path\n    string final_path = \"\";\n    for (int i = 0; i < K; ++i) {\n        int u = tour[i];\n        int v = tour[(i + 1) % K];\n        string segment = reconstruct_path(flatten(selected_points[u].r, selected_points[u].c), \n                                          flatten(selected_points[v].r, selected_points[v].c), \n                                          parents[u]);\n        final_path += segment;\n    }\n\n    cout << final_path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Maximum number of tasks as per constraints\nconst int MAX_N = 1005;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int in_degree = 0;\n    vector<int> dependents; \n    int priority = 0; \n    int status = -1; // -1: not started, 0: running, 1: done\n    int assigned_member = -1;\n};\n\nstruct Member {\n    int id;\n    vector<int> s; \n    int busy_until = 0; \n    int current_task = -1;\n    int start_day = 0;\n    int tasks_completed = 0;\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, K, R;\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // 1-based indexing for tasks\n    vector<Task> tasks(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int j = 0; j < K; ++j) {\n            cin >> tasks[i].d[j];\n        }\n    }\n\n    // Read dependencies\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        tasks[v].in_degree++;\n        tasks[u].dependents.push_back(v);\n    }\n\n    // Compute priority (downstream count) using bitsets for reachability\n    // Since u < v, we can process in reverse order to propagate reachability\n    vector<bitset<MAX_N>> reach(N + 1);\n    for (int i = N; i >= 1; --i) {\n        reach[i][i] = 1;\n        for (int v : tasks[i].dependents) {\n            reach[i] |= reach[v];\n        }\n        tasks[i].priority = (int)reach[i].count();\n    }\n\n    // Initialize members\n    vector<Member> members(M + 1);\n    for (int j = 1; j <= M; ++j) {\n        members[j].id = j;\n        members[j].s.assign(K, 0); // Initialize skill estimates to 0\n        members[j].busy_until = 0;\n    }\n\n    // Initial ready tasks (in_degree == 0)\n    vector<int> ready_tasks;\n    ready_tasks.reserve(N);\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            ready_tasks.push_back(i);\n        }\n    }\n\n    int current_day = 0;\n    const double ALPHA_BASE = 0.5;\n\n    while (true) {\n        current_day++;\n        \n        // 1. Decide assignments for free members\n        vector<pair<int, int>> assignments;\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int j = 1; j <= M; ++j) {\n            if (members[j].busy_until < current_day) {\n                free_members.push_back(j);\n            }\n        }\n\n        if (!free_members.empty() && !ready_tasks.empty()) {\n            // Filter ready_tasks to get valid candidates (status == -1)\n            vector<int> candidates;\n            candidates.reserve(ready_tasks.size());\n            for (int t_idx : ready_tasks) {\n                if (tasks[t_idx].status == -1) {\n                    candidates.push_back(t_idx);\n                }\n            }\n            \n            // Sort candidates by priority (descending) to schedule critical tasks first\n            sort(candidates.begin(), candidates.end(), [&](int a, int b) {\n                return tasks[a].priority > tasks[b].priority;\n            });\n\n            for (int t_idx : candidates) {\n                if (tasks[t_idx].status != -1) continue; \n                if (free_members.empty()) break;\n\n                int best_m = -1;\n                int min_t = 2000000000;\n                \n                // Find best member for this task based on estimated completion time\n                for (int m_idx : free_members) {\n                    int w = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                            w += tasks[t_idx].d[k] - members[m_idx].s[k];\n                        }\n                    }\n                    // Estimated time: if w=0 then 1, else approx w (ignoring noise for estimation)\n                    int t_est = max(1, w); \n                    if (t_est < min_t) {\n                        min_t = t_est;\n                        best_m = m_idx;\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_idx});\n                    tasks[t_idx].status = 0; // Running\n                    tasks[t_idx].assigned_member = best_m;\n                    members[best_m].busy_until = current_day + min_t - 1;\n                    members[best_m].current_task = t_idx;\n                    members[best_m].start_day = current_day;\n                    \n                    // Remove from free_members list\n                    for (auto it = free_members.begin(); it != free_members.end(); ++it) {\n                        if (*it == best_m) {\n                            free_members.erase(it);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << \"\\n\";\n        cout.flush();\n\n        // 2. Read completion info from Judge\n        int n_fin;\n        cin >> n_fin;\n        if (n_fin == -1) {\n            break;\n        }\n\n        vector<int> finished_members(n_fin);\n        for (int i = 0; i < n_fin; ++i) {\n            cin >> finished_members[i];\n        }\n\n        // 3. Update state and Skill Estimates\n        for (int m_idx : finished_members) {\n            int t_idx = members[m_idx].current_task;\n            if (t_idx == -1) continue; \n\n            // Calculate actual duration\n            int duration = current_day - members[m_idx].start_day + 1;\n            int t_obs = duration;\n            \n            // Skill Update Logic\n            // Model: t \u2248 1 + sum(max(0, d_k - s_k))\n            // We perform gradient descent on s_k to minimize (t_obs - t_pred)^2\n            int w_pred = 0;\n            vector<int> active_dims;\n            active_dims.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                    w_pred += tasks[t_idx].d[k] - members[m_idx].s[k];\n                    active_dims.push_back(k);\n                }\n            }\n            int t_pred = (w_pred == 0) ? 1 : w_pred;\n            \n            double error = (double)t_obs - t_pred;\n            \n            // Only update if there are active dimensions (deficits)\n            // If w_pred == 0 and t_obs > 1, it's likely noise, so we skip update to avoid destabilizing s_k >= d_k\n            if (!active_dims.empty()) {\n                // Learning rate decays with number of tasks completed\n                double alpha = ALPHA_BASE / sqrt(max(1, members[m_idx].tasks_completed + 1));\n                double update_per_dim = alpha * error / active_dims.size();\n                \n                for (int k : active_dims) {\n                    // If t_obs > t_pred (error > 0), we underestimated time -> overestimated skills -> decrease s_k\n                    // If t_obs < t_pred (error < 0), we overestimated time -> underestimated skills -> increase s_k\n                    // Update: s_new = s_old - alpha * error\n                    double new_s = members[m_idx].s[k] - update_per_dim;\n                    members[m_idx].s[k] = (int)round(new_s);\n                    if (members[m_idx].s[k] < 0) members[m_idx].s[k] = 0;\n                }\n            }\n\n            // Update Task Status\n            tasks[t_idx].status = 1; // Done\n            members[m_idx].current_task = -1;\n            members[m_idx].tasks_completed++;\n\n            // Update Dependencies\n            for (int v : tasks[t_idx].dependents) {\n                tasks[v].in_degree--;\n                if (tasks[v].in_degree == 0) {\n                    ready_tasks.push_back(v);\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n    int dist;\n};\n\nstruct Point {\n    int x, y;\n};\n\ninline int get_dist(Point p1, Point p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\n// Global data\nvector<Order> orders;\nPoint center = {400, 400};\nPoint all_points[2000]; // 0..1999. 2*i is pickup, 2*i+1 is delivery for order i\n\n// Current State\nvector<pair<int, int>> path; // pair<order_id, type(0=P, 1=D)>\nint pos[1000][2]; // pos[order_id][type] -> index in path\nbool in_selected[1000];\nint current_cost;\nint best_cost;\nvector<pair<int, int>> best_path;\nbool best_in_selected[1000];\n\nint calc_total_cost(const vector<pair<int, int>>& p) {\n    int cost = 0;\n    Point prev = center;\n    for (const auto& node : p) {\n        Point curr = all_points[node.first * 2 + node.second];\n        cost += get_dist(prev, curr);\n        prev = curr;\n    }\n    cost += get_dist(prev, center);\n    return cost;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read Input\n    orders.resize(1000);\n    for (int i = 0; i < 1000; ++i) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        orders[i].dist = abs(orders[i].ax - orders[i].cx) + abs(orders[i].ay - orders[i].cy);\n        all_points[2 * i] = {orders[i].ax, orders[i].ay};\n        all_points[2 * i + 1] = {orders[i].cx, orders[i].cy};\n    }\n\n    // Random Setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    uniform_int_distribution<int> dist_ord(0, 999);\n    uniform_int_distribution<int> dist_path(0, 99);\n\n    // Initial Selection\n    // Heuristic: Pick orders with small (dist(P, D) + dist(Center, P) + dist(Center, D))\n    vector<pair<int, int>> order_costs;\n    order_costs.reserve(1000);\n    for (int i = 0; i < 1000; ++i) {\n        int c = orders[i].dist + get_dist(center, all_points[2 * i]) + get_dist(center, all_points[2 * i + 1]);\n        order_costs.push_back({c, i});\n    }\n    sort(order_costs.begin(), order_costs.end());\n\n    fill(in_selected, in_selected + 1000, false);\n    vector<int> selected_indices;\n    selected_indices.reserve(50);\n    for (int i = 0; i < 50; ++i) {\n        int idx = order_costs[i].second;\n        in_selected[idx] = true;\n        selected_indices.push_back(idx);\n    }\n\n    // Initial Path Construction\n    // Sort selected orders by angle of midpoint\n    vector<pair<double, int>> sorted_orders;\n    sorted_orders.reserve(50);\n    for (int idx : selected_indices) {\n        int mx = (orders[idx].ax + orders[idx].cx) / 2;\n        int my = (orders[idx].ay + orders[idx].cy) / 2;\n        double angle = atan2(my - 400, mx - 400);\n        sorted_orders.push_back({angle, idx});\n    }\n    sort(sorted_orders.begin(), sorted_orders.end());\n\n    path.clear();\n    path.reserve(100);\n    for (const auto& p : sorted_orders) {\n        int idx = p.second;\n        path.push_back({idx, 0}); // Pickup\n        path.push_back({idx, 1}); // Delivery\n    }\n\n    // Initialize pos array\n    for(int i=0; i<1000; ++i) {\n        pos[i][0] = -1;\n        pos[i][1] = -1;\n    }\n    for (int i = 0; i < 100; ++i) {\n        pos[path[i].first][path[i].second] = i;\n    }\n\n    current_cost = calc_total_cost(path);\n    best_cost = current_cost;\n    best_path = path;\n    copy(in_selected, in_selected + 1000, best_in_selected);\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95; // seconds\n    \n    double temp = 10000.0;\n    // Adjust cooling rate to approximate cooling to ~1 over expected iterations\n    // We don't know exact iterations, but ~300k is a good guess for 2s\n    double cooling_rate = 0.99997; \n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        temp *= cooling_rate;\n        if (temp < 1.0) temp = 1.0;\n\n        // Decide move type\n        // 98% Path Move, 2% Order Swap\n        if (dist_01(rng) < 0.98) {\n            // Path Move: Swap two nodes\n            int i = dist_path(rng);\n            int j = dist_path(rng);\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            \n            int u = path[i].first;\n            int v = path[j].first;\n            int type_u = path[i].second;\n            int type_v = path[j].second;\n            \n            // Check validity quickly\n            bool ok = true;\n            \n            // For u:\n            int other_pos_u = pos[u][1 - type_u];\n            if (type_u == 0) { // P moving to j\n                if (j > other_pos_u) ok = false;\n            } else { // D moving to j\n                if (j < other_pos_u) ok = false;\n            }\n            \n            if (ok) {\n                // For v:\n                int other_pos_v = pos[v][1 - type_v];\n                if (type_v == 0) { // P moving to i\n                    if (i > other_pos_v) ok = false;\n                } else { // D moving to i\n                    if (i < other_pos_v) ok = false;\n                }\n            }\n            \n            if (ok) {\n                // Calculate delta cost\n                vector<pair<int, int>> edges;\n                edges.push_back({i-1, i});\n                edges.push_back({i, i+1});\n                if (j != i+1 && j != i) {\n                    edges.push_back({j-1, j});\n                    edges.push_back({j, j+1});\n                }\n                \n                int delta = 0;\n                for (const auto& e : edges) {\n                    int u_idx = e.first;\n                    int v_idx = e.second;\n                    \n                    auto get_pt = [&](int idx, const vector<pair<int, int>>& p) {\n                        if (idx < 0 || idx >= 100) return center;\n                        return all_points[p[idx].first * 2 + p[idx].second];\n                    };\n                    \n                    // For new state, path[i] and path[j] swapped.\n                    auto get_content = [&](int k) {\n                        if (k == i) return path[j];\n                        if (k == j) return path[i];\n                        return path[k];\n                    };\n                    \n                    Point p1_old = (u_idx == -1 || u_idx == 100) ? center : all_points[path[u_idx].first * 2 + path[u_idx].second];\n                    Point p2_old = (v_idx == -1 || v_idx == 100) ? center : all_points[path[v_idx].first * 2 + path[v_idx].second];\n                    \n                    Point p1_new = (u_idx == -1 || u_idx == 100) ? center : all_points[get_content(u_idx).first * 2 + get_content(u_idx).second];\n                    Point p2_new = (v_idx == -1 || v_idx == 100) ? center : all_points[get_content(v_idx).first * 2 + get_content(v_idx).second];\n                    \n                    // Handle boundaries for old points properly\n                    if (u_idx < 0 || u_idx >= 100) p1_old = center;\n                    if (v_idx < 0 || v_idx >= 100) p2_old = center;\n                    if (u_idx < 0 || u_idx >= 100) p1_new = center;\n                    if (v_idx < 0 || v_idx >= 100) p2_new = center;\n\n                    delta += get_dist(p1_new, p2_new) - get_dist(p1_old, p2_old);\n                }\n                \n                if (delta < 0 || dist_01(rng) < exp(-delta / temp)) {\n                    swap(path[i], path[j]);\n                    pos[u][type_u] = j;\n                    pos[v][type_v] = i;\n                    current_cost += delta;\n                }\n            }\n        } else {\n            // Order Swap\n            int rem_idx = -1;\n            int add_idx = -1;\n            \n            int attempts = 0;\n            while(attempts < 20) {\n                int cand = dist_ord(rng);\n                if (in_selected[cand]) {\n                    rem_idx = cand;\n                    break;\n                }\n                attempts++;\n            }\n            if (rem_idx == -1) continue;\n            \n            attempts = 0;\n            while(attempts < 20) {\n                int cand = dist_ord(rng);\n                if (!in_selected[cand]) {\n                    add_idx = cand;\n                    break;\n                }\n                attempts++;\n            }\n            if (add_idx == -1) continue;\n            \n            // Remove rem_idx from path\n            vector<pair<int, int>> temp_path;\n            temp_path.reserve(98);\n            for (const auto& node : path) {\n                if (node.first != rem_idx) {\n                    temp_path.push_back(node);\n                }\n            }\n            \n            int best_insert_i = 0, best_insert_j = 1;\n            int min_new_cost = 1e9;\n            \n            int tries = 50;\n            for(int t=0; t<tries; ++t) {\n                int pi = dist_path(rng) % 99; // 0..98\n                int pj = dist_path(rng) % 100; // 0..99\n                if (pi >= pj) {\n                    if (pi == pj) { pj = (pj + 1) % 100; }\n                    if (pi >= pj) continue; \n                    // Ensure pj > pi\n                    if (pj <= pi) pj = pi + 1;\n                }\n                \n                // Insert P at pi\n                vector<pair<int, int>> cand_path;\n                cand_path.reserve(99);\n                for(int k=0; k<98; ++k) {\n                    if (k == pi) cand_path.push_back({add_idx, 0});\n                    cand_path.push_back(temp_path[k]);\n                }\n                if (pi == 98) cand_path.push_back({add_idx, 0});\n                \n                // Insert D at pj (in 99-size path)\n                // pj must be > pi.\n                // Since cand_path has 99 elements, indices 0..98.\n                // We want D at index target_d.\n                // target_d in range pi+1 .. 99.\n                int target_d = pi + 1 + (dist_path(rng) % (100 - (pi + 1)));\n                \n                vector<pair<int, int>> final_cand;\n                final_cand.reserve(100);\n                for(int k=0; k<99; ++k) {\n                    if (k == target_d) final_cand.push_back({add_idx, 1});\n                    final_cand.push_back(cand_path[k]);\n                }\n                if (target_d == 99) final_cand.push_back({add_idx, 1});\n                \n                int c = calc_total_cost(final_cand);\n                if (t == 0 || c < min_new_cost) {\n                    min_new_cost = c;\n                    best_insert_i = pi;\n                    best_insert_j = target_d;\n                }\n            }\n            \n            if (min_new_cost < current_cost || dist_01(rng) < exp(-(min_new_cost - current_cost) / temp)) {\n                // Apply\n                vector<pair<int, int>> new_path;\n                new_path.reserve(100);\n                for(int k=0; k<98; ++k) {\n                    if (k == best_insert_i) new_path.push_back({add_idx, 0});\n                    new_path.push_back(temp_path[k]);\n                }\n                if (best_insert_i == 98) new_path.push_back({add_idx, 0});\n                \n                vector<pair<int, int>> final_path;\n                final_path.reserve(100);\n                for(int k=0; k<99; ++k) {\n                    if (k == best_insert_j) final_path.push_back({add_idx, 1});\n                    final_path.push_back(new_path[k]);\n                }\n                if (best_insert_j == 99) final_path.push_back({add_idx, 1});\n                \n                path = final_path;\n                current_cost = min_new_cost;\n                in_selected[rem_idx] = false;\n                in_selected[add_idx] = true;\n                \n                for(int k=0; k<1000; ++k) { pos[k][0] = -1; pos[k][1] = -1; }\n                for(int k=0; k<100; ++k) {\n                    pos[path[k].first][path[k].second] = k;\n                }\n            }\n        }\n        \n        if (current_cost < best_cost) {\n            best_cost = current_cost;\n            best_path = path;\n            copy(in_selected, in_selected + 1000, best_in_selected);\n        }\n        \n        iter++;\n    }\n\n    // Output\n    vector<int> final_orders;\n    final_orders.reserve(50);\n    for(int i=0; i<1000; ++i) {\n        if (best_in_selected[i]) final_orders.push_back(i + 1);\n    }\n    \n    cout << 50;\n    for(int x : final_orders) cout << \" \" << x;\n    cout << \"\\n\";\n    \n    cout << 102;\n    cout << \" \" << center.x << \" \" << center.y;\n    for(const auto& node : best_path) {\n        Point p = all_points[node.first * 2 + node.second];\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \" \" << center.x << \" \" << center.y;\n    cout << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Disjoint Set Union with path compression and union by rank\nstruct DSU {\n    vector<int> parent, rank_;\n    int components;\n    \n    DSU(int n) : parent(n), rank_(n, 0), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    \n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        components--;\n        return true;\n    }\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    // Read vertex coordinates\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    // Read edge endpoints and precompute expected distances\n    vector<pair<int, int>> edges(M);\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n        int u = edges[i].first, v = edges[i].second;\n        double dist = hypot(coords[u].first - coords[v].first, \n                           coords[u].second - coords[v].second);\n        d[i] = (int)round(dist);\n    }\n    \n    DSU dsu(N);\n    \n    // Process each edge online\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first, v = edges[i].second;\n        int remaining = M - 1 - i;  // Edges after this one\n        int needed = dsu.components - 1;  // Minimum edges needed for connectivity\n        \n        bool connects = (dsu.find(u) != dsu.find(v));\n        bool accept = false;\n        \n        if (connects) {\n            // Edge quality ratio (actual length / expected minimum length)\n            double ratio = (double)l / max(1, d[i]);\n            \n            // Connectivity urgency: how critical is it to accept connecting edges?\n            double urgency = (double)needed / max(1, remaining + 1);\n            \n            // Progress through the edge stream\n            double progress = (double)i / M;\n            \n            // Base threshold (expected value is 2.0, max is 3.0)\n            double threshold = 2.5;\n            \n            // Adjust threshold based on urgency\n            if (urgency > 0.7) {\n                threshold = 3.0;  // Very urgent - accept almost any connecting edge\n            } else if (urgency > 0.5) {\n                threshold = 2.8;\n            } else if (urgency > 0.3) {\n                threshold = 2.6;\n            } else if (urgency > 0.15) {\n                threshold = 2.4;\n            }\n            \n            // Early phase: be more selective if not urgent\n            if (progress < 0.2 && urgency < 0.2) {\n                threshold = min(threshold, 2.0);\n            } else if (progress < 0.4 && urgency < 0.2) {\n                threshold = min(threshold, 2.2);\n            }\n            \n            // Late phase safety: increase threshold when running low on edges\n            if (remaining <= needed + 20) {\n                threshold = max(threshold, 2.7);\n            }\n            if (remaining <= needed + 10) {\n                threshold = max(threshold, 2.9);\n            }\n            \n            // Critical: must accept if we might not have enough edges left\n            if (remaining <= needed) {\n                accept = true;\n            } else if (ratio <= threshold) {\n                accept = true;\n            }\n        }\n        \n        if (accept && connects) {\n            dsu.unite(u, v);\n            cout << 1 << \"\\n\";\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        cout.flush();  // Ensure output is sent immediately\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nclass Solver {\nprivate:\n    int N, M;\n    vector<Position> petPos;\n    vector<int> petType;\n    vector<Position> humanPos;\n    vector<vector<bool>> impassable;\n    vector<vector<bool>> humanTarget;\n    \n    bool isValid(int x, int y) const {\n        return x >= 1 && x <= GRID_SIZE && y >= 1 && y <= GRID_SIZE;\n    }\n    \n    bool isPassable(int x, int y) const {\n        if (!isValid(x, y)) return false;\n        return !impassable[x-1][y-1];\n    }\n    \n    bool hasPetAdjacent(int x, int y) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (const auto& pet : petPos) {\n                    if (pet.x == nx && pet.y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    bool hasHumanAdjacent(int x, int y, int excludeIdx = -1) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (int i = 0; i < M; i++) {\n                    if (i == excludeIdx) continue;\n                    if (humanPos[i].x == nx && humanPos[i].y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    vector<vector<bool>> computeReachable(const Position& start) const {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        queue<Position> q;\n        \n        if (isPassable(start.x, start.y)) {\n            visited[start.x-1][start.y-1] = true;\n            q.push(start);\n        }\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        \n        while (!q.empty()) {\n            Position cur = q.front();\n            q.pop();\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = cur.x + dx[d], ny = cur.y + dy[d];\n                if (isPassable(nx, ny) && !visited[nx-1][ny-1]) {\n                    visited[nx-1][ny-1] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        \n        return visited;\n    }\n    \n    int countPetsInRegion(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (const auto& pet : petPos) {\n            if (region[pet.x-1][pet.y-1]) {\n                count++;\n            }\n        }\n        return count;\n    }\n    \n    int countReachable(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (region[i][j]) count++;\n            }\n        }\n        return count;\n    }\n    \n    // Calculate minimum distance from position to any pet\n    int minPetDistance(int x, int y) const {\n        int minDist = 1000;\n        for (const auto& pet : petPos) {\n            int dist = abs(pet.x - x) + abs(pet.y - y);\n            minDist = min(minDist, dist);\n        }\n        return minDist;\n    }\n    \n    // Check if blocking this square would help create a partition\n    double evaluateBlockScore(int x, int y, int humanIdx) const {\n        double score = 0;\n        \n        // Base score for blocking\n        score += 100;\n        \n        // Bonus for being far from pets (safer)\n        int petDist = minPetDistance(x, y);\n        score += petDist * 5;\n        \n        // Bonus for continuing existing walls\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int wallCount = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny) && impassable[nx-1][ny-1]) {\n                wallCount++;\n            }\n        }\n        score += wallCount * 20;\n        \n        // Prefer edges and corners for better partitioning\n        if (x == 1 || x == GRID_SIZE || y == 1 || y == GRID_SIZE) {\n            score += 15;\n        }\n        if ((x == 1 || x == GRID_SIZE) && (y == 1 || y == GRID_SIZE)) {\n            score += 10;\n        }\n        \n        // Penalize if too close to this human (want to expand)\n        int humanDist = abs(x - humanPos[humanIdx].x) + abs(y - humanPos[humanIdx].y);\n        if (humanDist < 3) {\n            score -= (3 - humanDist) * 10;\n        }\n        \n        return score;\n    }\n    \n    // Evaluate move score\n    double evaluateMoveScore(int newX, int newY, int humanIdx) const {\n        double score = 0;\n        \n        // Count potential blocking opportunities from new position\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int blockOptions = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = newX + dx[d], ny = newY + dy[d];\n            if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !hasPetAdjacent(nx, ny)) {\n                blockOptions++;\n            }\n        }\n        score += blockOptions * 30;\n        \n        // Distance from pets\n        int petDist = minPetDistance(newX, newY);\n        score += petDist * 3;\n        \n        // Spread humans out\n        for (int i = 0; i < M; i++) {\n            if (i == humanIdx) continue;\n            int dist = abs(newX - humanPos[i].x) + abs(newY - humanPos[i].y);\n            if (dist < 5) {\n                score -= (5 - dist) * 5;\n            }\n        }\n        \n        return score;\n    }\n    \npublic:\n    void readInput() {\n        cin >> N;\n        petPos.resize(N);\n        petType.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petPos[i].x >> petPos[i].y >> petType[i];\n        }\n        \n        cin >> M;\n        humanPos.resize(M);\n        for (int i = 0; i < M; i++) {\n            cin >> humanPos[i].x >> humanPos[i].y;\n        }\n        \n        impassable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        humanTarget.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    }\n    \n    void readPetMoves() {\n        for (int i = 0; i < N; i++) {\n            string move;\n            cin >> move;\n            if (move != \".\") {\n                int x = petPos[i].x, y = petPos[i].y;\n                for (char c : move) {\n                    int nx = x, ny = y;\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    \n                    if (isValid(nx, ny) && isPassable(nx, ny)) {\n                        x = nx;\n                        y = ny;\n                    }\n                }\n                petPos[i] = {x, y};\n            }\n        }\n    }\n    \n    string decideActions(int turn) {\n        string actions(M, '.');\n        \n        // Track which squares will be blocked this turn (to avoid conflicts)\n        vector<vector<bool>> willBlock(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        char blockChars[] = {'u', 'd', 'l', 'r'};\n        char moveChars[] = {'U', 'D', 'L', 'R'};\n        \n        // First pass: identify best blocking opportunities\n        vector<pair<double, int>> humanScores(M);\n        for (int i = 0; i < M; i++) {\n            int x = humanPos[i].x, y = humanPos[i].y;\n            double bestScore = -1e18;\n            int bestD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1]) {\n                    if (!hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                        double score = evaluateBlockScore(nx, ny, i);\n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestD = d;\n                        }\n                    }\n                }\n            }\n            \n            humanScores[i] = {bestScore, bestD};\n        }\n        \n        // Second pass: execute actions (prioritize high-score humans)\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return humanScores[a].first > humanScores[b].first;\n        });\n        \n        for (int idx : order) {\n            int i = idx;\n            int x = humanPos[i].x, y = humanPos[i].y;\n            int bestD = humanScores[i].second;\n            \n            if (bestD >= 0) {\n                int nx = x + dx[bestD], ny = y + dy[bestD];\n                // Double check it's still available\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1] &&\n                    !hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                    actions[i] = blockChars[bestD];\n                    impassable[nx-1][ny-1] = true;\n                    willBlock[nx-1][ny-1] = true;\n                    continue;\n                }\n            }\n            \n            // Try to move to better position\n            double bestMoveScore = -1e18;\n            int bestMoveD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && isPassable(nx, ny)) {\n                    // Check if this square won't be blocked by others\n                    bool willBeBlocked = false;\n                    for (int j = 0; j < M; j++) {\n                        if (j == i) continue;\n                        int jd = humanScores[j].second;\n                        if (jd >= 0) {\n                            int tx = humanPos[j].x + dx[jd], ty = humanPos[j].y + dy[jd];\n                            if (tx == nx && ty == ny) {\n                                willBeBlocked = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (!willBeBlocked) {\n                        double score = evaluateMoveScore(nx, ny, i);\n                        if (score > bestMoveScore) {\n                            bestMoveScore = score;\n                            bestMoveD = d;\n                        }\n                    }\n                }\n            }\n            \n            if (bestMoveD >= 0 && bestMoveScore > 0) {\n                actions[i] = moveChars[bestMoveD];\n                humanPos[i].x += dx[bestMoveD];\n                humanPos[i].y += dy[bestMoveD];\n            }\n        }\n        \n        return actions;\n    }\n    \n    void solve() {\n        readInput();\n        \n        for (int turn = 0; turn < MAX_TURNS; turn++) {\n            string actions = decideActions(turn);\n            cout << actions << endl;\n            \n            if (turn < MAX_TURNS - 1) {\n                readPetMoves();\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}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 20;\nconst int MAX_STEPS = 200;\n\nstruct Problem {\n    int si, sj, ti, tj;\n    double p;\n    vector<string> h; // horizontal walls: h[i][j] = wall between (i,j) and (i,j+1)\n    vector<string> v; // vertical walls: v[i][j] = wall between (i,j) and (i+1,j)\n};\n\n// Direction vectors: U, D, L, R\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dirChar[4] = {'U', 'D', 'L', 'R'};\n\nbool canMove(const Problem& prob, int i, int j, int dir) {\n    int ni = i + di[dir];\n    int nj = j + dj[dir];\n    \n    // Check bounds\n    if (ni < 0 || ni >= GRID_SIZE || nj < 0 || nj >= GRID_SIZE) return false;\n    \n    // Check walls\n    if (dir == 0) { // U\n        if (prob.v[ni][j] == '1') return false;\n    } else if (dir == 1) { // D\n        if (prob.v[i][j] == '1') return false;\n    } else if (dir == 2) { // L\n        if (prob.h[i][nj] == '1') return false;\n    } else { // R\n        if (prob.h[i][j] == '1') return false;\n    }\n    return true;\n}\n\npair<int, int> movePos(int i, int j, int dir) {\n    return {i + di[dir], j + dj[dir]};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Problem prob;\n    cin >> prob.si >> prob.sj >> prob.ti >> prob.tj >> prob.p;\n    \n    prob.h.resize(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; i++) {\n        cin >> prob.h[i];\n    }\n    \n    prob.v.resize(GRID_SIZE - 1);\n    for (int i = 0; i < GRID_SIZE - 1; i++) {\n        cin >> prob.v[i];\n    }\n    \n    // DP: V[i][j][k] = expected score from position (i,j) with k steps remaining\n    // We use 2 layers to save memory\n    vector<vector<double>> V_cur(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    vector<vector<double>> V_next(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    \n    // Initialize: at target, remaining steps don't matter (already arrived)\n    // But we need to handle the scoring: 401 - t where t is arrival time\n    // If we're at target with k steps remaining in a L-step path, arrival was at step L-k\n    // Score = 401 - (L - k) = 401 - L + k\n    \n    // We'll build the path greedily, computing values backwards\n    // For path length L, V[i][j][k] = expected score with k steps remaining\n    \n    // Strategy: Try different path lengths and pick the best\n    string bestPath = \"\";\n    double bestScore = 0.0;\n    \n    for (int pathLen = 50; pathLen <= MAX_STEPS; pathLen += 5) {\n        // Initialize value function for 0 remaining steps\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                V_cur[i][j] = 0.0; // Can't reach target with 0 steps if not already there\n            }\n        }\n        V_cur[prob.ti][prob.tj] = 401.0 - pathLen; // Arrived exactly at last step\n        \n        // Backward DP\n        for (int k = 1; k <= pathLen; k++) {\n            for (int i = 0; i < GRID_SIZE; i++) {\n                for (int j = 0; j < GRID_SIZE; j++) {\n                    if (i == prob.ti && j == prob.tj) {\n                        // Already at target, score based on when we arrived\n                        V_next[i][j] = 401.0 - (pathLen - k);\n                        continue;\n                    }\n                    \n                    double bestVal = 0.0;\n                    for (int dir = 0; dir < 4; dir++) {\n                        double val = 0.0;\n                        int ni = i + di[dir];\n                        int nj = j + dj[dir];\n                        \n                        // With probability p: stay (forget)\n                        val += prob.p * V_cur[i][j];\n                        \n                        // With probability 1-p: try to move\n                        if (canMove(prob, i, j, dir)) {\n                            val += (1.0 - prob.p) * V_cur[ni][nj];\n                        } else {\n                            val += (1.0 - prob.p) * V_cur[i][j];\n                        }\n                        \n                        bestVal = max(bestVal, val);\n                    }\n                    V_next[i][j] = bestVal;\n                }\n            }\n            swap(V_cur, V_next);\n        }\n        \n        double startScore = V_cur[prob.si][prob.sj];\n        \n        // If this is better, construct the path\n        if (startScore > bestScore) {\n            bestScore = startScore;\n            \n            // Reconstruct path greedily\n            // Need to recompute DP to get the policy\n            vector<vector<vector<double>>> V_all(pathLen + 1, \n                vector<vector<double>>(GRID_SIZE, vector<double>(GRID_SIZE, 0.0)));\n            \n            // Initialize\n            for (int i = 0; i < GRID_SIZE; i++) {\n                for (int j = 0; j < GRID_SIZE; j++) {\n                    V_all[0][i][j] = 0.0;\n                }\n            }\n            V_all[0][prob.ti][prob.tj] = 401.0 - pathLen;\n            \n            // Forward DP (backwards in time)\n            for (int k = 1; k <= pathLen; k++) {\n                for (int i = 0; i < GRID_SIZE; i++) {\n                    for (int j = 0; j < GRID_SIZE; j++) {\n                        if (i == prob.ti && j == prob.tj) {\n                            V_all[k][i][j] = 401.0 - (pathLen - k);\n                            continue;\n                        }\n                        \n                        double bestVal = 0.0;\n                        for (int dir = 0; dir < 4; dir++) {\n                            double val = 0.0;\n                            int ni = i + di[dir];\n                            int nj = j + dj[dir];\n                            \n                            val += prob.p * V_all[k-1][i][j];\n                            \n                            if (canMove(prob, i, j, dir)) {\n                                val += (1.0 - prob.p) * V_all[k-1][ni][nj];\n                            } else {\n                                val += (1.0 - prob.p) * V_all[k-1][i][j];\n                            }\n                            \n                            bestVal = max(bestVal, val);\n                        }\n                        V_all[k][i][j] = bestVal;\n                    }\n                }\n            }\n            \n            // Greedy path construction\n            string path = \"\";\n            int ci = prob.si, cj = prob.sj;\n            int remaining = pathLen;\n            \n            while (remaining > 0 && (ci != prob.ti || cj != prob.tj)) {\n                int bestDir = 1; // Default D (towards target)\n                double bestVal = -1e18;\n                \n                for (int dir = 0; dir < 4; dir++) {\n                    double val = 0.0;\n                    int ni = ci + di[dir];\n                    int nj = cj + dj[dir];\n                    \n                    val += prob.p * V_all[remaining - 1][ci][cj];\n                    \n                    if (canMove(prob, ci, cj, dir)) {\n                        val += (1.0 - prob.p) * V_all[remaining - 1][ni][nj];\n                    } else {\n                        val += (1.0 - prob.p) * V_all[remaining - 1][ci][cj];\n                    }\n                    \n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestDir = dir;\n                    }\n                }\n                \n                path += dirChar[bestDir];\n                \n                // Update position (accounting for possible forget/wall)\n                // For path construction, we assume successful move for simplicity\n                // The actual execution is stochastic\n                int ni = ci + di[bestDir];\n                int nj = cj + dj[bestDir];\n                if (canMove(prob, ci, cj, bestDir)) {\n                    ci = ni;\n                    cj = nj;\n                }\n                \n                remaining--;\n            }\n            \n            // Fill remaining steps if needed (stay at target)\n            while (path.length() < pathLen) {\n                path += 'R'; // Arbitrary, won't matter if at target\n            }\n            \n            bestPath = path;\n        }\n    }\n    \n    // Also try a direct BFS path as baseline\n    vector<pair<int, int>> bfsPath;\n    {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n        vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n        vector<pair<int, int>> queue;\n        queue.push_back({prob.si, prob.sj});\n        visited[prob.si][prob.sj] = true;\n        \n        int head = 0;\n        while (head < (int)queue.size()) {\n            auto [ci, cj] = queue[head++];\n            if (ci == prob.ti && cj == prob.tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (canMove(prob, ci, cj, dir)) {\n                    int ni = ci + di[dir];\n                    int nj = cj + dj[dir];\n                    if (!visited[ni][nj]) {\n                        visited[ni][nj] = true;\n                        parent[ni][nj] = {ci, cj};\n                        parentDir[ni][nj] = dir;\n                        queue.push_back({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (visited[prob.ti][prob.tj]) {\n            string bfsStr = \"\";\n            int ci = prob.ti, cj = prob.tj;\n            while (ci != prob.si || cj != prob.sj) {\n                int dir = parentDir[ci][cj];\n                bfsStr += dirChar[dir];\n                auto [pi, pj] = parent[ci][cj];\n                ci = pi;\n                cj = pj;\n            }\n            reverse(bfsStr.begin(), bfsStr.end());\n            \n            // Pad to reasonable length for comparison\n            while (bfsStr.length() < 50) bfsStr += 'R';\n            if (bfsStr.length() < bestPath.length() || bestPath.empty()) {\n                // Evaluate BFS path\n                // Simple heuristic: shorter path with some padding\n                if ((int)bfsStr.length() <= MAX_STEPS) {\n                    bestPath = bfsStr;\n                }\n            }\n        }\n    }\n    \n    // Ensure path is within limits\n    if ((int)bestPath.length() > MAX_STEPS) {\n        bestPath = bestPath.substr(0, MAX_STEPS);\n    }\n    \n    cout << bestPath << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entering_direction] = exiting_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0: curve\n    {3, -1, -1, 0},  // 1: curve\n    {-1, -1, 3, 2},  // 2: curve\n    {-1, 2, 1, -1},  // 3: curve\n    {1, 0, 3, 2},    // 4: double curve\n    {3, 2, 1, 0},    // 5: double curve\n    {2, -1, 0, -1},  // 6: straight\n    {-1, 3, -1, 1},  // 7: straight\n};\n\n// Direction deltas: 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\nint grid[N][N];  // Original tile types\nint rot[N][N];   // Rotation amount (0-3)\n\n// Apply rotation to tile type\ninline int rotate_tile(int t, int r) {\n    if (t <= 3) return (t + r) % 4;\n    else if (t <= 5) return 4 + ((t - 4 + r) % 2);\n    else return 6 + ((t - 6 + r) % 2);\n}\n\n// Get current tile type after rotation\ninline int get_tile(int i, int j) {\n    return rotate_tile(grid[i][j], rot[i][j]);\n}\n\n// Trace a loop from starting position and direction\n// Returns loop length if valid loop, 0 otherwise\nint trace_loop(int si, int sj, int sd, int max_len = 2000) {\n    int i = si, j = sj, d = sd;\n    for (int len = 1; len <= max_len; len++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 == -1) return 0;\n        \n        i += di[d2];\n        j += dj[d2];\n        d = (d2 + 2) % 4;\n        \n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        if (i == si && j == sj && d == sd) return len;\n    }\n    return 0;\n}\n\n// Find all loops and return top 2 unique lengths\npair<long long, long long> get_top2_loops() {\n    vector<int> loops;\n    static bool vis[N][N][4];\n    memset(vis, 0, sizeof(vis));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                if (vis[i][j][d]) continue;\n                \n                // Trace path and detect loops\n                vector<tuple<int,int,int>> path;\n                int ci = i, cj = j, cd = d;\n                \n                while (ci >= 0 && ci < N && cj >= 0 && cj < N && !vis[ci][cj][cd]) {\n                    vis[ci][cj][cd] = true;\n                    path.push_back({ci, cj, cd});\n                    \n                    int t = get_tile(ci, cj);\n                    int d2 = to[t][cd];\n                    if (d2 == -1) break;\n                    \n                    ci += di[d2];\n                    cj += dj[d2];\n                    cd = (d2 + 2) % 4;\n                }\n                \n                // Check if we found a loop\n                if (ci >= 0 && ci < N && cj >= 0 && cj < N) {\n                    for (int k = 0; k < (int)path.size(); k++) {\n                        if (get<0>(path[k]) == ci && \n                            get<1>(path[k]) == cj && \n                            get<2>(path[k]) == cd) {\n                            int loop_len = path.size() - k;\n                            if (loop_len > 1) {\n                                loops.push_back(loop_len);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    // Get unique top 2\n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Initialize rotations to 0\n    memset(rot, 0, sizeof(rot));\n    \n    // Random number generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Get initial score\n    auto [l1, l2] = get_top2_loops();\n    long long best_score = l1 * l2;\n    \n    // Simulated annealing parameters\n    double temp = 1000.0;\n    double cooling = 0.99995;\n    int iterations = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Main optimization loop\n    while (true) {\n        // Check time limit (leave 100ms for output)\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed >= 1900) break;\n        \n        // Pick random tile and new rotation\n        int i = rng() % N;\n        int j = rng() % N;\n        int old_rot = rot[i][j];\n        int new_rot = (old_rot + 1 + rng() % 3) % 4;\n        \n        // Apply change\n        rot[i][j] = new_rot;\n        \n        // Evaluate new score\n        auto [nl1, nl2] = get_top2_loops();\n        long long new_score = nl1 * nl2;\n        \n        // Accept or reject based on simulated annealing\n        bool accept = false;\n        if (new_score >= best_score) {\n            accept = true;\n            best_score = new_score;\n        } else if (temp > 0.01) {\n            double prob = exp((double)(new_score - best_score) / temp);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (!accept) {\n            rot[i][j] = old_rot;  // Revert change\n        }\n        \n        // Cool down\n        temp *= cooling;\n        iterations++;\n    }\n    \n    // Output rotation string\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << rot[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Direction masks: 1=left, 2=up, 4=right, 8=down\nconst int LEFT = 1, UP = 2, RIGHT = 4, DOWN = 8;\nconst int dr[4] = {-1, 1, 0, 0};  // U, D, L, R\nconst int dc[4] = {0, 0, -1, 1};\nconst char dirs[4] = {'U', 'D', 'L', 'R'};\n\nint N;\nlong long T;\nvector<vector<int>> board;\nint empty_r, empty_c;\nstring operations;\n\n// Check if two adjacent cells have matching connections\nbool connects(int r1, int c1, int r2, int c2) {\n    if (board[r1][c1] == 0 || board[r2][c2] == 0) return false;\n    \n    if (r2 == r1 + 1) {  // r2 is below r1\n        return (board[r1][c1] & DOWN) && (board[r2][c2] & UP);\n    } else if (r2 == r1 - 1) {  // r2 is above r1\n        return (board[r1][c1] & UP) && (board[r2][c2] & DOWN);\n    } else if (c2 == c1 + 1) {  // c2 is right of c1\n        return (board[r1][c1] & RIGHT) && (board[r2][c2] & LEFT);\n    } else if (c2 == c1 - 1) {  // c2 is left of c1\n        return (board[r1][c1] & LEFT) && (board[r2][c2] & RIGHT);\n    }\n    return false;\n}\n\n// Compute size of largest tree (connected component)\nint computeMaxTree() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int maxTree = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] != 0 && !visited[i][j]) {\n                int treeSize = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                \n                while (!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    treeSize++;\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                            board[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                \n                maxTree = max(maxTree, treeSize);\n            }\n        }\n    }\n    \n    return maxTree;\n}\n\n// Find shortest path for empty square to reach target position\nstring findPath(int target_r, int target_c) {\n    if (empty_r == target_r && empty_c == target_c) return \"\";\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n    vector<vector<int>> dir_used(N, vector<int>(N, -1));\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\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 == target_r && c == target_c) {\n            string path = \"\";\n            int cr = r, cc = c;\n            while (parent[cr][cc].first != -1) {\n                int d = dir_used[cr][cc];\n                path += dirs[d];\n                int pr = parent[cr][cc].first;\n                int pc = parent[cr][cc].second;\n                cr = pr;\n                cc = pc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\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 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                dir_used[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return \"\";\n}\n\n// Execute a single move\nvoid executeMove(char move) {\n    int d;\n    if (move == 'U') d = 0;\n    else if (move == 'D') d = 1;\n    else if (move == 'L') d = 2;\n    else d = 3;  // 'R'\n    \n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    board[empty_r][empty_c] = board[nr][nc];\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    operations += move;\n}\n\n// Move empty square to target and execute slide\nvoid moveAndSlide(int target_r, int target_c, int slide_dir) {\n    string path = findPath(target_r, target_c);\n    for (char c : path) {\n        executeMove(c);\n    }\n    executeMove(dirs[slide_dir]);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> T;\n    \n    board.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') {\n                board[i][j] = c - '0';\n            } else {\n                board[i][j] = c - 'a' + 10;\n            }\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    int currentScore = computeMaxTree();\n    int maxScore = currentScore;\n    int noImprovementCount = 0;\n    \n    // Greedy hill-climbing with timeout protection\n    // Reserve 200ms buffer for system test variations\n    while (operations.size() < (size_t)T) {\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2800) break;  // Time limit protection\n        \n        int bestScore = currentScore;\n        int bestTargetR = -1, bestTargetC = -1, bestSlideDir = -1;\n        \n        // Try all possible moves\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (board[r][c] == 0) continue;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    \n                    // Check if this would move tile at (r,c) into empty at (nr,nc)\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (board[nr][nc] != 0) continue;\n                    \n                    // Temporarily make the move\n                    int temp = board[r][c];\n                    board[r][c] = 0;\n                    board[nr][nc] = temp;\n                    int old_er = empty_r, old_ec = empty_c;\n                    empty_r = nr;\n                    empty_c = nc;\n                    \n                    int newScore = computeMaxTree();\n                    \n                    // Restore state\n                    board[nr][nc] = 0;\n                    board[r][c] = temp;\n                    empty_r = old_er;\n                    empty_c = old_ec;\n                    \n                    // Prioritize moves that improve score, then by operation count\n                    if (newScore > bestScore || \n                        (newScore == bestScore && bestScore == N * N - 1)) {\n                        bestScore = newScore;\n                        bestTargetR = r;\n                        bestTargetC = c;\n                        bestSlideDir = d;\n                    }\n                }\n            }\n        }\n        \n        // If we found complete tree, try to minimize operations\n        if (bestScore == N * N - 1 && currentScore == N * N - 1) {\n            break;  // Already optimal\n        }\n        \n        if (bestTargetR == -1) {\n            // No improving move found, try random move to escape local optimum\n            noImprovementCount++;\n            if (noImprovementCount > 100) break;\n            \n            // Make a random valid move\n            vector<tuple<int, int, int>> validMoves;\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    if (board[r][c] == 0) continue;\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 < N && nc >= 0 && nc < N && board[nr][nc] == 0) {\n                            validMoves.push_back({r, c, d});\n                        }\n                    }\n                }\n            }\n            \n            if (!validMoves.empty()) {\n                auto [tr, tc, td] = validMoves[rand() % validMoves.size()];\n                moveAndSlide(tr, tc, td);\n                int newScore = computeMaxTree();\n                if (newScore >= currentScore) {\n                    currentScore = newScore;\n                    maxScore = max(maxScore, currentScore);\n                    noImprovementCount = 0;\n                }\n            } else {\n                break;\n            }\n        } else {\n            // Execute best move\n            moveAndSlide(bestTargetR, bestTargetC, bestSlideDir);\n            currentScore = bestScore;\n            maxScore = max(maxScore, currentScore);\n            noImprovementCount = 0;\n        }\n    }\n    \n    cout << operations << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Strawberry {\n    long long x, y;\n    int id;\n    bool active;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n    \n    // Returns which side of the line a point is on\n    // Positive = one side, Negative = other side, 0 = on line\n    long long side(long long x, long long y) const {\n        return (qx - px) * (y - py) - (qy - py) * (x - px);\n    }\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> cuts;\nmt19937 rng(12345);\n\n// Check if line is too close to any active strawberry\nbool lineIsSafe(const Line& line, long long margin = 1) {\n    for (const auto& s : strawberries) {\n        if (!s.active) continue;\n        long long side = line.side(s.x, s.y);\n        if (abs(side) <= margin * 1000LL) {  // Rough distance check\n            return false;\n        }\n    }\n    return true;\n}\n\n// Count strawberries on each side of a line within a region\npair<int, int> countStrawberries(const Line& line, const vector<int>& regionStraws) {\n    int left = 0, right = 0;\n    for (int idx : regionStraws) {\n        if (!strawberries[idx].active) continue;\n        long long side = line.side(strawberries[idx].x, strawberries[idx].y);\n        if (side > 0) left++;\n        else if (side < 0) right++;\n        // If side == 0, strawberry is cut (becomes inactive)\n    }\n    return {left, right};\n}\n\n// Try to find a line that separates a region into desired sizes\nbool findGoodCut(const vector<int>& regionStraws, int targetLeft, int targetRight, Line& bestLine) {\n    if (regionStraws.size() < 2) return false;\n    \n    int bestScore = -1;\n    \n    // Try random lines through pairs of points\n    for (int trial = 0; trial < 500; trial++) {\n        // Pick two random strawberries to define line direction\n        int i1 = regionStraws[rng() % regionStraws.size()];\n        int i2 = regionStraws[rng() % regionStraws.size()];\n        \n        if (i1 == i2) continue;\n        \n        // Create line perpendicular to the vector between them\n        long long dx = strawberries[i2].x - strawberries[i1].x;\n        long long dy = strawberries[i2].y - strawberries[i1].y;\n        \n        // Perpendicular direction\n        long long px = strawberries[i1].x;\n        long long py = strawberries[i1].y;\n        long long qx = px - dy;\n        long long qy = py + dx;\n        \n        // Offset the line to different positions\n        for (int offset = -50; offset <= 50; offset += 5) {\n            Line testLine = {px + offset * dx / 10, py + offset * dy / 10, \n                           qx + offset * dx / 10, qy + offset * dy / 10};\n            \n            if (!lineIsSafe(testLine, 10)) continue;\n            \n            auto [left, right] = countStrawberries(testLine, regionStraws);\n            \n            // Score based on how close we are to target\n            int score = 0;\n            if (left == targetLeft && right == targetRight) score = 1000;\n            else if (left == targetLeft || right == targetRight) score = 500;\n            else if (left > 0 && right > 0) score = 100;\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestLine = testLine;\n            }\n        }\n    }\n    \n    return bestScore > 0;\n}\n\n// Find a line that creates a piece with exactly d strawberries\nbool findCutForSize(const vector<int>& regionStraws, int d, Line& bestLine) {\n    if (regionStraws.size() <= d) return false;\n    \n    int bestScore = -1;\n    \n    for (int trial = 0; trial < 1000; trial++) {\n        // Random line through cake\n        long long angle = rng() % 360;\n        double rad = angle * 3.14159265359 / 180.0;\n        long long dx = (long long)(cos(rad) * 10000);\n        long long dy = (long long)(sin(rad) * 10000);\n        \n        // Random offset from center\n        long long offset = (rng() % 20001) - 10000;\n        \n        Line testLine = {offset, 0, offset + dx, dy};\n        \n        if (!lineIsSafe(testLine, 50)) continue;\n        \n        auto [left, right] = countStrawberries(testLine, regionStraws);\n        \n        int score = 0;\n        if (left == d || right == d) score = 1000;\n        else if (abs(left - d) <= 2 || abs(right - d) <= 2) score = 500;\n        else if (left > 0 && right > 0) score = 100;\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestLine = testLine;\n        }\n    }\n    \n    return bestScore > 0;\n}\n\n// Get all strawberries in a region defined by existing cuts\nvector<int> getRegion(const vector<int>& allStraws, const vector<int>& signature) {\n    vector<int> result;\n    for (int idx : allStraws) {\n        if (!strawberries[idx].active) continue;\n        bool match = true;\n        for (size_t i = 0; i < cuts.size() && i < signature.size(); i++) {\n            long long side = cuts[i].side(strawberries[idx].x, strawberries[idx].y);\n            int expected = signature[i];\n            if ((side > 0 && expected != 1) || (side < 0 && expected != -1) || (side == 0)) {\n                match = false;\n                break;\n            }\n        }\n        if (match) result.push_back(idx);\n    }\n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    vector<int> allStraws(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n        strawberries[i].id = i;\n        strawberries[i].active = true;\n        allStraws[i] = i;\n    }\n    \n    // Priority: create pieces matching demand\n    // Start with smaller d values (easier to achieve)\n    vector<pair<int, int>> targets;\n    for (int d = 1; d <= 10; d++) {\n        for (int j = 0; j < a[d]; j++) {\n            targets.push_back({d, j});\n        }\n    }\n    \n    // Sort by d (smaller first - easier to isolate)\n    sort(targets.begin(), targets.end());\n    \n    // Track regions as sets of strawberry indices\n    vector<vector<int>> regions = {allStraws};\n    \n    int cutsUsed = 0;\n    \n    // Greedy: try to satisfy demands one by one\n    for (auto [targetD, targetIdx] : targets) {\n        if (cutsUsed >= K) break;\n        \n        // Find a region with enough strawberries\n        int bestRegion = -1;\n        int bestRegionSize = targetD + 10;  // Want region not much larger than target\n        \n        for (size_t r = 0; r < regions.size(); r++) {\n            int count = 0;\n            for (int idx : regions[r]) {\n                if (strawberries[idx].active) count++;\n            }\n            if (count >= targetD && count < bestRegionSize) {\n                bestRegionSize = count;\n                bestRegion = r;\n            }\n        }\n        \n        if (bestRegion < 0) continue;\n        \n        // Try to find a cut that isolates exactly targetD strawberries\n        Line bestLine;\n        bool found = false;\n        \n        for (int attempt = 0; attempt < 5 && !found; attempt++) {\n            if (findCutForSize(regions[bestRegion], targetD, bestLine)) {\n                // Verify the cut works\n                auto [left, right] = countStrawberries(bestLine, regions[bestRegion]);\n                if (left == targetD || right == targetD) {\n                    found = true;\n                }\n            }\n        }\n        \n        if (!found) continue;\n        \n        // Apply the cut\n        cuts.push_back(bestLine);\n        cutsUsed++;\n        \n        // Update regions and strawberry status\n        vector<vector<int>> newRegions;\n        for (size_t r = 0; r < regions.size(); r++) {\n            if ((int)r != bestRegion) {\n                newRegions.push_back(regions[r]);\n                continue;\n            }\n            \n            vector<int> leftStraws, rightStraws;\n            for (int idx : regions[r]) {\n                if (!strawberries[idx].active) continue;\n                long long side = bestLine.side(strawberries[idx].x, strawberries[idx].y);\n                if (side > 0) leftStraws.push_back(idx);\n                else if (side < 0) rightStraws.push_back(idx);\n                else strawberries[idx].active = false;  // Cut through strawberry\n            }\n            \n            if (!leftStraws.empty()) newRegions.push_back(leftStraws);\n            if (!rightStraws.empty()) newRegions.push_back(rightStraws);\n        }\n        regions = newRegions;\n    }\n    \n    // Output the cuts\n    cout << cuts.size() << \"\\n\";\n    for (const auto& line : cuts) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Global variables\nint N, M;\nbool has_dot[65][65];\nbool used_edge[65][65][4]; // 0: X+, 1: Y+, 2: Diag /, 3: Diag \\\nvector<int> row_dots[65]; // row_dots[y] contains list of x\nvector<int> col_dots[65]; // col_dots[x] contains list of y\n\nstruct Point {\n    int x, y;\n    long long w;\n};\n\nvector<Point> sorted_points;\nvector<array<int, 8>> result_moves;\n\nauto start_time = chrono::steady_clock::now();\nconst double TIME_LIMIT = 4.8;\n\n// Check if an edge is used\n// Edge types:\n// 0: (x, y) to (x+1, y) -> stored at (x, y)\n// 1: (x, y) to (x, y+1) -> stored at (x, y)\n// 2: (x, y) to (x+1, y+1) -> stored at (x, y)\n// 3: (x, y) to (x-1, y+1) -> stored at (x, y) (start point has larger x)\nbool is_edge_used(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        if (y < 0 || y >= N - 1) return false;\n        return used_edge[x1][y][1];\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        if (x < 0 || x >= N - 1) return false;\n        return used_edge[x][y1][0];\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) { // Diag /\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][2];\n            } else { // Diag \\ (x1 < x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][3];\n            }\n        } else { // x1 > x2\n            if (y1 < y2) { // Diag \\ (x1 > x2, y1 < y2) -> Start is (x1, y1)\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][3];\n            } else { // Diag / (x1 > x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][2];\n            }\n        }\n    }\n    return false;\n}\n\nvoid mark_edge(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        used_edge[x1][y][1] = true;\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        used_edge[x][y1][0] = true;\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) used_edge[x1][y1][2] = true;\n            else used_edge[x2][y2][3] = true;\n        } else {\n            if (y1 < y2) used_edge[x1][y1][3] = true;\n            else used_edge[x2][y2][2] = true;\n        }\n    }\n}\n\n// Check perimeter constraints\n// pts: 4 vertices in order\n// dots: 3 existing dots that are allowed to be on perimeter\nbool check_perimeter(const vector<pair<int,int>>& pts, const vector<pair<int,int>>& dots) {\n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        \n        if (is_edge_used(x1, y1, x2, y2)) return false;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0) ? 0 : (dx / steps);\n        int sy = (dy == 0) ? 0 : (dy / steps);\n        \n        for (int k = 1; k < steps; ++k) {\n            int cx = x1 + k * sx;\n            int cy = y1 + k * sy;\n            if (has_dot[cx][cy]) {\n                bool allowed = false;\n                for (const auto& d : dots) {\n                    if (d.first == cx && d.second == cy) {\n                        allowed = true;\n                        break;\n                    }\n                }\n                if (!allowed) return false;\n            }\n        }\n    }\n    return true;\n}\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    vector<pair<int,int>> rect_pts;\n    vector<pair<int,int>> dot_pts;\n};\n\n// Try to find a valid rectangle for empty point (x, y)\n// Returns true if found, and fills 'move'\nbool try_fill(int x, int y, Move& out_move) {\n    // 1. Axis Aligned\n    // We need (x, yp), (xp, y), (xp, yp) to be dots.\n    // To avoid iterator invalidation, we copy relevant parts or just use indices.\n    // Since we return immediately, we can just use references but NOT modify vectors.\n    \n    for (int yp : row_dots[y]) {\n        if (yp == y) continue;\n        for (int xp : col_dots[x]) {\n            if (xp == x) continue;\n            if (has_dot[xp][yp]) {\n                // Candidate found\n                // Vertices: (x, y), (xp, y), (xp, yp), (x, yp)\n                vector<pair<int,int>> rect = {{x, y}, {xp, y}, {xp, yp}, {x, yp}};\n                vector<pair<int,int>> dots = {{xp, y}, {xp, yp}, {x, yp}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xp, y, xp, yp, x, yp, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // 2. 45-degree\n    // Case A: Vertical Diagonal (x, y) and (x, yd)\n    for (int yd : col_dots[x]) {\n        if (yd == y) continue;\n        int dy = yd - y;\n        if (abs(dy) % 2 != 0) continue;\n        int w = abs(dy) / 2;\n        int ym = y + dy / 2;\n        int x2 = x - w;\n        int x3 = x + w;\n        \n        if (x2 >= 0 && x2 < N && x3 >= 0 && x3 < N) {\n            if (has_dot[x2][ym] && has_dot[x3][ym]) {\n                // Vertices: (x, y), (x3, ym), (x, yd), (x2, ym)\n                vector<pair<int,int>> rect = {{x, y}, {x3, ym}, {x, yd}, {x2, ym}};\n                vector<pair<int,int>> dots = {{x, yd}, {x2, ym}, {x3, ym}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, x3, ym, x, yd, x2, ym, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    // Case B: Horizontal Diagonal (x, y) and (xd, y)\n    for (int xd : row_dots[y]) {\n        if (xd == x) continue;\n        int dx = xd - x;\n        if (abs(dx) % 2 != 0) continue;\n        int w = abs(dx) / 2;\n        int xm = x + dx / 2;\n        int y2 = y - w;\n        int y3 = y + w;\n        \n        if (y2 >= 0 && y2 < N && y3 >= 0 && y3 < N) {\n            if (has_dot[xm][y2] && has_dot[xm][y3]) {\n                // Vertices: (x, y), (xm, y3), (xd, y), (xm, y2)\n                vector<pair<int,int>> rect = {{x, y}, {xm, y3}, {xd, y}, {xm, y2}};\n                vector<pair<int,int>> dots = {{xd, y}, {xm, y2}, {xm, y3}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xm, y3, xd, y, xm, y2, rect, dots};\n                    return true;\n                }\n            }\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 >> M)) return 0;\n    \n    long long c = (N - 1) / 2;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        has_dot[x][y] = true;\n        row_dots[y].push_back(x);\n        col_dots[x].push_back(y);\n    }\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            sorted_points.push_back({x, y, w});\n        }\n    }\n    \n    sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n        return a.w > b.w;\n    });\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        bool found = false;\n        Move best_move;\n        \n        for (const auto& p : sorted_points) {\n            if (has_dot[p.x][p.y]) continue;\n            if (row_dots[p.y].empty() && col_dots[p.x].empty()) continue;\n            \n            if (try_fill(p.x, p.y, best_move)) {\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) break;\n        \n        // Apply move\n        result_moves.push_back({best_move.x1, best_move.y1, best_move.x2, best_move.y2, \n                                best_move.x3, best_move.y3, best_move.x4, best_move.y4});\n        \n        has_dot[best_move.x1][best_move.y1] = true;\n        row_dots[best_move.y1].push_back(best_move.x1);\n        col_dots[best_move.x1].push_back(best_move.y1);\n        \n        for (size_t i = 0; i < 4; ++i) {\n            mark_edge(best_move.rect_pts[i].first, best_move.rect_pts[i].second, \n                      best_move.rect_pts[(i + 1) % 4].first, best_move.rect_pts[(i + 1) % 4].second);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& m : result_moves) {\n        cout << m[0] << \" \" << m[1] << \" \" << m[2] << \" \" << m[3] << \" \" \n             << m[4] << \" \" << m[5] << \" \" << m[6] << \" \" << m[7] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 10;\n\nstruct Candy {\n    int flavor;\n    int row, col;\n};\n\nclass GameState {\npublic:\n    array<array<int, N>, N> grid;  // 0 = empty, 1-3 = flavor\n    vector<Candy> candies;\n    \n    GameState() {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = 0;\n    }\n    \n    GameState(const GameState& other) = default;\n    \n    void placeCandy(int row, int col, int flavor) {\n        grid[row][col] = flavor;\n        candies.push_back({flavor, row, col});\n    }\n    \n    vector<pair<int,int>> getEmptyCells() const {\n        vector<pair<int,int>> empty;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    empty.push_back({i, j});\n                }\n            }\n        }\n        return empty;\n    }\n    \n    GameState tilt(char dir) const {\n        GameState result = *this;\n        auto& g = result.grid;\n        \n        if (dir == 'F') {  // Forward (up)\n            for (int j = 0; j < N; j++) {\n                int writeRow = 0;\n                for (int i = 0; i < N; i++) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow++;\n                    }\n                }\n            }\n        } else if (dir == 'B') {  // Backward (down)\n            for (int j = 0; j < N; j++) {\n                int writeRow = N - 1;\n                for (int i = N - 1; i >= 0; i--) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow--;\n                    }\n                }\n            }\n        } else if (dir == 'L') {  // Left\n            for (int i = 0; i < N; i++) {\n                int writeCol = 0;\n                for (int j = 0; j < N; j++) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol++;\n                    }\n                }\n            }\n        } else if (dir == 'R') {  // Right\n            for (int i = 0; i < N; i++) {\n                int writeCol = N - 1;\n                for (int j = N - 1; j >= 0; j--) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol--;\n                    }\n                }\n            }\n        }\n        \n        // Update candy positions\n        result.candies.clear();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (g[i][j] != 0) {\n                    result.candies.push_back({g[i][j], i, j});\n                }\n            }\n        }\n        \n        return result;\n    }\n    \n    int countSameFlavorAdjacency() const {\n        int count = 0;\n        const int dr[] = {-1, 1, 0, 0};\n        const int dc[] = {0, 0, -1, 1};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) continue;\n                for (int d = 0; d < 4; d++) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (grid[ni][nj] == grid[i][j]) {\n                            count++;\n                        }\n                    }\n                }\n            }\n        }\n        return count / 2;  // Each adjacency counted twice\n    }\n    \n    vector<int> getComponentSizes() const {\n        vector<int> sizes;\n        array<array<bool, N>, N> visited{};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0 && !visited[i][j]) {\n                    int flavor = grid[i][j];\n                    int size = 0;\n                    vector<pair<int,int>> stack = {{i, j}};\n                    visited[i][j] = true;\n                    \n                    while (!stack.empty()) {\n                        auto [r, c] = stack.back();\n                        stack.pop_back();\n                        size++;\n                        \n                        const int dr[] = {-1, 1, 0, 0};\n                        const int dc[] = {0, 0, -1, 1};\n                        \n                        for (int d = 0; d < 4; d++) {\n                            int nr = r + dr[d], nc = c + dc[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                if (!visited[nr][nc] && grid[nr][nc] == flavor) {\n                                    visited[nr][nc] = true;\n                                    stack.push_back({nr, nc});\n                                }\n                            }\n                        }\n                    }\n                    sizes.push_back(size);\n                }\n            }\n        }\n        return sizes;\n    }\n    \n    double evaluateScore() const {\n        auto sizes = getComponentSizes();\n        array<int, 4> flavorCount{};\n        \n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] != 0)\n                    flavorCount[grid[i][j]]++;\n        \n        double numerator = 0;\n        for (int s : sizes) numerator += s * s;\n        \n        double denominator = 0;\n        for (int f = 1; f <= 3; f++) denominator += flavorCount[f] * flavorCount[f];\n        \n        if (denominator == 0) return 0;\n        return 1e6 * numerator / denominator;\n    }\n    \n    // Heuristic evaluation for greedy selection\n    double heuristicEvaluate(const vector<int>& futureFlavors, int lookAhead) const {\n        double score = countSameFlavorAdjacency() * 10.0;\n        \n        // Add component size bonus\n        auto sizes = getComponentSizes();\n        for (int s : sizes) {\n            score += s * s * 0.5;\n        }\n        \n        // Consider future flavors - prefer tilts that create space for upcoming flavors\n        if (lookAhead > 0 && !futureFlavors.empty()) {\n            array<int, 4> flavorCount{};\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (grid[i][j] != 0)\n                        flavorCount[grid[i][j]]++;\n            \n            // Bonus for having clusters of flavors that appear soon\n            for (int f = 1; f <= 3; f++) {\n                if (flavorCount[f] > 0) {\n                    int upcoming = 0;\n                    for (int i = 0; i < min(lookAhead, (int)futureFlavors.size()); i++) {\n                        if (futureFlavors[i] == f) upcoming++;\n                    }\n                    score += upcoming * flavorCount[f] * 0.3;\n                }\n            }\n        }\n        \n        return score;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read flavor sequence\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    GameState state;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Find the p-th empty cell (1-indexed)\n        auto empty = state.getEmptyCells();\n        int row = empty[p - 1].first;\n        int col = empty[p - 1].second;\n        \n        // Place the candy\n        state.placeCandy(row, col, flavors[t]);\n        \n        // Skip tilt on last candy (nothing happens)\n        if (t == 99) {\n            cout << 'F' << endl;\n            continue;\n        }\n        \n        // Evaluate all 4 tilt directions\n        vector<pair<double, char>> evaluations;\n        \n        for (char dir : dirs) {\n            GameState next = state.tilt(dir);\n            \n            // Base heuristic score\n            double score = next.heuristicEvaluate(\n                vector<int>(flavors.begin() + t + 1, flavors.end()),\n                5\n            );\n            \n            // Add some randomness for exploration\n            score += (rng() % 100) * 0.01;\n            \n            evaluations.push_back({score, dir});\n        }\n        \n        // Select best direction\n        sort(evaluations.begin(), evaluations.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        char bestDir = evaluations[0].second;\n        cout << bestDir << endl;\n        \n        // Update state\n        state = state.tilt(bestDir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Compute degree sequence from edge string (sorted)\nvector<int> computeDegreeSeq(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Count edges\nint countEdges(const string& edges) {\n    int cnt = 0;\n    for (char c : edges) {\n        if (c == '1') cnt++;\n    }\n    return cnt;\n}\n\n// Count triangles O(N^3)\nint countTriangles(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    \n    int triangles = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!adj[i][j]) continue;\n            for (int k = j + 1; k < N; k++) {\n                if (adj[i][k] && adj[j][k]) {\n                    triangles++;\n                }\n            }\n        }\n    }\n    return triangles;\n}\n\n// Build adjacency matrix from edge string\nvector<vector<bool>> buildAdj(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    return adj;\n}\n\n// Count 4-cycles (another invariant)\nint count4Cycles(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    int cycles = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!adj[i][j]) continue;\n            for (int k = j + 1; k < N; k++) {\n                if (!adj[j][k]) continue;\n                for (int l = k + 1; l < N; l++) {\n                    if (adj[i][l] && adj[k][l]) {\n                        // Check if it forms a 4-cycle\n                        int edge_count = adj[i][j] + adj[j][k] + adj[k][l] + adj[l][i];\n                        if (edge_count >= 4) cycles++;\n                    }\n                }\n            }\n        }\n    }\n    return cycles;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n    \n    // Choose N based on epsilon and M\n    // Higher epsilon needs more redundancy (larger N)\n    // But larger N reduces score, so find balance\n    int N = 35;\n    if (eps > 0.30) N = 60;\n    else if (eps > 0.20) N = 50;\n    else if (eps > 0.10) N = 42;\n    else if (eps < 0.03) N = 25;\n    \n    // Ensure N is in valid range\n    N = max(4, min(100, N));\n    \n    int total_edges = N * (N - 1) / 2;\n    \n    // Store graph information for matching\n    vector<string> graphs(M);\n    vector<int> edge_counts(M);\n    vector<vector<int>> degree_seqs(M, vector<int>(N));\n    vector<int> triangle_counts(M);\n    \n    // Generate M graphs with well-separated properties\n    // Key idea: spread edge counts evenly to maximize separation\n    for (int k = 0; k < M; k++) {\n        // Target edge count - evenly distributed\n        int target_edges = M > 1 ? (k * total_edges) / (M - 1) : total_edges / 2;\n        target_edges = max(0, min(total_edges, target_edges));\n        edge_counts[k] = target_edges;\n        \n        // Create edge string\n        string g(total_edges, '0');\n        \n        // Select positions for edges using deterministic shuffle per graph\n        vector<int> positions(total_edges);\n        iota(positions.begin(), positions.end(), 0);\n        \n        // Different seed for each graph to get different edge distributions\n        mt19937 kg(10000 + k * 17);\n        shuffle(positions.begin(), positions.end(), kg);\n        \n        for (int i = 0; i < target_edges && i < total_edges; i++) {\n            g[positions[i]] = '1';\n        }\n        \n        graphs[k] = g;\n        \n        // Precompute invariants\n        degree_seqs[k] = computeDegreeSeq(g, N);\n        triangle_counts[k] = countTriangles(g, N);\n    }\n    \n    // Output N and graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << graphs[k] << \"\\n\";\n    }\n    cout << flush;\n    \n    // Process 100 queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        if (h.empty() || h.length() != (size_t)total_edges) {\n            // Fallback if input is malformed\n            cout << 0 << \"\\n\";\n            cout << flush;\n            continue;\n        }\n        \n        // Compute invariants for query graph\n        int h_edges = countEdges(h);\n        vector<int> h_deg = computeDegreeSeq(h, N);\n        int h_triangles = countTriangles(h, N);\n        \n        // Find best matching graph using weighted distance\n        int best_k = 0;\n        double best_score = 1e18;\n        \n        for (int k = 0; k < M; k++) {\n            double score = 0;\n            \n            // Edge count difference (most robust invariant)\n            // Weight heavily as it's very stable under permutation\n            double edge_diff = abs(h_edges - edge_counts[k]);\n            score += edge_diff * edge_diff * 0.15;\n            \n            // Degree sequence difference\n            // Also very stable under permutation, somewhat robust to noise\n            int deg_diff = 0;\n            for (int i = 0; i < N; i++) {\n                deg_diff += abs(h_deg[i] - degree_seqs[k][i]);\n            }\n            score += deg_diff * deg_diff * 0.08;\n            \n            // Triangle count difference\n            // More sensitive to noise but provides additional discrimination\n            double tri_diff = abs(h_triangles - triangle_counts[k]);\n            score += tri_diff * tri_diff * 0.25;\n            \n            if (score < best_score) {\n                best_score = score;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nstruct Edge {\n    int id;\n    int u, v;\n    long long w;\n    double mid_x, mid_y;\n    double importance;\n};\n\nclass Solver {\npublic:\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<vector<pair<int, int>>> adj;\n    vector<pair<int, int>> coords;\n    vector<vector<long long>> base_dist;\n    chrono::steady_clock::time_point start_time;\n    \n    static constexpr long long INF = 1e18;\n    static constexpr long long UNREACHABLE = 1000000000;\n    \n    void compute_base_distances() {\n        base_dist.assign(N, vector<long long>(N, INF));\n        \n        for (int src = 0; src < N; src++) {\n            base_dist[src][src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > base_dist[src][u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < base_dist[src][v]) {\n                        base_dist[src][v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n    }\n    \n    void compute_edge_importance() {\n        vector<double> importance(M, 0);\n        \n        int samples = min(N, 25);\n        vector<int> sources(samples);\n        for (int i = 0; i < samples; i++) {\n            sources[i] = i * N / samples;\n        }\n        \n        for (int src : sources) {\n            vector<long long> dist(N, INF);\n            vector<int> parent_edge(N, -1);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        parent_edge[v] = edge_idx;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int v = 0; v < N; v++) {\n                if (v != src && parent_edge[v] != -1) {\n                    importance[parent_edge[v]] += 1.0;\n                }\n            }\n        }\n        \n        for (int i = 0; i < M; i++) {\n            edges[i].importance = importance[i];\n        }\n    }\n    \n    double compute_frustration_fast(const vector<int>& edges_to_remove) {\n        if (edges_to_remove.empty()) return 0.0;\n        \n        vector<bool> edge_removed(M, false);\n        for (int idx : edges_to_remove) {\n            edge_removed[idx] = true;\n        }\n        \n        double total_increase = 0;\n        int sample_vertices = min(N, 20);\n        vector<int> samples(sample_vertices);\n        for (int i = 0; i < sample_vertices; i++) {\n            samples[i] = i * N / sample_vertices;\n        }\n        \n        for (int src : samples) {\n            vector<long long> dist(N, INF);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    if (edge_removed[edge_idx]) continue;\n                    \n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int dst : samples) {\n                if (src == dst) continue;\n                \n                long long d_k = (dist[dst] >= INF) ? UNREACHABLE : dist[dst];\n                long long d_base = (base_dist[src][dst] >= INF) ? UNREACHABLE : base_dist[src][dst];\n                \n                total_increase += max(0LL, d_k - d_base);\n            }\n        }\n        \n        double scale = (double)(N * (N - 1)) / (sample_vertices * (sample_vertices - 1));\n        return total_increase * scale / (N * (N - 1));\n    }\n    \n    double compute_total_frustration(const vector<int>& assignment) {\n        vector<vector<int>> day_edges(D);\n        for (int i = 0; i < M; i++) {\n            day_edges[assignment[i] - 1].push_back(i);\n        }\n        \n        double total = 0;\n        for (int d = 0; d < D; d++) {\n            total += compute_frustration_fast(day_edges[d]);\n        }\n        return total / D;\n    }\n    \n    vector<int> solve() {\n        start_time = chrono::steady_clock::now();\n        \n        compute_base_distances();\n        compute_edge_importance();\n        \n        // Sort edges by importance (descending)\n        vector<int> edge_order(M);\n        iota(edge_order.begin(), edge_order.end(), 0);\n        sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n            return edges[a].importance > edges[b].importance;\n        });\n        \n        // Greedy assignment: spread important edges across days\n        vector<int> assignment(M);\n        vector<vector<int>> day_edges(D);\n        vector<double> day_importance(D, 0);\n        \n        for (int edge_idx : edge_order) {\n            int best_day = 0;\n            double min_importance = 1e18;\n            \n            for (int d = 0; d < D; d++) {\n                if ((int)day_edges[d].size() < K) {\n                    if (day_importance[d] < min_importance) {\n                        min_importance = day_importance[d];\n                        best_day = d;\n                    }\n                }\n            }\n            \n            assignment[edge_idx] = best_day + 1;\n            day_edges[best_day].push_back(edge_idx);\n            day_importance[best_day] += edges[edge_idx].importance;\n        }\n        \n        // Local search optimization\n        local_search(assignment);\n        \n        return assignment;\n    }\n    \n    void local_search(vector<int>& assignment) {\n        mt19937 rng(42);\n        \n        int iterations = 0;\n        int max_iterations = 500;\n        double current_score = compute_total_frustration(assignment);\n        double best_score = current_score;\n        vector<int> best_assignment = assignment;\n        \n        while (iterations < max_iterations) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 5.5) {\n                break;\n            }\n            \n            // Try swapping two edges\n            int i = uniform_int_distribution<>(0, M - 1)(rng);\n            int j = uniform_int_distribution<>(0, M - 1)(rng);\n            \n            if (i == j) continue;\n            \n            int day_i = assignment[i] - 1;\n            int day_j = assignment[j] - 1;\n            \n            if (day_i == day_j) continue;\n            \n            // Try swap\n            assignment[i] = day_j + 1;\n            assignment[j] = day_i + 1;\n            \n            double new_score = compute_total_frustration(assignment);\n            \n            if (new_score < best_score) {\n                best_score = new_score;\n                best_assignment = assignment;\n                iterations = 0;\n            } else {\n                // Revert\n                assignment[i] = day_i + 1;\n                assignment[j] = day_j + 1;\n                iterations++;\n            }\n        }\n        \n        assignment = best_assignment;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    Solver solver;\n    solver.N = N;\n    solver.M = M;\n    solver.D = D;\n    solver.K = K;\n    \n    solver.edges.resize(M);\n    solver.adj.resize(N);\n    solver.coords.resize(N);\n    \n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        solver.edges[i] = {i, u, v, (long long)w, 0, 0, 0};\n        solver.adj[u].push_back({v, i});\n        solver.adj[v].push_back({u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    \n    // Compute edge midpoints for potential spatial clustering\n    for (int i = 0; i < M; i++) {\n        int u = solver.edges[i].u;\n        int v = solver.edges[i].v;\n        solver.edges[i].mid_x = (solver.coords[u].first + solver.coords[v].first) / 2.0;\n        solver.edges[i].mid_y = (solver.coords[u].second + solver.coords[v].second) / 2.0;\n    }\n    \n    auto assignment = solver.solve();\n    \n    for (int i = 0; i < M; i++) {\n        cout << assignment[i] << (i == M - 1 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n};\n\n// Generate all 24 rotations of a block\nvector<vector<Point3D>> generateRotations(const vector<Point3D>& cells) {\n    vector<vector<Point3D>> rotations;\n    \n    // 24 rotations: 6 faces \u00d7 4 rotations each\n    vector<array<int, 3>> axes[24] = {\n        {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}},\n        {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, {{1, 0, 0}, {0, 0, -1}, {0, 1, 0}},\n        {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}, {{-1, 0, 0}, {0, 0, 1}, {0, 1, 0}},\n        {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}}, {{-1, 0, 0}, {0, 0, -1}, {0, -1, 0}},\n        {{0, 1, 0}, {1, 0, 0}, {0, 0, -1}}, {{0, 1, 0}, {0, 0, 1}, {1, 0, 0}},\n        {{0, 1, 0}, {-1, 0, 0}, {0, 0, 1}}, {{0, 1, 0}, {0, 0, -1}, {-1, 0, 0}},\n        {{0, -1, 0}, {1, 0, 0}, {0, 0, 1}}, {{0, -1, 0}, {0, 0, -1}, {1, 0, 0}},\n        {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}, {{0, -1, 0}, {0, 0, 1}, {-1, 0, 0}},\n        {{0, 0, 1}, {1, 0, 0}, {0, 1, 0}}, {{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}},\n        {{0, 0, 1}, {-1, 0, 0}, {0, -1, 0}}, {{0, 0, 1}, {0, -1, 0}, {1, 0, 0}},\n        {{0, 0, -1}, {1, 0, 0}, {0, -1, 0}}, {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}},\n        {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}}, {{0, 0, -1}, {0, -1, 0}, {-1, 0, 0}}\n    };\n    \n    for (int r = 0; r < 24; r++) {\n        vector<Point3D> rotated;\n        for (const auto& cell : cells) {\n            Point3D p;\n            p.x = cell.x * axes[r][0][0] + cell.y * axes[r][0][1] + cell.z * axes[r][0][2];\n            p.y = cell.x * axes[r][1][0] + cell.y * axes[r][1][1] + cell.z * axes[r][1][2];\n            p.z = cell.x * axes[r][2][0] + cell.y * axes[r][2][1] + cell.z * axes[r][2][2];\n            rotated.push_back(p);\n        }\n        // Normalize (translate to origin)\n        int min_x = INT_MAX, min_y = INT_MAX, min_z = INT_MAX;\n        for (const auto& p : rotated) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n        sort(rotated.begin(), rotated.end());\n        rotations.push_back(rotated);\n    }\n    \n    // Remove duplicates\n    sort(rotations.begin(), rotations.end());\n    rotations.erase(unique(rotations.begin(), rotations.end()), rotations.end());\n    \n    return rotations;\n}\n\n// Check if two blocks have the same shape (one is rotation of other)\nbool sameShape(const vector<Point3D>& cells1, const vector<Point3D>& cells2) {\n    if (cells1.size() != cells2.size()) return false;\n    auto rotations = generateRotations(cells1);\n    for (const auto& rot : rotations) {\n        if (rot == cells2) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D;\n    cin >> D;\n    \n    // Read silhouettes\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; i++) cin >> f1[i];\n    for (int i = 0; i < D; i++) cin >> r1[i];\n    for (int i = 0; i < D; i++) cin >> f2[i];\n    for (int i = 0; i < D; i++) cin >> r2[i];\n    \n    // Compute valid positions for each silhouette\n    // valid[z][y][x] = true if block can be placed at (x,y,z)\n    vector<vector<vector<bool>>> valid1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> valid2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[z][y][x] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Find common valid positions\n    vector<vector<vector<bool>>> common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                common[z][y][x] = valid1[z][y][x] && valid2[z][y][x];\n            }\n        }\n    }\n    \n    // Output grids\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Track blocks: block_id -> cells in arrangement 1 and 2\n    map<int, vector<Point3D>> block_cells1, block_cells2;\n    \n    int block_id = 1;\n    \n    // Strategy: Try to create larger blocks in common region first\n    // Use connected component labeling on common positions\n    \n    vector<vector<vector<bool>>> visited(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // BFS to find connected components in common region\n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x] && !visited[z][y][x]) {\n                    // BFS to find connected component\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front();\n                        q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                common[nz][ny][nx] && !visited[nz][ny][nx]) {\n                                visited[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    // Assign this component as a shared block\n                    for (const auto& cell : component) {\n                        b1[cell.z][cell.y][cell.x] = block_id;\n                        b2[cell.z][cell.y][cell.x] = block_id;\n                        block_cells1[block_id].push_back(cell);\n                        block_cells2[block_id].push_back(cell);\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Now handle positions valid only in arrangement 1\n    fill(visited.begin(), visited.end(), vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (valid1[z][y][x] && !common[z][y][x] && !visited[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front();\n                        q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                valid1[nz][ny][nx] && !common[nz][ny][nx] && !visited[nz][ny][nx]) {\n                                visited[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& cell : component) {\n                        b1[cell.z][cell.y][cell.x] = block_id;\n                        block_cells1[block_id].push_back(cell);\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Handle positions valid only in arrangement 2\n    fill(visited.begin(), visited.end(), vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (valid2[z][y][x] && !common[z][y][x] && !visited[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front();\n                        q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                valid2[nz][ny][nx] && !common[nz][ny][nx] && !visited[nz][ny][nx]) {\n                                visited[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& cell : component) {\n                        b2[cell.z][cell.y][cell.x] = block_id;\n                        block_cells2[block_id].push_back(cell);\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Verify and fix: blocks used in both must have same shape\n    // For blocks in both, normalize their shapes and check\n    map<int, vector<Point3D>> normalized_shape1, normalized_shape2;\n    \n    for (auto& [id, cells] : block_cells1) {\n        if (block_cells2.count(id)) {\n            // Normalize shape 1\n            vector<Point3D> norm1 = cells;\n            int min_x = INT_MAX, min_y = INT_MAX, min_z = INT_MAX;\n            for (const auto& p : norm1) {\n                min_x = min(min_x, p.x);\n                min_y = min(min_y, p.y);\n                min_z = min(min_z, p.z);\n            }\n            for (auto& p : norm1) {\n                p.x -= min_x;\n                p.y -= min_y;\n                p.z -= min_z;\n            }\n            sort(norm1.begin(), norm1.end());\n            normalized_shape1[id] = norm1;\n            \n            // Normalize shape 2\n            vector<Point3D> norm2 = block_cells2[id];\n            min_x = INT_MAX; min_y = INT_MAX; min_z = INT_MAX;\n            for (const auto& p : norm2) {\n                min_x = min(min_x, p.x);\n                min_y = min(min_y, p.y);\n                min_z = min(min_z, p.z);\n            }\n            for (auto& p : norm2) {\n                p.x -= min_x;\n                p.y -= min_y;\n                p.z -= min_z;\n            }\n            sort(norm2.begin(), norm2.end());\n            normalized_shape2[id] = norm2;\n        }\n    }\n    \n    // If shapes don't match, split into separate blocks\n    vector<int> to_split;\n    for (auto& [id, cells1] : normalized_shape1) {\n        if (normalized_shape2.count(id)) {\n            if (cells1 != normalized_shape2[id]) {\n                // Check if one is rotation of other\n                if (!sameShape(cells1, normalized_shape2[id])) {\n                    to_split.push_back(id);\n                }\n            }\n        }\n    }\n    \n    // For mismatched blocks, we need to use separate block IDs\n    // This is complex - for now, fall back to 1x1x1 for problematic blocks\n    if (!to_split.empty()) {\n        // Reset and use simpler approach\n        fill(b1.begin(), b1.end(), vector<vector<int>>(D, vector<int>(D, 0)));\n        fill(b2.begin(), b2.end(), vector<vector<int>>(D, vector<int>(D, 0)));\n        block_id = 1;\n        \n        // Use 1x1x1 blocks for common positions\n        for (int z = 0; z < D; z++) {\n            for (int y = 0; y < D; y++) {\n                for (int x = 0; x < D; x++) {\n                    if (common[z][y][x]) {\n                        b1[z][y][x] = block_id;\n                        b2[z][y][x] = block_id;\n                        block_id++;\n                    }\n                }\n            }\n        }\n        \n        // 1x1x1 blocks for valid1 only\n        for (int z = 0; z < D; z++) {\n            for (int y = 0; y < D; y++) {\n                for (int x = 0; x < D; x++) {\n                    if (valid1[z][y][x] && !common[z][y][x]) {\n                        b1[z][y][x] = block_id;\n                        block_id++;\n                    }\n                }\n            }\n        }\n        \n        // 1x1x1 blocks for valid2 only\n        for (int z = 0; z < D; z++) {\n            for (int y = 0; y < D; y++) {\n                for (int x = 0; x < D; x++) {\n                    if (valid2[z][y][x] && !common[z][y][x]) {\n                        b2[z][y][x] = block_id;\n                        block_id++;\n                    }\n                }\n            }\n        }\n    }\n    \n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    \n    // Output b1 (flattened: x*D^2 + y*D + z)\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                cout << b1[z][y][x];\n                if (!(z == D-1 && y == D-1 && x == D-1)) cout << \" \";\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    // Output b2\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                cout << b2[z][y][x];\n                if (!(z == D-1 && y == D-1 && x == D-1)) cout << \" \";\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <numeric>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        return parent[x] == x ? x : parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        parent[y] = x;\n        return true;\n    }\n};\n\nlong long dist_ll(Point a, Point b) {\n    long long dx = a.x - b.x;\n    long long dy = a.y - b.y;\n    return round(sqrt(dx * dx + dy * dy));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    vector<Point> stations(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n    }\n    \n    vector<Point> residents(K);\n    for (int i = 0; i < K; i++) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n    \n    // Precompute distances from each resident to each station\n    vector<vector<long long>> resident_station_dist(K, vector<long long>(N));\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            resident_station_dist[k][i] = dist_ll(residents[k], stations[i]);\n        }\n    }\n    \n    // Build MST from station 0 for initial connectivity\n    vector<pair<long long, int>> mst_edges;\n    vector<Edge> sorted_edges = edges;\n    sort(sorted_edges.begin(), sorted_edges.end(), \n         [](const Edge& a, const Edge& b) { return a.w < b.w; });\n    \n    DSU dsu(N);\n    vector<int> edge_in_mst(M, 0);\n    long long mst_cost = 0;\n    int edges_added = 0;\n    \n    for (int i = 0; i < M && edges_added < N - 1; i++) {\n        int idx = -1;\n        for (int j = 0; j < M; j++) {\n            if (edge_in_mst[j]) continue;\n            if (edges[j].w == sorted_edges[i].w && \n                dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                idx = j;\n                break;\n            }\n        }\n        if (idx == -1) {\n            for (int j = 0; j < M; j++) {\n                if (edge_in_mst[j]) continue;\n                if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                    idx = j;\n                    break;\n                }\n            }\n        }\n        if (idx != -1) {\n            dsu.unite(edges[idx].u, edges[idx].v);\n            edge_in_mst[idx] = 1;\n            mst_cost += edges[idx].w;\n            edges_added++;\n        }\n    }\n    \n    // Find connected component from station 0\n    vector<int> reachable(N, 0);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (edge_in_mst[i]) {\n            adj[edges[i].u].push_back(edges[i].v);\n            adj[edges[i].v].push_back(edges[i].u);\n        }\n    }\n    \n    queue<int> q;\n    q.push(0);\n    reachable[0] = 1;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (!reachable[v]) {\n                reachable[v] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Assign residents to nearest reachable station\n    vector<long long> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        long long min_dist = 1e18;\n        int best_station = -1;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i]) {\n                if (resident_station_dist[k][i] < min_dist) {\n                    min_dist = resident_station_dist[k][i];\n                    best_station = i;\n                }\n            }\n        }\n        if (best_station != -1 && min_dist <= 5000) {\n            P[best_station] = max(P[best_station], min_dist);\n        }\n    }\n    \n    // Calculate initial cost\n    auto calc_cost = [&]() -> long long {\n        long long cost = 0;\n        for (int i = 0; i < N; i++) {\n            cost += P[i] * P[i];\n        }\n        for (int i = 0; i < M; i++) {\n            if (edge_in_mst[i]) {\n                cost += edges[i].w;\n            }\n        }\n        return cost;\n    };\n    \n    auto check_coverage = [&]() -> bool {\n        for (int k = 0; k < K; k++) {\n            bool covered = false;\n            for (int i = 0; i < N; i++) {\n                if (reachable[i] && resident_station_dist[k][i] <= P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n            if (!covered) return false;\n        }\n        return true;\n    };\n    \n    long long best_cost = calc_cost();\n    vector<int> best_edge_state = edge_in_mst;\n    vector<long long> best_P = P;\n    \n    // Try adding beneficial edges\n    mt19937 rng(42);\n    for (int iter = 0; iter < 500; iter++) {\n        vector<int> current_edge_state = best_edge_state;\n        vector<long long> current_P = best_P;\n        \n        // Recompute reachable\n        vector<int> cur_reachable(N, 0);\n        vector<vector<int>> cur_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (current_edge_state[i]) {\n                cur_adj[edges[i].u].push_back(edges[i].v);\n                cur_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> cq;\n        cq.push(0);\n        cur_reachable[0] = 1;\n        while (!cq.empty()) {\n            int u = cq.front(); cq.pop();\n            for (int v : cur_adj[u]) {\n                if (!cur_reachable[v]) {\n                    cur_reachable[v] = 1;\n                    cq.push(v);\n                }\n            }\n        }\n        \n        // Try adding a random edge\n        int edge_to_add = uniform_int_distribution<>(0, M-1)(rng);\n        if (!current_edge_state[edge_to_add]) {\n            current_edge_state[edge_to_add] = 1;\n            \n            // Recompute reachable\n            fill(cur_reachable.begin(), cur_reachable.end(), 0);\n            for (int i = 0; i < N; i++) cur_adj[i].clear();\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    cur_adj[edges[i].u].push_back(edges[i].v);\n                    cur_adj[edges[i].v].push_back(edges[i].u);\n                }\n            }\n            cq = queue<int>();\n            cq.push(0);\n            cur_reachable[0] = 1;\n            while (!cq.empty()) {\n                int u = cq.front(); cq.pop();\n                for (int v : cur_adj[u]) {\n                    if (!cur_reachable[v]) {\n                        cur_reachable[v] = 1;\n                        cq.push(v);\n                    }\n                }\n            }\n            \n            // Recalculate P\n            fill(current_P.begin(), current_P.end(), 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    current_P[best_station] = max(current_P[best_station], min_dist);\n                }\n            }\n            \n            // Calculate new cost\n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += current_P[i] * current_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            // Check if all residents covered\n            bool all_covered = true;\n            for (int k = 0; k < K; k++) {\n                bool covered = false;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i] && resident_station_dist[k][i] <= current_P[i]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    all_covered = false;\n                    break;\n                }\n            }\n            \n            if (all_covered && new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = current_edge_state;\n                best_P = current_P;\n            }\n        }\n    }\n    \n    // Try removing expensive edges if possible\n    vector<pair<long long, int>> edge_by_cost;\n    for (int i = 0; i < M; i++) {\n        if (best_edge_state[i]) {\n            edge_by_cost.push_back({edges[i].w, i});\n        }\n    }\n    sort(edge_by_cost.rbegin(), edge_by_cost.rend());\n    \n    for (auto& [w, idx] : edge_by_cost) {\n        vector<int> test_edge_state = best_edge_state;\n        test_edge_state[idx] = 0;\n        \n        // Check if still connected\n        vector<int> test_reachable(N, 0);\n        vector<vector<int>> test_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (test_edge_state[i]) {\n                test_adj[edges[i].u].push_back(edges[i].v);\n                test_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> tq;\n        tq.push(0);\n        test_reachable[0] = 1;\n        while (!tq.empty()) {\n            int u = tq.front(); tq.pop();\n            for (int v : test_adj[u]) {\n                if (!test_reachable[v]) {\n                    test_reachable[v] = 1;\n                    tq.push(v);\n                }\n            }\n        }\n        \n        // Check if all residents still coverable\n        bool all_coverable = true;\n        for (int k = 0; k < K; k++) {\n            bool can_cover = false;\n            for (int i = 0; i < N; i++) {\n                if (test_reachable[i] && resident_station_dist[k][i] <= 5000) {\n                    can_cover = true;\n                    break;\n                }\n            }\n            if (!can_cover) {\n                all_coverable = false;\n                break;\n            }\n        }\n        \n        if (all_coverable) {\n            vector<long long> test_P(N, 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (test_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    test_P[best_station] = max(test_P[best_station], min_dist);\n                }\n            }\n            \n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += test_P[i] * test_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (test_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = test_edge_state;\n                best_P = test_P;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << best_P[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << best_edge_state[i] << (i == M-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\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\nint N = 30;\nint grid[30][30];\nPoint pos[465]; // pos[value] = {x, y}\nvector<tuple<int, int, int, int>> ops;\n\n// Directions for neighbors\n// (dx, dy)\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid swap_balls(int x1, int y1, int x2, int y2) {\n    int v1 = grid[x1][y1];\n    int v2 = grid[x2][y2];\n    grid[x1][y1] = v2;\n    grid[x2][y2] = v1;\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n}\n\n// BFS to find closest needed value\nint find_and_move(int r, int c, const vector<bool>& is_needed) {\n    Point target = {r, c};\n    \n    // BFS structures\n    // Using static arrays to avoid reallocation, but resetting visited\n    static int dist[30][30];\n    static Point parent[30][30];\n    static bool visited[30][30];\n    \n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            visited[i][j] = false;\n        }\n    }\n    \n    queue<pair<Point, int>> q;\n    q.push({target, 0});\n    visited[r][c] = true;\n    dist[r][c] = 0;\n    parent[r][c] = {-1, -1};\n    \n    Point best_pos = {-1, -1};\n    int best_val = -1;\n    int best_dist = 1e9;\n    \n    while(!q.empty()) {\n        pair<Point, int> front = q.front();\n        Point curr = front.first;\n        int d = front.second;\n        q.pop();\n        \n        if (d > best_dist) {\n            // Since BFS is ordered by distance, we can stop if we exceed best_dist\n            // However, we need to finish the current layer if d == best_dist to ensure we found the closest\n            // But since we update best_dist immediately, any subsequent node with d >= best_dist won't improve.\n            // So we can break.\n            break;\n        }\n        \n        // Check if this cell has a needed value\n        int val = grid[curr.x][curr.y];\n        if (is_needed[val]) {\n            if (d < best_dist) {\n                best_dist = d;\n                best_pos = curr;\n                best_val = val;\n            }\n        }\n        \n        // Expand neighbors\n        for(int i=0; i<6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (is_valid(nx, ny)) {\n                // Obstacle check\n                // 1. Rows < r are forbidden\n                if (nx < r) continue;\n                // 2. In row r, cols < c are forbidden (already filled)\n                if (nx == r && ny < c) continue;\n                \n                if (!visited[nx][ny]) {\n                    visited[nx][ny] = true;\n                    dist[nx][ny] = d + 1;\n                    parent[nx][ny] = curr;\n                    q.push({{nx, ny}, d + 1});\n                }\n            }\n        }\n    }\n    \n    if (best_val == -1) {\n        return -1;\n    }\n    \n    // Reconstruct path from best_pos to target\n    vector<Point> sequence;\n    Point curr = best_pos;\n    while (true) {\n        sequence.push_back(curr);\n        if (curr == target) break;\n        curr = parent[curr.x][curr.y];\n    }\n    \n    // Execute swaps\n    // sequence[0] is start, sequence.back() is target.\n    for (size_t i = 0; i < sequence.size() - 1; ++i) {\n        swap_balls(sequence[i].x, sequence[i].y, sequence[i+1].x, sequence[i+1].y);\n    }\n    \n    return best_val;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read input\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> grid[i][j];\n            pos[grid[i][j]] = {i, j};\n        }\n    }\n    \n    // Process each row from top to bottom\n    for (int r = 0; r < N; ++r) {\n        int start_val = r * (r + 1) / 2;\n        int end_val = (r + 1) * (r + 2) / 2 - 1;\n        \n        vector<bool> is_needed(465, false);\n        for (int v = start_val; v <= end_val; ++v) {\n            is_needed[v] = true;\n        }\n        \n        // Fill row r positions 0 to r\n        for (int c = 0; c <= r; ++c) {\n            int val = find_and_move(r, c, is_needed);\n            if (val == -1) {\n                // Should not happen\n                return 1;\n            }\n            // The value is now at (r, c).\n            // In the next iteration (c+1), (r, c) becomes an obstacle.\n            // So this value won't be picked again.\n        }\n    }\n    \n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \" << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0;\nconst int ENTRANCE_J = 4;\n\nstruct Container {\n    int id;\n    int pi, pj;\n};\n\n// Check if a cell is reachable from entrance through empty cells\nbool isReachable(int di, int dj, int D, const vector<vector<bool>>& obstacle, \n                 const vector<vector<bool>>& occupied, const vector<vector<bool>>& exclude) {\n    if (obstacle[di][dj] || occupied[di][dj] || exclude[di][dj]) return false;\n    if (di == ENTRANCE_I && dj == ENTRANCE_J) return true;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == di && cj == dj) return true;\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && \n                !occupied[ni][nj] && !exclude[ni][nj]) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return false;\n}\n\n// Get all reachable empty cells from entrance\nvector<pair<int,int>> getReachableEmpty(int D, const vector<vector<bool>>& obstacle,\n                                         const vector<vector<bool>>& occupied) {\n    vector<pair<int,int>> result;\n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && !occupied[ni][nj]) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n                result.push_back({ni, nj});\n            }\n        }\n    }\n    return result;\n}\n\n// Compute BFS distance from entrance\nint bfsDistance(int ti, int tj, int D, const vector<vector<bool>>& obstacle) {\n    if (ti == ENTRANCE_I && tj == ENTRANCE_J) return 0;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    dist[ENTRANCE_I][ENTRANCE_J] = 0;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                dist[ni][nj] == -1 && !obstacle[ni][nj]) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                if (ni == ti && nj == tj) return dist[ni][nj];\n                q.push({ni, nj});\n            }\n        }\n    }\n    return D * D;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    int D_val;\n    cin >> D_val >> N;\n    \n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n    \n    // Pre-compute distances for all cells\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (!obstacle[i][j] && !(i == ENTRANCE_I && j == ENTRANCE_J)) {\n                dist[i][j] = bfsDistance(i, j, D, obstacle);\n                cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Sort cells by distance (farthest first for storage)\n    sort(cells.begin(), cells.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        return dist[a.first][a.second] > dist[b.first][b.second];\n    });\n    \n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n    vector<Container> containers;\n    int totalContainers = D * D - 1 - N;\n    \n    // Storage phase\n    for (int d = 0; d < totalContainers; d++) {\n        int t;\n        cin >> t;\n        \n        // Find farthest reachable empty cell\n        int bestI = -1, bestJ = -1;\n        for (auto& [i, j] : cells) {\n            if (!occupied[i][j]) {\n                // Temporarily mark as occupied to check reachability\n                occupied[i][j] = true;\n                \n                // Check if still reachable (for future containers)\n                auto reachable = getReachableEmpty(D, obstacle, occupied);\n                \n                // Check if we can still reach all currently occupied cells\n                bool allReachable = true;\n                for (auto& c : containers) {\n                    occupied[c.pi][c.pj] = false;\n                    if (!isReachable(c.pi, c.pj, D, obstacle, occupied, {{}})) {\n                        allReachable = false;\n                    }\n                    occupied[c.pi][c.pj] = true;\n                }\n                \n                occupied[i][j] = false;\n                \n                if (allReachable && reachable.size() >= (totalContainers - d - 1)) {\n                    bestI = i;\n                    bestJ = j;\n                    break;\n                }\n            }\n        }\n        \n        // Fallback: just pick first reachable\n        if (bestI == -1) {\n            auto reachable = getReachableEmpty(D, obstacle, occupied);\n            if (!reachable.empty()) {\n                // Pick farthest reachable\n                pair<int,int> best = reachable[0];\n                for (auto& [i, j] : reachable) {\n                    if (dist[i][j] > dist[best.first][best.second]) {\n                        best = {i, j};\n                    }\n                }\n                bestI = best.first;\n                bestJ = best.second;\n            }\n        }\n        \n        occupied[bestI][bestJ] = true;\n        containers.push_back({t, bestI, bestJ});\n        cout << bestI << \" \" << bestJ << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval phase - output containers in ID order\n    sort(containers.begin(), containers.end(), [](const Container& a, const Container& b) {\n        return a.id < b.id;\n    });\n    \n    for (auto& c : containers) {\n        cout << c.pi << \" \" << c.pj << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    // Use a 2D vector to store the grid. \n    // n=50 is small, so memory usage is negligible.\n    vector<vector<int>> grid(n, vector<int>(n));\n\n    // Read the input grid\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    // Output the grid exactly as is.\n    // Reasoning:\n    // 1. The input constraints state 1 <= c_{i,j} <= m, so there are no 0s in the input.\n    // 2. The score is (number of 0s) + 1. Since input has 0 zeros, Score = 1.\n    // 3. Score 1 is the theoretical minimum (count cannot be negative).\n    // 4. The input is guaranteed to satisfy connectivity for colors 1..m.\n    // 5. Color 0 connectivity is satisfied via the \"outside\" region (as per problem note).\n    // 6. Adjacencies are preserved because the map is identical.\n    // Thus, echoing the input is the optimal and safest strategy.\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 <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Weight estimates using Elo-style rating\n    vector<double> rating(N, 1000.0);\n    const double K = 20.0; // Learning rate\n    \n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int queries_used = 0;\n    \n    // Phase 1: Systematic pairwise comparisons\n    // First, compare each item with several others to get baseline estimates\n    vector<vector<int>> comparison_count(N, vector<int>(N, 0));\n    \n    // Create a comparison schedule\n    vector<pair<int, int>> comparisons;\n    \n    // Round-robin style comparisons for good coverage\n    for (int offset = 1; offset < N && (int)comparisons.size() < Q; offset++) {\n        for (int i = 0; i < N && (int)comparisons.size() < Q; i++) {\n            int j = (i + offset) % N;\n            if (i < j) {\n                comparisons.push_back({i, j});\n            }\n        }\n    }\n    \n    // Execute comparisons\n    for (auto& [i, j] : comparisons) {\n        if (queries_used >= Q) break;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        // Expected score based on current ratings\n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        // Actual score\n        double actual_i, actual_j;\n        if (result == \"<\") {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result == \">\") {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else { // \"=\"\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        // Update ratings\n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n        comparison_count[i][j]++;\n        comparison_count[j][i]++;\n    }\n    \n    // Use remaining queries for additional random comparisons\n    // Focus on items with fewer comparisons\n    while (queries_used < Q) {\n        // Find items with fewer comparisons\n        vector<int> comparison_total(N, 0);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                comparison_total[i] += comparison_count[i][j];\n            }\n        }\n        \n        // Weighted random selection (prefer less compared items)\n        vector<double> weights(N);\n        double weight_sum = 0;\n        for (int i = 0; i < N; i++) {\n            weights[i] = 1.0 / (1.0 + comparison_total[i]);\n            weight_sum += weights[i];\n        }\n        \n        uniform_real_distribution<> dist(0, weight_sum);\n        double r = dist(rng);\n        int i = 0;\n        for (; i < N - 1; i++) {\n            r -= weights[i];\n            if (r <= 0) break;\n        }\n        \n        int j;\n        do {\n            j = rng() % N;\n        } while (j == i);\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        double actual_i, actual_j;\n        if (result == \"<\") {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result == \">\") {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else {\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n        comparison_count[i][j]++;\n        comparison_count[j][i]++;\n    }\n    \n    // Phase 2: Partition items into D groups\n    // Sort items by rating (descending - heaviest first)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return rating[a] > rating[b];\n    });\n    \n    // Greedy assignment: assign heaviest items to lightest groups\n    vector<double> group_weight(D, 0.0);\n    vector<int> assignment(N);\n    vector<vector<int>> groups(D);\n    \n    for (int idx : indices) {\n        // Find group with minimum weight\n        int best_group = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] < group_weight[best_group]) {\n                best_group = g;\n            }\n        }\n        assignment[idx] = best_group;\n        group_weight[best_group] += rating[idx];\n        groups[best_group].push_back(idx);\n    }\n    \n    // Phase 3: Local search optimization\n    // Try swapping items between groups to reduce variance\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        // Calculate current variance\n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        double current_variance = 0;\n        for (int g = 0; g < D; g++) {\n            current_variance += (group_weight[g] - mean) * (group_weight[g] - mean);\n        }\n        \n        // Try swapping pairs of items from different groups\n        for (int g1 = 0; g1 < D && !improved; g1++) {\n            for (int g2 = g1 + 1; g2 < D && !improved; g2++) {\n                for (int i1 : groups[g1]) {\n                    for (int i2 : groups[g2]) {\n                        // Calculate new weights if we swap\n                        double new_w1 = group_weight[g1] - rating[i1] + rating[i2];\n                        double new_w2 = group_weight[g2] - rating[i2] + rating[i1];\n                        \n                        // Calculate new variance contribution\n                        double old_contrib = (group_weight[g1] - mean) * (group_weight[g1] - mean) +\n                                            (group_weight[g2] - mean) * (group_weight[g2] - mean);\n                        double new_contrib = (new_w1 - mean) * (new_w1 - mean) +\n                                            (new_w2 - mean) * (new_w2 - mean);\n                        \n                        if (new_contrib < old_contrib - 1e-9) {\n                            // Perform swap\n                            assignment[i1] = g2;\n                            assignment[i2] = g1;\n                            \n                            // Update groups\n                            auto it1 = find(groups[g1].begin(), groups[g1].end(), i1);\n                            auto it2 = find(groups[g2].begin(), groups[g2].end(), i2);\n                            *it1 = i2;\n                            *it2 = i1;\n                            \n                            group_weight[g1] = new_w1;\n                            group_weight[g2] = new_w2;\n                            \n                            improved = true;\n                            break;\n                        }\n                    }\n                    if (improved) break;\n                }\n                if (improved) break;\n            }\n        }\n        \n        // Also try moving single items\n        if (!improved) {\n            for (int g1 = 0; g1 < D && !improved; g1++) {\n                for (int g2 = 0; g2 < D && !improved; g2++) {\n                    if (g1 == g2) continue;\n                    if (groups[g1].empty()) continue;\n                    \n                    for (int i : groups[g1]) {\n                        double new_w1 = group_weight[g1] - rating[i];\n                        double new_w2 = group_weight[g2] + rating[i];\n                        \n                        double old_contrib = (group_weight[g1] - mean) * (group_weight[g1] - mean) +\n                                            (group_weight[g2] - mean) * (group_weight[g2] - mean);\n                        double new_contrib = (new_w1 - mean) * (new_w1 - mean) +\n                                            (new_w2 - mean) * (new_w2 - mean);\n                        \n                        if (new_contrib < old_contrib - 1e-9) {\n                            assignment[i] = g2;\n                            \n                            auto it = find(groups[g1].begin(), groups[g1].end(), i);\n                            groups[g1].erase(it);\n                            groups[g2].push_back(i);\n                            \n                            group_weight[g1] = new_w1;\n                            group_weight[g2] = new_w2;\n                            \n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output 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\nusing namespace std;\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    int bps = n / m;  // boxes per stack\n    \n    // Stack representation: stacks[i] = boxes from bottom to top\n    vector<vector<int>> stacks(m);\n    // Position tracking\n    vector<int> box_stack(n + 1);   // which stack contains box v\n    vector<int> box_height(n + 1);  // height in that stack (0 = bottom)\n    \n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < bps; j++) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            box_stack[box] = i;\n            box_height[box] = j;\n        }\n    }\n    \n    vector<pair<int, int>> ops;\n    \n    for (int target = 1; target <= n; target++) {\n        int s = box_stack[target];\n        int h = box_height[target];\n        int top = (int)stacks[s].size() - 1;\n        \n        if (h == top) {\n            // Target is at top, remove directly (operation 2)\n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            \n            // Update positions for remaining boxes in this stack\n            for (size_t i = 0; i < stacks[s].size(); i++) {\n                int b = stacks[s][i];\n                box_stack[b] = s;\n                box_height[b] = (int)i;\n            }\n        } else {\n            // Need to move boxes from height h to top (operation 1)\n            vector<int> moving;\n            for (int i = h; i <= top; i++) {\n                moving.push_back(stacks[s][i]);\n            }\n            \n            // Find best destination stack using heuristic scoring\n            int best = -1;\n            long long best_score = -1000000000000LL;\n            \n            for (int d = 0; d < m; d++) {\n                if (d == s) continue;\n                \n                long long score = 0;\n                \n                // Strong preference for empty stacks\n                if (stacks[d].empty()) {\n                    score += 10000000;\n                } else {\n                    int dest_top = stacks[d].back();\n                    // Prefer stacks where top box won't block near targets\n                    if (dest_top > target) {\n                        score += dest_top * 10;\n                    }\n                }\n                \n                // Bonus for moving high-numbered boxes (won't block soon)\n                for (int b : moving) {\n                    if (b > target + 50) {\n                        score += 5000;\n                    } else if (b > target + 20) {\n                        score += 2000;\n                    } else if (b > target) {\n                        score += 500;\n                    }\n                }\n                \n                // Penalty for blocking future targets\n                int dest_size = (int)stacks[d].size();\n                for (int f = target + 1; f <= min(target + 20, n); f++) {\n                    if (box_stack[f] == d && box_height[f] >= dest_size) {\n                        // This future target would be blocked by our move\n                        score -= 100000;\n                    }\n                }\n                \n                // Prefer stacks with fewer boxes (less likely to block)\n                score -= (long long)stacks[d].size() * 100;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best = d;\n                }\n            }\n            \n            // Fallback if no destination found\n            if (best == -1) {\n                for (int d = 0; d < m; d++) {\n                    if (d != s) {\n                        best = d;\n                        break;\n                    }\n                }\n            }\n            \n            // Operation 1: Move target and boxes above to destination\n            ops.push_back({target, best + 1});\n            \n            // Remove from source stack\n            stacks[s].resize(h);\n            for (size_t i = 0; i < stacks[s].size(); i++) {\n                int b = stacks[s][i];\n                box_stack[b] = s;\n                box_height[b] = (int)i;\n            }\n            \n            // Add to destination stack\n            for (int b : moving) {\n                stacks[best].push_back(b);\n                box_stack[b] = best;\n                box_height[b] = (int)stacks[best].size() - 1;\n            }\n            \n            // Operation 2: Remove target (now at top of destination)\n            ops.push_back({target, 0});\n            stacks[best].pop_back();\n            \n            // Update positions for remaining boxes in destination stack\n            for (size_t i = 0; i < stacks[best].size(); i++) {\n                int b = stacks[best][i];\n                box_stack[b] = best;\n                box_height[b] = (int)i;\n            }\n        }\n    }\n    \n    // Output all operations\n    for (auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    int N;\n    cin >> N;\n    \n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    vector<vector<int>> d(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    // Build adjacency list\n    const int DI[] = {-1, 0, 1, 0};\n    const int DJ[] = {0, 1, 0, -1};\n    const char DIR[] = {'U', 'R', 'D', 'L'};\n    \n    vector<vector<vector<int>>> adj(N, vector<vector<int>>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int dir = 0; dir < 4; dir++) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                bool has_wall = false;\n                if (dir == 0 && i > 0 && h[i-1][j] == '1') has_wall = true;\n                if (dir == 1 && v[i][j] == '1') has_wall = true;\n                if (dir == 2 && h[i][j] == '1') has_wall = true;\n                if (dir == 3 && j > 0 && v[i][j-1] == '1') has_wall = true;\n                \n                if (!has_wall) {\n                    adj[i][j].push_back(dir);\n                }\n            }\n        }\n    }\n    \n    // BFS to compute distances from (0,0) and check reachability\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({0, 0});\n    dist[0][0] = 0;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        for (int dir : adj[i][j]) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Create priority list of squares (higher d = higher priority)\n    vector<tuple<int, int, int>> squares;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            squares.push_back({d[i][j], i, j});\n        }\n    }\n    sort(squares.rbegin(), squares.rend());\n    \n    // BFS to find shortest path between two points\n    auto find_path = [&](int si, int sj, int ti, int tj) -> string {\n        if (si == ti && sj == tj) return \"\";\n        \n        vector<vector<int>> bd(N, vector<int>(N, -1));\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n        vector<vector<int>> pdir(N, vector<int>(N, -1));\n        queue<pair<int,int>> bq;\n        \n        bd[si][sj] = 0;\n        bq.push({si, sj});\n        \n        while (!bq.empty()) {\n            auto [i, j] = bq.front();\n            bq.pop();\n            \n            if (i == ti && j == tj) break;\n            \n            for (int dir : adj[i][j]) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (bd[ni][nj] == -1) {\n                    bd[ni][nj] = bd[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    pdir[ni][nj] = dir;\n                    bq.push({ni, nj});\n                }\n            }\n        }\n        \n        if (bd[ti][tj] == -1) return \"\";\n        \n        string path = \"\";\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path += DIR[pdir[ci][cj]];\n            auto [pi, pj] = parent[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    // Create initial route using DFS spanning tree\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string route = \"\";\n    int ci = 0, cj = 0;\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        // Sort neighbors by d value (visit high-d squares first)\n        vector<pair<int, int>> neighbors;\n        for (int dir : adj[i][j]) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            if (!visited[ni][nj]) {\n                neighbors.push_back({d[ni][nj], dir});\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        \n        for (auto [val, dir] : neighbors) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            route += DIR[dir];\n            dfs(ni, nj);\n            // Return: opposite direction\n            int opp_dir = (dir + 2) % 4;\n            route += DIR[opp_dir];\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Check route length and optimize if needed\n    const int MAX_LEN = 100000;\n    \n    // Try to optimize by creating a more efficient route\n    // Strategy: Visit high-priority squares more frequently\n    \n    if (route.length() < MAX_LEN / 2) {\n        // We have room to add more visits to high-d squares\n        string optimized = route;\n        \n        // Calculate visit count per square in current route\n        vector<vector<int>> visit_count(N, vector<int>(N, 0));\n        int pi = 0, pj = 0;\n        visit_count[0][0]++;\n        \n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            visit_count[pi][pj]++;\n        }\n        \n        // Add extra visits to highest-d squares\n        int total_d = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                total_d += d[i][j];\n            }\n        }\n        \n        // Target: visit count proportional to d[i][j]\n        for (auto [val, i, j] : squares) {\n            if ((int)optimized.length() >= MAX_LEN - 2 * N) break;\n            \n            int target_visits = max(1, (int)(val * route.length() / total_d));\n            int extra_needed = target_visits - visit_count[i][j];\n            \n            while (extra_needed > 0 && (int)optimized.length() < MAX_LEN - 2 * N) {\n                // Find path from current position to (i,j) and back\n                string to_target = find_path(pi, pj, i, j);\n                string back = find_path(i, j, pi, pj);\n                \n                if (to_target.empty() || back.empty()) break;\n                \n                optimized += to_target + back;\n                extra_needed--;\n                \n                // Update position (should be back at pi, pj)\n            }\n        }\n        \n        route = optimized;\n    }\n    \n    // Final check: ensure we end at (0,0)\n    int fi = 0, fj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                fi += DI[dir];\n                fj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (fi != 0 || fj != 0) {\n        string back = find_path(fi, fj, 0, 0);\n        route += back;\n    }\n    \n    // Ensure all squares visited\n    vector<vector<bool>> final_visited(N, vector<bool>(N, false));\n    int vi = 0, vj = 0;\n    final_visited[0][0] = true;\n    \n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                vi += DI[dir];\n                vj += DJ[dir];\n                break;\n            }\n        }\n        final_visited[vi][vj] = true;\n    }\n    \n    // If any square not visited, add detours\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!final_visited[i][j] && (int)route.length() < MAX_LEN - 2 * N) {\n                string to_sq = find_path(0, 0, i, j);\n                string back = find_path(i, j, 0, 0);\n                if (!to_sq.empty() && !back.empty()) {\n                    route = to_sq + back + route;\n                    final_visited[i][j] = true;\n                }\n            }\n        }\n    }\n    \n    // Truncate if too long\n    if ((int)route.length() > MAX_LEN) {\n        route = route.substr(0, MAX_LEN);\n        // Ensure ends at (0,0)\n        int ei = 0, ej = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    ei += DI[dir];\n                    ej += DJ[dir];\n                    break;\n                }\n            }\n        }\n        if (ei != 0 || ej != 0) {\n            string back = find_path(ei, ej, 0, 0);\n            if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n                route += back;\n            }\n        }\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<string> grid;\nvector<string> targets;\nvector<vector<pair<int, int>>> char_positions;\n\n// Calculate overlap: suffix of a matches prefix of b\nint calc_overlap(const string& a, const string& b) {\n    int max_ov = 0;\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = 1; len <= max_len; len++) {\n        if (a.substr(a.size() - len) == b.substr(0, len)) {\n            max_ov = len;\n        }\n    }\n    return max_ov;\n}\n\n// Manhattan distance\ninline int dist(pair<int, int> p1, pair<int, int> p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\n// Build solution from order\ntuple<string, vector<pair<int, int>>, int> build_solution(const vector<int>& order) {\n    string S = \"\";\n    vector<pair<int, int>> positions;\n    positions.reserve(5000);\n    pair<int, int> cur_pos = {si, sj};\n    int total_cost = 0;\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        \n        // Calculate overlap with current string end\n        int overlap_len = 0;\n        if (!S.empty()) {\n            int max_check = min((int)S.size(), (int)t.size());\n            for (int len = max_check; len >= 1; len--) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    if (S[S.size() - len + k] != t[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        // Add non-overlapping characters\n        for (int i = overlap_len; i < (int)t.size(); i++) {\n            char c = t[i];\n            int c_idx = c - 'A';\n            \n            // Find nearest position for this character\n            pair<int, int> best_pos = char_positions[c_idx][0];\n            int best_d = dist(cur_pos, best_pos);\n            \n            for (size_t k = 1; k < char_positions[c_idx].size(); k++) {\n                int d = dist(cur_pos, char_positions[c_idx][k]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_pos = char_positions[c_idx][k];\n                }\n            }\n            \n            total_cost += best_d + 1;\n            positions.push_back(best_pos);\n            S += c;\n            cur_pos = best_pos;\n        }\n    }\n    \n    return {S, positions, total_cost};\n}\n\n// Check if all targets are covered\nbool check_coverage(const string& S, const vector<string>& targets) {\n    for (const auto& t : targets) {\n        if (S.find(t) == string::npos) {\n            return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Read input\n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    grid.resize(N);\n    char_positions.resize(26);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    // Build overlap matrix\n    vector<vector<int>> overlap(M, vector<int>(M));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) {\n                overlap[i][j] = calc_overlap(targets[i], targets[j]);\n            }\n        }\n    }\n    \n    // Random number generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> best_order;\n    vector<pair<int, int>> best_positions;\n    int best_cost = INT_MAX;\n    bool found_valid = false;\n    \n    // Main optimization loop\n    int trials = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > 1800) break;\n        \n        vector<int> order;\n        vector<bool> used(M, false);\n        order.reserve(M);\n        \n        // Random start\n        uniform_int_distribution<int> dist_int(0, M - 1);\n        int start = dist_int(rng);\n        order.push_back(start);\n        used[start] = true;\n        \n        // Greedy with randomness\n        for (int step = 1; step < M; step++) {\n            vector<pair<int, int>> candidates;\n            candidates.reserve(M - step);\n            \n            int last = order.back();\n            for (int i = 0; i < M; i++) {\n                if (!used[i]) {\n                    candidates.push_back({overlap[last][i], i});\n                }\n            }\n            \n            // Sort by overlap (descending)\n            sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n                return a.first > b.first;\n            });\n            \n            // Pick from top candidates\n            int num_candidates = min((int)candidates.size(), 15);\n            uniform_int_distribution<int> pick_dist(0, num_candidates - 1);\n            int pick_idx = pick_dist(rng);\n            int next = candidates[pick_idx].second;\n            \n            order.push_back(next);\n            used[next] = true;\n        }\n        \n        // Build solution\n        auto [S, positions, cost] = build_solution(order);\n        \n        // Check coverage and update best\n        if (check_coverage(S, targets)) {\n            found_valid = true;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_order = order;\n                best_positions = positions;\n            }\n        } else if (!found_valid && (int)positions.size() < 5000) {\n            // Keep any solution that doesn't exceed operation limit\n            if (best_positions.empty() || cost < best_cost) {\n                best_cost = cost;\n                best_order = order;\n                best_positions = positions;\n            }\n        }\n        \n        trials++;\n        \n        // Local search every 20 trials\n        if (trials % 20 == 0 && !best_order.empty() && found_valid) {\n            for (int swap_trial = 0; swap_trial < 30; swap_trial++) {\n                auto ls_now = chrono::steady_clock::now();\n                auto ls_elapsed = chrono::duration_cast<chrono::milliseconds>(ls_now - start_time).count();\n                if (ls_elapsed > 1850) break;\n                \n                uniform_int_distribution<int> swap_dist(0, M - 2);\n                int pos = swap_dist(rng);\n                \n                vector<int> new_order = best_order;\n                swap(new_order[pos], new_order[pos + 1]);\n                \n                auto [S2, positions2, cost2] = build_solution(new_order);\n                \n                if (check_coverage(S2, targets) && cost2 < best_cost) {\n                    best_cost = cost2;\n                    best_order = new_order;\n                    best_positions = positions2;\n                }\n            }\n        }\n    }\n    \n    // Ensure we have a valid solution\n    if (best_positions.empty() && !best_order.empty()) {\n        auto [S, positions, cost] = build_solution(best_order);\n        best_positions = positions;\n    }\n    \n    // Fallback: simple sequential output\n    if (best_positions.empty()) {\n        pair<int, int> cur_pos = {si, sj};\n        for (int i = 0; i < M; i++) {\n            for (char c : targets[i]) {\n                int c_idx = c - 'A';\n                pair<int, int> best_pos = char_positions[c_idx][0];\n                for (auto& pos : char_positions[c_idx]) {\n                    if (dist(cur_pos, pos) < dist(cur_pos, best_pos)) {\n                        best_pos = pos;\n                    }\n                }\n                best_positions.push_back(best_pos);\n                cur_pos = best_pos;\n            }\n        }\n    }\n    \n    // Output coordinates\n    for (auto& p : best_positions) {\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 <random>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for problem data\nint N, M;\ndouble eps;\nstruct Shape {\n    int id;\n    vector<pair<int, int>> cells;\n    int max_r, max_c;\n};\nvector<Shape> shapes;\n\n// Interaction functions\nvoid query_drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n}\n\nint read_drill() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid query_divine(const vector<pair<int, int>>& pts) {\n    cout << \"q \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_divine() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid guess(const vector<pair<int, int>>& pts) {\n    cout << \"a \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_guess() {\n    int res;\n    cin >> res;\n    return res;\n}\n\n// Solver state\nvector<double> target_row_sum, target_col_sum;\nvector<int> current_pos; // r0, c0, r1, c1, ...\n\n// Evaluate loss\ndouble evaluate_loss(const vector<int>& pos) {\n    vector<int> r_sum(N, 0), c_sum(N, 0);\n    for (int k = 0; k < M; ++k) {\n        int r = pos[2 * k];\n        int c = pos[2 * k + 1];\n        const auto& shape = shapes[k];\n        for (auto& cell : shape.cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            // Bounds check technically not needed if pos is valid, but safe\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                r_sum[rr]++;\n                c_sum[cc]++;\n            }\n        }\n    }\n    double loss = 0;\n    for (int i = 0; i < N; ++i) {\n        double diff = r_sum[i] - target_row_sum[i];\n        loss += diff * diff;\n        diff = c_sum[i] - target_col_sum[i];\n        loss += diff * diff;\n    }\n    return loss;\n}\n\nint main() {\n    // Fast IO\n    cin.tie(NULL);\n    cout.tie(NULL);\n\n    // Read Input\n    if (!(cin >> N >> M >> eps)) return 0;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shapes[k].id = k;\n        shapes[k].cells.resize(d);\n        int max_r = -1, max_c = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n            max_r = max(max_r, shapes[k].cells[i].first);\n            max_c = max(max_c, shapes[k].cells[i].second);\n        }\n        shapes[k].max_r = max_r;\n        shapes[k].max_c = max_c;\n    }\n\n    // 1. Query Rows and Cols\n    target_row_sum.resize(N);\n    target_col_sum.resize(N);\n    \n    // Helper to get target sum from observation\n    auto get_target = [&](int obs, int k) {\n        double mu = k * eps;\n        double scale = 1.0 - 2.0 * eps;\n        if (abs(scale) < 1e-9) return 0.0; \n        double est = (obs - mu) / scale;\n        return max(0.0, est);\n    };\n\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_pts;\n        row_pts.reserve(N);\n        for (int j = 0; j < N; ++j) row_pts.push_back({i, j});\n        query_divine(row_pts);\n        int obs = read_divine();\n        target_row_sum[i] = get_target(obs, N);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_pts;\n        col_pts.reserve(N);\n        for (int i = 0; i < N; ++i) col_pts.push_back({i, j});\n        query_divine(col_pts);\n        int obs = read_divine();\n        target_col_sum[j] = get_target(obs, N);\n    }\n\n    // 2. Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    current_pos.resize(2 * M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = N - 1 - shapes[k].max_r;\n        int max_c = N - 1 - shapes[k].max_c;\n        // Ensure non-negative range\n        if (max_r < 0) max_r = 0;\n        if (max_c < 0) max_c = 0;\n        current_pos[2 * k] = uniform_int_distribution<>(0, max_r)(rng);\n        current_pos[2 * k + 1] = uniform_int_distribution<>(0, max_c)(rng);\n    }\n\n    double current_loss = evaluate_loss(current_pos);\n    double best_loss = current_loss;\n    vector<int> best_pos = current_pos;\n\n    double temp = 100.0;\n    double cooling_rate = 0.995;\n    auto start_time = chrono::steady_clock::now();\n    \n    // Run SA for up to 2.0 seconds\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 2.0) break;\n        \n        // Propose move\n        int k = uniform_int_distribution<>(0, M - 1)(rng);\n        int dim = uniform_int_distribution<>(0, 1)(rng); // 0 for r, 1 for c\n        int delta = uniform_int_distribution<>(-1, 1)(rng);\n        if (delta == 0) delta = 1;\n        \n        int idx = 2 * k + dim;\n        int old_val = current_pos[idx];\n        int new_val = old_val + delta;\n        \n        int max_val = N - 1 - (dim == 0 ? shapes[k].max_r : shapes[k].max_c);\n        if (new_val < 0 || new_val > max_val) continue;\n        \n        current_pos[idx] = new_val;\n        double new_loss = evaluate_loss(current_pos);\n        \n        double diff = new_loss - current_loss;\n        \n        if (diff < 0 || exp(-diff / temp) > uniform_real_distribution<>(0.0, 1.0)(rng)) {\n            current_loss = new_loss;\n            if (new_loss < best_loss) {\n                best_loss = new_loss;\n                best_pos = current_pos;\n            }\n        } else {\n            current_pos[idx] = old_val; // Revert\n        }\n        \n        temp *= cooling_rate;\n        if (temp < 1e-3) break;\n    }\n\n    // 3. Generate Prediction\n    vector<pair<int, int>> s_cand;\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        int r = best_pos[2 * k];\n        int c = best_pos[2 * k + 1];\n        for (auto& cell : shapes[k].cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                grid[rr][cc]++;\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                s_cand.push_back({i, j});\n            }\n        }\n    }\n\n    // 4. Verify Rest (Drill all cells not in s_cand)\n    // This ensures we don't miss any oil (False Negatives).\n    // False Positives in s_cand are risked but unlikely if loss is low.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 0) {\n                query_drill(i, j);\n                int v = read_drill();\n                if (v > 0) {\n                    s_cand.push_back({i, j});\n                    grid[i][j] = v;\n                }\n            }\n        }\n    }\n\n    // 5. Guess\n    // Sort s_cand for consistency\n    sort(s_cand.begin(), s_cand.end());\n    // Remove duplicates just in case (logic shouldn't produce any)\n    s_cand.erase(unique(s_cand.begin(), s_cand.end()), s_cand.end());\n    \n    guess(s_cand);\n    int res = read_guess();\n    if (res == 1) return 0;\n    \n    // If wrong, we could try to recover, but for this solution we exit.\n    // In a contest, one might fallback to drilling everything if guess fails.\n    // But we already drilled s_rest. The only error source is s_cand false positives.\n    // To fix, we would need to drill s_cand cells to check if v=0.\n    // Given time limit, we stop.\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global constants\nconst int W = 1000;\n\n// Problem data\nint D, N;\nvector<vector<int>> a; // a[d][k]\n\n// Grid dimensions\nint R, C;\n\n// State: H[d][r], W[d][c]\n// Using vector of vectors\nvector<vector<int>> H;\nvector<vector<int>> W_vec; // Renamed to W_vec to avoid conflict with constant W\n\n// Mapping from k to (r, c)\npair<int, int> get_rc(int k) {\n    return {k / C, k % C};\n}\n\n// Calculate total cost\nlong long calculate_cost() {\n    long long total_cost = 0;\n    \n    // Area costs\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                total_cost += 100LL * (a[d][k] - area);\n            }\n        }\n    }\n    \n    // Partition costs\n    for (int d = 1; d < D; ++d) {\n        // Horizontal lines\n        int y_prev = 0;\n        int y_curr = 0;\n        for (int r = 0; r < R; ++r) {\n            y_prev += H[d-1][r];\n            y_curr += H[d][r];\n            total_cost += (long long)W * abs(y_prev - y_curr);\n        }\n        // Vertical lines\n        int x_prev = 0;\n        int x_curr = 0;\n        for (int c = 0; c < C; ++c) {\n            x_prev += W_vec[d-1][c];\n            x_curr += W_vec[d][c];\n            total_cost += (long long)W * abs(x_prev - x_curr);\n        }\n    }\n    \n    return total_cost;\n}\n\n// Calculate delta cost for a change in H[d][r] or W_vec[d][c]\n// This is more efficient for SA\nlong long calculate_delta_cost(int d, int type, int idx, int delta) {\n    // type 0: H, 1: W_vec\n    long long delta_cost = 0;\n    \n    // Area cost change for day d\n    if (type == 0) { // H[d][idx] changes by delta\n        int r = idx;\n        int old_h = H[d][r];\n        int new_h = old_h + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kr == r) {\n                long long old_area = (long long)old_h * W_vec[d][kc];\n                long long new_area = (long long)new_h * W_vec[d][kc];\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    } else { // W_vec[d][idx] changes by delta\n        int c = idx;\n        int old_w = W_vec[d][c];\n        int new_w = old_w + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kc == c) {\n                long long old_area = (long long)H[d][kr] * old_w;\n                long long new_area = (long long)H[d][kr] * new_w;\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    }\n    \n    // Partition cost change\n    // Affected days: d (with d-1) and d+1 (with d)\n    // If d=0, only d+1. But L_0=0, so partition cost starts from d=1.\n    // Partition cost between d-1 and d depends on cumulative sums at d-1 and d.\n    // Changing H[d][idx] changes cumulative sums for r >= idx on day d.\n    \n    auto update_partition = [&](int day_idx, int type_p, int idx_p, int delta_p) {\n        // day_idx is the day being modified (d)\n        // We need to compare with day_idx-1 and day_idx+1\n        long long cost_change = 0;\n        \n        // Compare with day_idx - 1\n        if (day_idx > 0) {\n            int sum_prev = 0;\n            int sum_curr = 0;\n            // We only need to sum from idx_p to end because before idx_p sums are same\n            // But wait, cumulative sum at r depends on H[0]...H[r].\n            // If H[idx] changes, all cumulative sums Y_r for r > idx change.\n            // Y_idx also changes.\n            // So for all r from idx to R-1, Y_r changes by delta_p.\n            // Cost adds W * |delta_p| for each such line.\n            // Number of lines affected: R - idx_p.\n            // Wait, lines are at Y_1, ..., Y_R.\n            // Y_r = sum(H[0]...H[r-1]).\n            // If H[idx] changes, Y_r changes for r > idx.\n            // So lines Y_{idx+1} ... Y_R change.\n            // Count = R - idx.\n            // But Y_R is at W (fixed sum), so Y_R doesn't change?\n            // We enforce sum H = W. So if H[idx] += delta, some H[other] -= delta.\n            // So Y_R remains W.\n            // So lines affected are those between idx and the 'other' index.\n            // This makes delta calculation complex if we swap.\n            // Let's stick to full cost recalc for partition if needed, or simplify.\n            // Given N is small, full partition cost recalc for affected days is fast.\n            // Affected days: d-1 (boundary d-1|d) and d (boundary d|d+1).\n            // Just recalc partition cost for these two boundaries.\n        }\n        return cost_change;\n    };\n\n    // Simpler approach: Recalculate partition cost for boundaries involving day d.\n    // Boundaries: (d-1, d) and (d, d+1).\n    // Store previous partition cost for these boundaries to subtract.\n    // But implementing this cleanly is verbose.\n    // Given the speed of O(N) area calc, O(R+C) partition calc is also fast.\n    // Let's just calculate the delta for partition explicitly.\n    \n    // Partition cost contribution of day d with d-1:\n    // Sum_r W * |Y_{d,r} - Y_{d-1,r}|\n    // If H[d][idx] changes by delta, Y_{d,r} changes by delta for r > idx.\n    // (Assuming we adjust another H[d][other] to keep sum constant).\n    // If we do swap move (H[idx]+=1, H[other]-=1), then Y_r changes by 1 for r in (min, max].\n    // This is getting complicated for delta.\n    // Given 3 seconds, we can afford O(R+C) per step.\n    // Let's implement a function that recalculates partition cost for day d boundaries.\n    \n    return delta_cost; // Placeholder, will implement full delta in SA loop or use full cost for safety if fast enough\n}\n\n// Function to calculate partition cost between day d1 and d2\nlong long calc_partition_between(int d1, int d2) {\n    long long cost = 0;\n    int y1 = 0, y2 = 0;\n    for (int r = 0; r < R; ++r) {\n        y1 += H[d1][r];\n        y2 += H[d2][r];\n        cost += (long long)W * abs(y1 - y2);\n    }\n    int x1 = 0, x2 = 0;\n    for (int c = 0; c < C; ++c) {\n        x1 += W_vec[d1][c];\n        x2 += W_vec[d2][c];\n        cost += (long long)W * abs(x1 - x2);\n    }\n    return cost;\n}\n\n// Global current cost\nlong long current_cost = 0;\n\nvoid update_cost_after_change(int d, const vector<int>& old_H, const vector<int>& old_W) {\n    // Recompute area cost for day d\n    // Recompute partition cost for (d-1, d) and (d, d+1)\n    // This is O(N + R + C).\n    \n    // We need to subtract old contributions and add new.\n    // To do this cleanly, we need to store per-day costs.\n    // Let's store vector<long long> area_cost(D), partition_cost(D) (cost between d-1 and d)\n    // partition_cost[0] = 0.\n    // Total = sum(area) + sum(partition).\n}\n\n// Let's use a simpler SA structure where we just recompute necessary parts.\n// Since D is small, we can store per-day area cost and per-boundary partition cost.\nvector<long long> day_area_cost;\nvector<long long> boundary_part_cost; // size D, boundary_part_cost[d] is cost between d-1 and d. [0] is 0.\n\nvoid init_costs() {\n    day_area_cost.assign(D, 0);\n    boundary_part_cost.assign(D, 0);\n    \n    for (int d = 0; d < D; ++d) {\n        long long cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                cost += 100LL * (a[d][k] - area);\n            }\n        }\n        day_area_cost[d] = cost;\n    }\n    \n    for (int d = 1; d < D; ++d) {\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n    }\n    \n    current_cost = 0;\n    for (long long c : day_area_cost) current_cost += c;\n    for (long long c : boundary_part_cost) current_cost += c;\n}\n\nvoid apply_move_and_update(int d, int type, int idx, int delta) {\n    // Apply move\n    if (type == 0) {\n        H[d][idx] += delta;\n    } else {\n        W_vec[d][idx] += delta;\n    }\n    \n    // Update day_area_cost[d]\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    // Update boundary_part_cost[d] (between d-1 and d)\n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    // Update boundary_part_cost[d+1] (between d and d+1)\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nvoid revert_move_and_update(int d, int type, int idx, int delta) {\n    // Revert\n    if (type == 0) {\n        H[d][idx] -= delta;\n    } else {\n        W_vec[d][idx] -= delta;\n    }\n    \n    // Recalculate costs (same as apply, effectively undoing the change in values)\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int W_in;\n    if (!(cin >> W_in >> D >> N)) return 0;\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    // Determine R, C\n    // Try to find R that minimizes initial area cost heuristic\n    int best_R = 1;\n    long long min_init_cost = -1;\n    \n    for (int r_try = 1; r_try <= N; ++r_try) {\n        int c_try = (N + r_try - 1) / r_try;\n        // Heuristic cost estimate\n        // Distribute W to rows/cols based on sqrt(area)\n        long long est_cost = 0;\n        // Just pick the one closest to square\n        if (min_init_cost == -1 || abs(r_try - c_try) < abs(best_R - (N + best_R - 1) / best_R)) {\n             best_R = r_try;\n        }\n    }\n    // Prefer square-ish\n    best_R = max(1, (int)round(sqrt(N)));\n    R = best_R;\n    C = (N + R - 1) / R;\n    \n    // Initialize H and W_vec\n    H.assign(D, vector<int>(R));\n    W_vec.assign(D, vector<int>(C));\n    \n    mt19937 rng(12345);\n    \n    for (int d = 0; d < D; ++d) {\n        // Calculate target \"weight\" for each row and col\n        vector<long long> row_weight(R, 0);\n        vector<long long> col_weight(C, 0);\n        \n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            // Use sqrt of area as weight\n            long long w = (long long)sqrt(a[d][k]) + 1;\n            row_weight[r] += w;\n            col_weight[c] += w;\n        }\n        \n        long long sum_rw = accumulate(row_weight.begin(), row_weight.end(), 0LL);\n        long long sum_cw = accumulate(col_weight.begin(), col_weight.end(), 0LL);\n        \n        // Distribute W\n        int rem_h = W;\n        for (int r = 0; r < R; ++r) {\n            int h = (sum_rw == 0) ? W/R : (int)((double)row_weight[r] / sum_rw * W);\n            H[d][r] = h;\n            rem_h -= h;\n        }\n        // Distribute remainder\n        int r_idx = 0;\n        while (rem_h > 0) {\n            H[d][r_idx % R]++;\n            rem_h--;\n            r_idx++;\n        }\n        // Ensure min 1\n        for(int r=0; r<R; ++r) if(H[d][r] < 1) H[d][r] = 1;\n        // Re-normalize sum to W (simple adjust)\n        int sum_h = accumulate(H[d].begin(), H[d].end(), 0);\n        if (sum_h != W) {\n            H[d][0] += (W - sum_h);\n        }\n        \n        int rem_w = W;\n        for (int c = 0; c < C; ++c) {\n            int w = (sum_cw == 0) ? W/C : (int)((double)col_weight[c] / sum_cw * W);\n            W_vec[d][c] = w;\n            rem_w -= w;\n        }\n        int c_idx = 0;\n        while (rem_w > 0) {\n            W_vec[d][c_idx % C]++;\n            rem_w--;\n            c_idx++;\n        }\n        for(int c=0; c<C; ++c) if(W_vec[d][c] < 1) W_vec[d][c] = 1;\n        int sum_w = accumulate(W_vec[d].begin(), W_vec[d].end(), 0);\n        if (sum_w != W) {\n            W_vec[d][0] += (W - sum_w);\n        }\n    }\n    \n    init_costs();\n    \n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double T = 10000.0;\n    double T_end = 1.0;\n    double alpha = 0.99995;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break; // Leave margin\n        \n        // Pick move\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        int type = uniform_int_distribution<int>(0, 1)(rng); // 0: H, 1: W\n        int dim = (type == 0) ? R : C;\n        int idx = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        // Pick another index to swap with to maintain sum\n        int idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        while (idx2 == idx) idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 1)(rng)) delta = -1;\n        \n        // Check validity (must be >= 1)\n        if (type == 0) {\n            if (H[d][idx] + delta < 1 || H[d][idx2] - delta < 1) continue;\n        } else {\n            if (W_vec[d][idx] + delta < 1 || W_vec[d][idx2] - delta < 1) continue;\n        }\n        \n        // Apply first change\n        if (type == 0) H[d][idx] += delta;\n        else W_vec[d][idx] += delta;\n        \n        // Calculate cost delta roughly? \n        // No, let's just apply both and calc cost.\n        if (type == 0) H[d][idx2] -= delta;\n        else W_vec[d][idx2] -= delta;\n        \n        // We need to calculate new cost efficiently.\n        // Since we changed two indices, we can just recompute day_area_cost[d] and boundaries.\n        // Store old values to revert if rejected.\n        int old_val1 = (type == 0) ? H[d][idx] - delta : W_vec[d][idx] - delta;\n        int old_val2 = (type == 0) ? H[d][idx2] + delta : W_vec[d][idx2] + delta;\n        \n        long long old_day_cost = day_area_cost[d];\n        long long old_bound1 = (d > 0) ? boundary_part_cost[d] : 0;\n        long long old_bound2 = (d < D-1) ? boundary_part_cost[d+1] : 0;\n        \n        // Recompute area cost\n        long long new_area_cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                new_area_cost += 100LL * (a[d][k] - area);\n            }\n        }\n        \n        long long new_bound1 = 0, new_bound2 = 0;\n        if (d > 0) new_bound1 = calc_partition_between(d-1, d);\n        if (d < D-1) new_bound2 = calc_partition_between(d, d+1);\n        \n        long long delta_E = (new_area_cost - old_day_cost) + (new_bound1 - old_bound1) + (new_bound2 - old_bound2);\n        \n        bool accept = false;\n        if (delta_E <= 0) accept = true;\n        else {\n            double p = exp(-delta_E / T);\n            if (uniform_real_distribution<double>(0, 1)(rng) < p) accept = true;\n        }\n        \n        if (accept) {\n            current_cost += delta_E;\n            day_area_cost[d] = new_area_cost;\n            if (d > 0) boundary_part_cost[d] = new_bound1;\n            if (d < D-1) boundary_part_cost[d+1] = new_bound2;\n        } else {\n            // Revert\n            if (type == 0) {\n                H[d][idx] = old_val1;\n                H[d][idx2] = old_val2;\n            } else {\n                W_vec[d][idx] = old_val1;\n                W_vec[d][idx2] = old_val2;\n            }\n        }\n        \n        T *= alpha;\n        iter++;\n    }\n    \n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            int i_start = 0;\n            for (int i = 0; i < r; ++i) i_start += H[d][i];\n            int i_end = i_start + H[d][r];\n            \n            int j_start = 0;\n            for (int j = 0; j < c; ++j) j_start += W_vec[d][j];\n            int j_end = j_start + W_vec[d][c];\n            \n            cout << i_start << \" \" << j_start << \" \" << i_end << \" \" << j_end << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\nusing ll = long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int STAMP_SIZE = 3;\nconst int POS_LIMIT = N - STAMP_SIZE + 1; // 7\n\nll A[N][N];\nll S[M][STAMP_SIZE][STAMP_SIZE];\nll Grid[N][N];\nll CurrentScore = 0;\n\nstruct Op {\n    int m, p, q;\n};\nvector<Op> ops;\n\n// Fast random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nll get_rem(ll v) {\n    ll r = v % MOD;\n    if (r < 0) r += MOD;\n    return r;\n}\n\n// Calculate score delta if we add stamp m at (p, q) with multiplier 'delta' (+1 or -1)\n// Does not modify global state, just returns the change in score\nll calc_delta(int m, int p, int q, int delta) {\n    ll score_change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i;\n            int c = q + j;\n            ll old_val = Grid[r][c];\n            ll new_val = old_val + delta * S[m][i][j];\n            \n            // We assume Grid values are always non-negative in valid states\n            // But during calculation new_val could theoretically be negative if we remove \n            // more than added, but we only remove existing ops, so new_val >= A[r][c] >= 0.\n            \n            score_change += get_rem(new_val) - get_rem(old_val);\n        }\n    }\n    return score_change;\n}\n\n// Apply operation to Grid and update CurrentScore\nvoid apply_op(int m, int p, int q, int delta) {\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i;\n            int c = q + j;\n            ll old_val = Grid[r][c];\n            Grid[r][c] += delta * S[m][i][j];\n            ll new_val = Grid[r][c];\n            CurrentScore += get_rem(new_val) - get_rem(old_val);\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, m_in, k_in;\n    if (!(cin >> n_in >> m_in >> k_in)) return 0;\n    // n_in, m_in, k_in should match constants N, M, K but we use constants for array sizing.\n    // The problem guarantees N=9, M=20, K=81.\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n            Grid[i][j] = A[i][j];\n        }\n    }\n\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < STAMP_SIZE; ++i) {\n            for (int j = 0; j < STAMP_SIZE; ++j) {\n                cin >> S[m][i][j];\n            }\n        }\n    }\n\n    // Calculate Initial Score\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            CurrentScore += get_rem(Grid[i][j]);\n        }\n    }\n\n    // Uniform distributions\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, POS_LIMIT - 1);\n    uniform_int_distribution<int> dist_q(0, POS_LIMIT - 1);\n    uniform_int_distribution<int> dist_ops(0, 100); // For move type selection\n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n\n    // Greedy Initialization\n    // Try to add K operations greedily\n    // To speed up, we don't scan all 980 options every time if not needed, \n    // but 980 is small enough.\n    for (int step = 0; step < K; ++step) {\n        ll best_delta = -1e18; // Can be negative\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        // Sample a subset of moves to save time? \n        // 980 * 9 ops is ~9000 ops. K=81 -> 700,000 ops. Very fast.\n        // Let's do full scan for Greedy.\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < POS_LIMIT; ++p) {\n                for (int q = 0; q < POS_LIMIT; ++q) {\n                    ll d = calc_delta(m, p, q, 1);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_delta <= 0) {\n            // No improvement possible by adding more stamps\n            break;\n        }\n\n        ops.push_back({best_m, best_p, best_q});\n        apply_op(best_m, best_p, best_q, 1);\n    }\n\n    ll best_score = CurrentScore;\n    vector<Op> best_ops = ops;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    ll T_start = 1000000000LL; // 1e9\n    double time_limit = 1.900; // seconds\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= time_limit) break;\n\n        double progress = elapsed / time_limit;\n        // Linear cooling\n        ll T = (ll)(T_start * (1.0 - progress));\n        if (T < 1) T = 1;\n\n        // Decide move type\n        int move_type = dist_ops(rng);\n        bool accepted = false;\n        \n        // We need to store state to revert if rejected\n        // But since we calculate delta first, we only apply if accepted.\n        \n        if (ops.empty()) {\n            // Must Add\n            move_type = 200; // Force Add\n        } else if (ops.size() >= K) {\n            // Cannot Add\n            if (move_type < 70) move_type = 0; // Change\n            else move_type = 100; // Remove\n        }\n\n        if (move_type < 70) {\n            // Change an existing operation\n            int idx = uniform_int_distribution<int>(0, ops.size() - 1)(rng);\n            Op old_op = ops[idx];\n            \n            // Propose new op\n            int new_m = dist_m(rng);\n            int new_p = dist_p(rng);\n            int new_q = dist_q(rng);\n            \n            // Avoid null move\n            if (new_m == old_op.m && new_p == old_op.p && new_q == old_op.q) {\n                continue; \n            }\n\n            ll delta = calc_delta(new_m, new_p, new_q, 1);\n            delta += calc_delta(old_op.m, old_op.p, old_op.q, -1);\n\n            if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                // Accept\n                apply_op(old_op.m, old_op.p, old_op.q, -1);\n                apply_op(new_m, new_p, new_q, 1);\n                ops[idx] = {new_m, new_p, new_q};\n                accepted = true;\n            }\n        } else if (move_type < 85) {\n            // Add operation\n            if (ops.size() < K) {\n                int new_m = dist_m(rng);\n                int new_p = dist_p(rng);\n                int new_q = dist_q(rng);\n                \n                ll delta = calc_delta(new_m, new_p, new_q, 1);\n                if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                    apply_op(new_m, new_p, new_q, 1);\n                    ops.push_back({new_m, new_p, new_q});\n                    accepted = true;\n                }\n            }\n        } else {\n            // Remove operation\n            if (!ops.empty()) {\n                int idx = uniform_int_distribution<int>(0, ops.size() - 1)(rng);\n                Op old_op = ops[idx];\n                \n                ll delta = calc_delta(old_op.m, old_op.p, old_op.q, -1);\n                if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                    apply_op(old_op.m, old_op.p, old_op.q, -1);\n                    // Remove from vector efficiently (swap with back and pop)\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                    accepted = true;\n                }\n            }\n        }\n\n        if (CurrentScore > best_score) {\n            best_score = CurrentScore;\n            best_ops = ops;\n        }\n        \n        iter++;\n    }\n\n    // Output\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 <queue>\n#include <algorithm>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction helpers\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar dchar[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int id;\n    int r, c;\n    int holding; // -1 if empty, else container ID\n    bool is_large;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    Crane cranes[N];\n    vector<int> inputs[N]; // Queues of containers to arrive at each row\n    int input_idx[N]; // Next index to arrive\n    int next_dispatch[N]; // Next expected container ID for each dispatch gate\n    vector<int> dispatched[N]; // List of dispatched IDs for inversion check (not strictly needed for logic but good for debug)\n    int total_dispatched;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = -1;\n            cranes[i].id = i;\n            cranes[i].r = i;\n            cranes[i].c = 0;\n            cranes[i].holding = -1;\n            cranes[i].is_large = (i == 0);\n            input_idx[i] = 0;\n            next_dispatch[i] = i * N;\n            total_dispatched = 0;\n        }\n    }\n};\n\nclass Solver {\n    State state;\n    vector<string> ans;\n    int turn;\n    bool finished;\n\npublic:\n    Solver(const vector<vector<int>>& A) {\n        ans.resize(N);\n        turn = 0;\n        finished = false;\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                state.inputs[i].push_back(A[i][j]);\n            }\n        }\n    }\n\n    void receive_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.input_idx[i] < N) {\n                // Check condition: neither a container nor a crane holding a container at that square\n                bool has_container = (state.grid[i][0] != -1);\n                bool crane_holding = false;\n                // Check if any crane is at (i,0) holding a container\n                // Actually, cranes are unique per square.\n                // We need to find if the crane at (i,0) is holding.\n                // Iterate cranes to find one at (i,0)\n                int crane_at_sq = -1;\n                for(int k=0; k<N; ++k) {\n                    if(state.cranes[k].r == i && state.cranes[k].c == 0) {\n                        crane_at_sq = k;\n                        break;\n                    }\n                }\n                if(crane_at_sq != -1 && state.cranes[crane_at_sq].holding != -1) {\n                    crane_holding = true;\n                }\n\n                if(!has_container && !crane_holding) {\n                    state.grid[i][0] = state.inputs[i][state.input_idx[i]];\n                    state.input_idx[i]++;\n                }\n            }\n        }\n    }\n\n    void dispatch_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.grid[i][N-1] != -1) {\n                int cid = state.grid[i][N-1];\n                // Dispatch immediately\n                state.grid[i][N-1] = -1;\n                state.dispatched[i].push_back(cid);\n                state.total_dispatched++;\n                // Update next_dispatch only if correct order\n                // Actually next_dispatch is just a counter for expected ID\n                // We don't stop dispatching, but score penalizes wrong ID\n                // For our strategy, we ensure we only place correct ID there.\n                // But if somehow wrong ID is there, it dispatches.\n                // We assume our logic prevents wrong ID placement.\n                if(cid == state.next_dispatch[i]) {\n                    state.next_dispatch[i]++;\n                }\n            }\n        }\n    }\n\n    bool is_valid_move(int crane_idx, int nr, int nc, const vector<pair<int,int>>& planned_next) {\n        if(nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n        \n        // Check collision with other cranes' next positions\n        for(int k=0; k<crane_idx; ++k) {\n            if(planned_next[k].first == nr && planned_next[k].second == nc) return false; // Vertex collision\n            // Swap collision\n            if(planned_next[k].first == state.cranes[crane_idx].r && planned_next[k].second == state.cranes[crane_idx].c) {\n                if(nr == state.cranes[k].r && nc == state.cranes[k].c) return false;\n            }\n        }\n        // Check collision with future cranes' current positions?\n        // Sequential planning handles future cranes by treating their current pos as obstacle \n        // UNLESS they move away.\n        // But simpler: treat all other cranes' current pos as obstacles unless they move.\n        // Since we plan sequentially, we don't know future moves yet.\n        // Safe bet: Treat all other cranes' current pos as obstacles.\n        // Exception: If we move into a square vacated by a previously planned crane (handled by planned_next check).\n        // What about cranes k > crane_idx? They haven't planned yet.\n        // We must not move into their current square.\n        for(int k=crane_idx+1; k<N; ++k) {\n            if(state.cranes[k].r == nr && state.cranes[k].c == nc) return false;\n        }\n        \n        return true;\n    }\n\n    // Check small crane constraint: dest must not have container if carrying\n    bool is_valid_cell_for_carrying(int crane_idx, int r, int c) {\n        if(state.cranes[crane_idx].holding == -1) return true;\n        if(state.cranes[crane_idx].is_large) return true;\n        // Small crane carrying\n        if(state.grid[r][c] != -1) return false;\n        return true;\n    }\n\n    void solve() {\n        while(turn < MAX_TURNS && state.total_dispatched < N*N) {\n            turn++;\n            receive_containers();\n            \n            // Plan moves\n            vector<char> moves(N, '.');\n            vector<pair<int,int>> planned_next(N);\n            for(int i=0; i<N; ++i) planned_next[i] = {state.cranes[i].r, state.cranes[i].c};\n\n            // Task Assignment & Movement\n            // Prioritize:\n            // 1. Dispatching (if holding correct item at gate) -> Q\n            // 2. Moving to Gate (if holding correct item for gate)\n            // 3. Picking up from Input\n            // 4. Moving to Buffer\n            // 5. Moving empty to help\n            \n            // We will determine action for each crane sequentially\n            // To avoid complex global optimization, use greedy heuristic per crane\n            \n            for(int i=0; i<N; ++i) {\n                Crane &cr = state.cranes[i];\n                int best_action = -1; // 0:. 1:U 2:D 3:L 4:R 5:P 6:Q 7:B\n                int best_score = -1e9;\n                int nr = cr.r, nc = cr.c;\n                char move_char = '.';\n\n                // Helper to evaluate a move\n                auto try_move = [&](int tr, int tc, char ch) {\n                    if(!is_valid_move(i, tr, tc, planned_next)) return;\n                    if(!is_valid_cell_for_carrying(i, tr, tc)) return;\n                    \n                    int score = 0;\n                    \n                    // Heuristic scoring\n                    // If holding container\n                    if(cr.holding != -1) {\n                        int target_row = cr.holding / N;\n                        int dist_to_gate = abs(tr - target_row) + abs(tc - (N-1));\n                        \n                        // High priority if at gate and correct ID\n                        if(tr == target_row && tc == N-1) {\n                            if(cr.holding == state.next_dispatch[target_row]) {\n                                score += 10000; // Must dispatch\n                            }\n                        }\n                        \n                        // Prefer moving towards gate\n                        score -= dist_to_gate;\n                        \n                        // Small crane penalty for congestion (hard to estimate locally)\n                    } else {\n                        // Empty\n                        // Prefer going to Input gates with pending containers\n                        int min_dist_input = 1000;\n                        for(int r=0; r<N; ++r) {\n                            if(state.input_idx[r] < N) {\n                                // Check if container is there\n                                if(state.grid[r][0] != -1) {\n                                    int d = abs(tr - r) + abs(tc - 0);\n                                    if(d < min_dist_input) min_dist_input = d;\n                                }\n                            }\n                        }\n                        score -= min_dist_input * 2;\n                        \n                        // Also prefer going to buffers with containers destined for dispatch\n                        // (Large crane logic)\n                        if(cr.is_large) {\n                            // Look for containers in Cols 1-3\n                            int min_dist_buffer = 1000;\n                            for(int r=0; r<N; ++r) {\n                                for(int c=1; c<N-1; ++c) {\n                                    if(state.grid[r][c] != -1) {\n                                        int cid = state.grid[r][c];\n                                        int t_row = cid / N;\n                                        // If this container is next for its gate, prioritize\n                                        if(cid == state.next_dispatch[t_row]) {\n                                            int d = abs(tr - r) + abs(tc - c);\n                                            // Bonus if close to gate\n                                            score += 500 - d; \n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if(score > best_score) {\n                        best_score = score;\n                        nr = tr; nc = tc;\n                        move_char = ch;\n                        // Check if P or Q is better\n                        // P\n                        if(ch == '.') {\n                             if(cr.holding == -1 && state.grid[cr.r][cr.c] != -1) {\n                                 // Can Pick\n                                 // Score based on container value\n                                 int cid = state.grid[cr.r][cr.c];\n                                 int t_row = cid / N;\n                                 if(cid == state.next_dispatch[t_row]) score += 2000;\n                                 else score += 100;\n                                 if(score > best_score) {\n                                     best_score = score;\n                                     move_char = 'P';\n                                     // nr, nc same\n                                 }\n                             }\n                             // Q\n                             if(cr.holding != -1 && state.grid[cr.r][cr.c] == -1) {\n                                 // Can Place\n                                 int t_row = cr.holding / N;\n                                 if(cr.r == t_row && cr.c == N-1) {\n                                     if(cr.holding == state.next_dispatch[t_row]) score += 5000;\n                                     else score -= 1000; // Wrong gate\n                                 } else if (cr.c >= 1 && cr.c <= 3) {\n                                     score += 10; // Buffer\n                                 }\n                                 if(score > best_score) {\n                                     best_score = score;\n                                     move_char = 'Q';\n                                 }\n                             }\n                        }\n                    }\n                };\n\n                // Try all moves\n                try_move(cr.r, cr.c, '.');\n                for(int d=0; d<4; ++d) try_move(cr.r + dr[d], cr.c + dc[d], dchar[d]);\n\n                // Apply best move\n                moves[i] = move_char;\n                planned_next[i] = {nr, nc}; // Note: if P/Q, pos doesn't change\n                if(move_char != 'P' && move_char != 'Q' && move_char != '.') {\n                    planned_next[i] = {nr, nc};\n                } else {\n                    planned_next[i] = {cr.r, cr.c};\n                }\n            }\n\n            // Execute moves and update state\n            for(int i=0; i<N; ++i) {\n                ans[i] += moves[i];\n                Crane &cr = state.cranes[i];\n                char m = moves[i];\n                \n                if(m == 'P') {\n                    cr.holding = state.grid[cr.r][cr.c];\n                    state.grid[cr.r][cr.c] = -1;\n                } else if(m == 'Q') {\n                    state.grid[cr.r][cr.c] = cr.holding;\n                    cr.holding = -1;\n                } else if(m == 'U') {\n                    cr.r--;\n                } else if(m == 'D') {\n                    cr.r++;\n                } else if(m == 'L') {\n                    cr.c--;\n                } else if(m == 'R') {\n                    cr.c++;\n                }\n                // '.' and 'B' (not using B)\n            }\n\n            dispatch_containers();\n            \n            if(turn >= MAX_TURNS) break;\n        }\n        \n        // Pad if needed? Problem says shorter strings padded by system.\n        // But we should ensure we don't output empty strings if possible.\n        // If loop didn't run, fill with '.'\n        for(int i=0; i<N; ++i) {\n            if(ans[i].empty()) ans[i] = \".\";\n        }\n    }\n\n    void print_ans() {\n        for(int i=0; i<N; ++i) {\n            cout << ans[i] << endl;\n        }\n    }\n};\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.print_ans();\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <string>\n#include <cstdlib>\n\nusing namespace std;\n\n// Structure to represent grid coordinates\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Coord& o) const { return !(*this == o); }\n};\n\n// Manhattan distance between two coordinates\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint N;\nint h[25][25];\nvector<Coord> sources;\nvector<Coord> sinks;\n\n// Flow targets for each source cell: list of {sink_coord, amount}\nstruct FlowTarget {\n    Coord sink;\n    int amount;\n};\nvector<FlowTarget> source_flows[25][25];\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\n    // Read input and identify sources (h > 0) and sinks (h < 0)\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    // Working copy of heights to track remaining supply/demand\n    int cur_h[25][25];\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            cur_h[i][j] = h[i][j];\n    \n    // Indices of active sources and sinks\n    vector<int> src_idx(sources.size());\n    iota(src_idx.begin(), src_idx.end(), 0);\n    vector<int> snk_idx(sinks.size());\n    iota(snk_idx.begin(), snk_idx.end(), 0);\n\n    // Greedy Flow Calculation\n    // Repeatedly pick the pair (source, sink) with minimum distance and transfer soil.\n    // This approximates the Minimum Cost Flow / Earth Mover's Distance.\n    while (!src_idx.empty() && !snk_idx.empty()) {\n        int s_choice = -1;\n        int k_choice = -1;\n        int min_d = 1e9;\n\n        // Find the pair with minimum Manhattan distance\n        for (int s : src_idx) {\n            for (int k : snk_idx) {\n                int d = dist(sources[s], sinks[k]);\n                if (d < min_d) {\n                    min_d = d;\n                    s_choice = s;\n                    k_choice = k;\n                }\n            }\n        }\n        \n        if (s_choice == -1) break;\n\n        Coord u = sources[s_choice];\n        Coord v = sinks[k_choice];\n        // Transfer as much as possible\n        int amount = min(cur_h[u.r][u.c], -cur_h[v.r][v.c]);\n        \n        source_flows[u.r][u.c].push_back({v, amount});\n        \n        cur_h[u.r][u.c] -= amount;\n        cur_h[v.r][v.c] += amount;\n        \n        // Remove exhausted source or sink from active lists\n        if (cur_h[u.r][u.c] == 0) {\n            for(int i=0; i<src_idx.size(); ++i) {\n                if(src_idx[i] == s_choice) {\n                    src_idx[i] = src_idx.back();\n                    src_idx.pop_back();\n                    break;\n                }\n            }\n        }\n        if (cur_h[v.r][v.c] == 0) {\n            for(int i=0; i<snk_idx.size(); ++i) {\n                if(snk_idx[i] == k_choice) {\n                    snk_idx[i] = snk_idx.back();\n                    snk_idx.pop_back();\n                    break;\n                }\n            }\n        }\n    }\n\n    vector<string> ops;\n    Coord cur = {0, 0}; // Truck starts at (0,0)\n\n    // List of sources that have soil to transport\n    vector<Coord> active_sources;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!source_flows[i][j].empty()) {\n                active_sources.push_back({i, j});\n            }\n        }\n    }\n\n    // Order sources using Nearest Neighbor heuristic to minimize empty travel\n    vector<bool> visited_source(active_sources.size(), false);\n    int sources_remaining = active_sources.size();\n\n    while (sources_remaining > 0) {\n        int best_idx = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < active_sources.size(); ++i) {\n            if (!visited_source[i]) {\n                int d = dist(cur, active_sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n        }\n\n        if (best_idx == -1) break;\n\n        Coord u = active_sources[best_idx];\n        visited_source[best_idx] = true;\n        sources_remaining--;\n\n        // Move truck to source u\n        while (cur != u) {\n            if (cur.r < u.r) { cur.r++; ops.push_back(\"D\"); }\n            else if (cur.r > u.r) { cur.r--; ops.push_back(\"U\"); }\n            else if (cur.c < u.c) { cur.c++; ops.push_back(\"R\"); }\n            else if (cur.c > u.c) { cur.c--; ops.push_back(\"L\"); }\n        }\n\n        // Calculate total load to pick up at u\n        int total_load = 0;\n        for (auto& flow : source_flows[u.r][u.c]) {\n            total_load += flow.amount;\n        }\n\n        // Load soil\n        ops.push_back(\"+\" + to_string(total_load));\n\n        // Visit assigned sinks for this source\n        // Order sinks using Nearest Neighbor to minimize loaded travel\n        vector<FlowTarget> targets = source_flows[u.r][u.c];\n        vector<bool> visited_target(targets.size(), false);\n        int targets_remaining = targets.size();\n\n        while (targets_remaining > 0) {\n            int best_t = -1;\n            int min_td = 1e9;\n            for (int i = 0; i < targets.size(); ++i) {\n                if (!visited_target[i]) {\n                    int d = dist(cur, targets[i].sink);\n                    if (d < min_td) {\n                        min_td = d;\n                        best_t = i;\n                    }\n                }\n            }\n            \n            Coord v = targets[best_t].sink;\n            // Move truck to sink v\n            while (cur != v) {\n                if (cur.r < v.r) { cur.r++; ops.push_back(\"D\"); }\n                else if (cur.r > v.r) { cur.r--; ops.push_back(\"U\"); }\n                else if (cur.c < v.c) { cur.c++; ops.push_back(\"R\"); }\n                else if (cur.c > v.c) { cur.c--; ops.push_back(\"L\"); }\n            }\n\n            // Unload soil\n            int amt = targets[best_t].amount;\n            ops.push_back(\"-\" + to_string(amt));\n            \n            visited_target[best_t] = true;\n            targets_remaining--;\n        }\n    }\n\n    // Output the sequence of operations\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 <cmath>\n#include <random>\n#include <set>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n    \n    int seed_count = 2 * N * (N - 1); // 60 seeds\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    \n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    for (int turn = 0; turn < T; turn++) {\n        // Calculate total value for each seed\n        vector<int> seed_value(seed_count, 0);\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                seed_value[i] += X[i][j];\n            }\n        }\n        \n        // Find best seed for each dimension\n        vector<int> best_for_dim(M, -1);\n        for (int d = 0; d < M; d++) {\n            int best_val = -1;\n            for (int i = 0; i < seed_count; i++) {\n                if (X[i][d] > best_val) {\n                    best_val = X[i][d];\n                    best_for_dim[d] = i;\n                }\n            }\n        }\n        \n        // Select seeds to plant: prioritize high-value seeds and dimension specialists\n        vector<pair<int, int>> seed_score; // (score, seed_index)\n        for (int i = 0; i < seed_count; i++) {\n            int score = seed_value[i];\n            // Bonus for being best in any dimension\n            for (int d = 0; d < M; d++) {\n                if (best_for_dim[d] == i) {\n                    score += 50; // Dimension specialist bonus\n                }\n            }\n            seed_score.push_back({score, i});\n        }\n        \n        // Sort by score descending\n        sort(seed_score.begin(), seed_score.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        \n        // Select top 36 seeds\n        vector<int> selected;\n        set<int> selected_set;\n        for (int i = 0; i < seed_count && selected.size() < N * N; i++) {\n            if (selected_set.find(seed_score[i].second) == selected_set.end()) {\n                selected.push_back(seed_score[i].second);\n                selected_set.insert(seed_score[i].second);\n            }\n        }\n        \n        // Ensure we cover all dimension specialists\n        for (int d = 0; d < M; d++) {\n            if (selected_set.find(best_for_dim[d]) == selected_set.end() && selected.size() < N * N) {\n                selected.push_back(best_for_dim[d]);\n                selected_set.insert(best_for_dim[d]);\n            }\n        }\n        \n        // If still not enough (shouldn't happen), fill randomly\n        for (int i = 0; i < seed_count && selected.size() < N * N; i++) {\n            if (selected_set.find(i) == selected_set.end()) {\n                selected.push_back(i);\n                selected_set.insert(i);\n            }\n        }\n        \n        // Arrange seeds in grid to maximize adjacency between complementary seeds\n        // Strategy: Place high-value seeds in center, dimension specialists on edges\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        vector<bool> used(selected.size(), false);\n        \n        // Sort selected by value for placement priority\n        vector<pair<int, int>> selected_by_value;\n        for (int i = 0; i < selected.size(); i++) {\n            selected_by_value.push_back({seed_value[selected[i]], i});\n        }\n        sort(selected_by_value.begin(), selected_by_value.end(), greater<pair<int,int>>());\n        \n        // Place seeds in spiral pattern from center for better mixing\n        vector<pair<int, int>> positions;\n        int cx = N / 2, cy = N / 2;\n        \n        // Generate spiral positions from center\n        for (int layer = 0; layer <= N / 2; layer++) {\n            // Top row (right to left)\n            for (int j = N - 1 - layer; j >= layer; j--) {\n                if (layer <= N - 1 - layer) positions.push_back({layer, j});\n            }\n            // Left column (top to bottom)\n            for (int i = layer + 1; i <= N - 1 - layer; i++) {\n                positions.push_back({i, layer});\n            }\n            // Bottom row (left to right)\n            if (N - 1 - layer > layer) {\n                for (int j = layer + 1; j <= N - 1 - layer; j++) {\n                    positions.push_back({N - 1 - layer, j});\n                }\n            }\n            // Right column (bottom to top)\n            if (N - 1 - layer > layer) {\n                for (int i = N - 2 - layer; i > layer; i--) {\n                    positions.push_back({i, N - 1 - layer});\n                }\n            }\n        }\n        \n        // Trim positions to N*N\n        while (positions.size() > N * N) positions.pop_back();\n        \n        // Place seeds: high-value in center, ensure dimension specialists are well-placed\n        // First, identify dimension specialists in selected\n        vector<int> dim_specialists;\n        for (int d = 0; d < M; d++) {\n            if (selected_set.count(best_for_dim[d])) {\n                dim_specialists.push_back(best_for_dim[d]);\n            }\n        }\n        \n        // Create a mapping from seed index to position in selected\n        vector<int> seed_to_selected_idx(seed_count, -1);\n        for (int i = 0; i < selected.size(); i++) {\n            seed_to_selected_idx[selected[i]] = i;\n        }\n        \n        // Place seeds with good distribution\n        vector<int> placement_order;\n        \n        // Add dimension specialists first (spread them out)\n        for (int ds : dim_specialists) {\n            int idx = seed_to_selected_idx[ds];\n            if (!used[idx]) {\n                placement_order.push_back(idx);\n                used[idx] = true;\n            }\n        }\n        \n        // Add remaining high-value seeds\n        for (auto& p : selected_by_value) {\n            if (!used[p.second]) {\n                placement_order.push_back(p.second);\n                used[p.second] = true;\n            }\n        }\n        \n        // Fill grid\n        int pos_idx = 0;\n        for (int idx : placement_order) {\n            if (pos_idx < positions.size()) {\n                A[positions[pos_idx].first][positions[pos_idx].second] = selected[idx];\n                pos_idx++;\n            }\n        }\n        \n        // Fill any remaining positions\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (A[i][j] == -1) {\n                    // Find any unused seed\n                    for (int k = 0; k < selected.size(); k++) {\n                        if (!used[k]) {\n                            A[i][j] = selected[k];\n                            used[k] = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output the grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n    bool operator<(const Point& o) const {\n        if (x != o.x) return x < o.x;\n        return y < o.y;\n    }\n};\n\nint dist(Point a, Point b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> S(N), T(N);\n    for (int i = 0; i < N; i++) cin >> S[i];\n    for (int i = 0; i < N; i++) cin >> T[i];\n    \n    vector<Point> sources, targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (S[i][j] == '1') sources.push_back({i, j});\n            if (T[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n    \n    // Design arm: star topology with varying edge lengths\n    int V_prime = min(V, (int)sources.size() + 1);\n    if (V_prime < 2) V_prime = 2;\n    int num_fingertips = V_prime - 1;\n    \n    cout << V_prime << \"\\n\";\n    vector<int> edge_len(V_prime, 0);\n    for (int i = 1; i < V_prime; i++) {\n        edge_len[i] = (i - 1) % (N - 1) + 1;\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Find good initial root position (center of sources)\n    int sum_x = 0, sum_y = 0;\n    for (auto& p : sources) {\n        sum_x += p.x;\n        sum_y += p.y;\n    }\n    int root_x = sum_x / M;\n    int root_y = sum_y / M;\n    root_x = max(0, min(N - 1, root_x));\n    root_y = max(0, min(N - 1, root_y));\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Grid state tracking\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = (S[i][j] == '1' ? 1 : 0);\n        }\n    }\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            is_target[i][j] = (T[i][j] == '1' ? 1 : 0);\n        }\n    }\n    \n    // Fingertip state\n    vector<int> fp_dir(num_fingertips, 0);  // 0:R, 1:D, 2:L, 3:U\n    vector<bool> fp_holding(num_fingertips, false);\n    \n    auto get_fp_pos = [&](int fp_idx) -> Point {\n        int d = fp_dir[fp_idx];\n        return {root_x + DX[d] * edge_len[fp_idx + 1], \n                root_y + DY[d] * edge_len[fp_idx + 1]};\n    };\n    \n    auto in_bounds = [&](Point p) -> bool {\n        return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n    };\n    \n    auto can_pick = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 1;\n    };\n    \n    auto can_place = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 0;\n    };\n    \n    vector<string> commands;\n    int turns = 0;\n    int delivered = 0;\n    \n    // Create source-target matching (greedy by distance)\n    vector<bool> src_used(sources.size(), false);\n    vector<bool> tgt_used(targets.size(), false);\n    vector<pair<int, int>> pairs;\n    \n    for (int iter = 0; iter < M; iter++) {\n        int best_si = -1, best_ti = -1, best_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); i++) {\n            if (src_used[i]) continue;\n            for (int j = 0; j < (int)targets.size(); j++) {\n                if (tgt_used[j]) continue;\n                int d = dist(sources[i], targets[j]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_si = i;\n                    best_ti = j;\n                }\n            }\n        }\n        if (best_si >= 0) {\n            src_used[best_si] = true;\n            tgt_used[best_ti] = true;\n            pairs.push_back({best_si, best_ti});\n        }\n    }\n    \n    // Process pairs using multiple fingertips in parallel\n    int pair_idx = 0;\n    vector<int> fp_task(num_fingertips, -1);  // Which pair each fingertip is handling\n    \n    while ((pair_idx < (int)pairs.size() || \n           count(fp_task.begin(), fp_task.end(), -1) < num_fingertips) && \n           turns < 99000) {\n        \n        string cmd(V_prime * 2, '.');\n        bool action_taken = false;\n        \n        // Assign new tasks to idle fingertips\n        for (int fp = 0; fp < num_fingertips && pair_idx < (int)pairs.size(); fp++) {\n            if (fp_task[fp] == -1 && !fp_holding[fp]) {\n                fp_task[fp] = pair_idx++;\n            }\n        }\n        \n        // Process each fingertip\n        for (int fp = 0; fp < num_fingertips; fp++) {\n            if (fp_task[fp] == -1) continue;\n            \n            int si = pairs[fp_task[fp]].first;\n            int ti = pairs[fp_task[fp]].second;\n            Point src = sources[si];\n            Point tgt = targets[ti];\n            \n            if (!fp_holding[fp]) {\n                // Need to pick up from source\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == src && can_pick(src)) {\n                    // Pick up\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = true;\n                    grid[src.x][src.y] = 0;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach source\n                    int target_rx = src.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = src.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == src.x && ty == src.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            } else {\n                // Need to deliver to target\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == tgt && can_place(tgt) && is_target[tgt.x][tgt.y]) {\n                    // Place\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = false;\n                    grid[tgt.x][tgt.y] = 1;\n                    fp_task[fp] = -1;\n                    delivered++;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach target\n                    int target_rx = tgt.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = tgt.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == tgt.x && ty == tgt.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            }\n        }\n        \n        // If no fingertips active, try to activate more\n        if (!action_taken) {\n            bool found = false;\n            for (int fp = 0; fp < num_fingertips && !found; fp++) {\n                if (fp_task[fp] == -1 && pair_idx < (int)pairs.size()) {\n                    fp_task[fp] = pair_idx++;\n                    found = true;\n                }\n            }\n            if (!found) break;\n            continue;\n        }\n        \n        commands.push_back(cmd);\n        turns++;\n    }\n    \n    // Output all commands\n    for (const string& c : commands) {\n        cout << c << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int CELL_SIZE = 500;\nconst int GW = MAX_COORD / CELL_SIZE; // 200\nconst int GH = MAX_COORD / CELL_SIZE; // 200\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\n\nstruct Point {\n    int x, y;\n};\n\nstruct GridCell {\n    int m; // mackerels\n    int s; // sardines\n    int score() const { return m - s; }\n};\n\nGridCell grid[GH][GW];\nbool selected[GH][GW];\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {0, 0, -1, 1};\nconst int DY[4] = {-1, 1, 0, 0};\n\n// For polygon extraction\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    bool operator==(const Edge& other) const {\n        return x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2;\n    }\n};\n\n// Priority Queue Element for Growth\nstruct PQElement {\n    int r, c;\n    int score;\n    bool operator<(const PQElement& other) const {\n        return score < other.score; // Max heap\n    }\n};\n\n// Function to check if a point is inside the polygon\n// Ray casting algorithm\nbool isInside(const vector<Point>& poly, int px, int py) {\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        \n        // Check if point is on the edge\n        // Since edges are orthogonal, check if point lies on segment\n        if (xi == xj && px == xi && py >= min(yi, yj) && py <= max(yi, yj)) return true;\n        if (yi == yj && py == yi && px >= min(xi, xj) && px <= max(xi, xj)) return true;\n\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score\nlong long calculateScore(const vector<Point>& poly, const vector<Point>& mackerels, const vector<Point>& sardines) {\n    long long a = 0;\n    long long b = 0;\n    for (const auto& p : mackerels) {\n        if (isInside(poly, p.x, p.y)) a++;\n    }\n    for (const auto& p : sardines) {\n        if (isInside(poly, p.x, p.y)) b++;\n    }\n    return a - b + 1;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<Point> mackerels(N);\n    vector<Point> sardines(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    // Initialize grid\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            grid[r][c] = {0, 0};\n            selected[r][c] = false;\n        }\n    }\n\n    // Populate grid\n    for (const auto& p : mackerels) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].m++;\n        }\n    }\n    for (const auto& p : sardines) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].s++;\n        }\n    }\n\n    // Find best starting cell\n    int best_r = 0, best_c = 0;\n    int best_score = -1e9;\n    \n    // We want to start with a cell that has mackerels\n    bool found_positive = false;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            int sc = grid[r][c].score();\n            if (sc > best_score) {\n                best_score = sc;\n                best_r = r;\n                best_c = c;\n            }\n            if (sc > 0) found_positive = true;\n        }\n    }\n\n    // If no positive score cell, find one with at least 1 mackerel\n    if (!found_positive) {\n        best_score = -1e9;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                if (grid[r][c].m > 0) {\n                    int sc = grid[r][c].score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n        }\n    }\n\n    // Grow region\n    priority_queue<PQElement> pq;\n    selected[best_r][best_c] = true;\n    \n    // Add neighbors of start cell\n    for (int i = 0; i < 4; ++i) {\n        int nr = best_r + DY[i];\n        int nc = best_c + DX[i];\n        if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc]) {\n            pq.push({nr, nc, grid[nr][nc].score()});\n        }\n    }\n    // Mark added to PQ to avoid duplicates? \n    // A cell can be neighbor to multiple selected cells. \n    // We can use a 'in_pq' array or just check 'selected' when popping.\n    // To avoid duplicates in PQ, we can use a visited_pq array.\n    vector<vector<bool>> in_pq(GH, vector<bool>(GW, false));\n    for (int i = 0; i < 4; ++i) {\n        int nr = best_r + DY[i];\n        int nc = best_c + DX[i];\n        if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc]) {\n            in_pq[nr][nc] = true;\n        }\n    }\n\n    long long current_perimeter = 4LL * CELL_SIZE; // Initial rectangle\n\n    while (!pq.empty()) {\n        PQElement top = pq.top();\n        pq.pop();\n\n        int r = top.r;\n        int c = top.c;\n\n        if (selected[r][c]) continue;\n\n        // Estimate perimeter change\n        // Adding a cell adds 4 sides, removes 2 * shared_edges\n        int shared = 0;\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                shared++;\n            }\n        }\n        long long new_perimeter = current_perimeter + 4LL * CELL_SIZE - 2LL * shared * CELL_SIZE;\n\n        if (new_perimeter > MAX_PERIMETER - 1000) { // Leave some margin\n            // Don't add, but continue to check other candidates?\n            // Since PQ is sorted by score, if this one is too big, smaller ones might fit?\n            // But perimeter depends on shape. \n            // For simplicity, if this addition exceeds limit, skip it.\n            continue;\n        }\n\n        selected[r][c] = true;\n        current_perimeter = new_perimeter;\n\n        // Add neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc] && !in_pq[nr][nc]) {\n                in_pq[nr][nc] = true;\n                pq.push({nr, nc, grid[nr][nc].score()});\n            }\n        }\n    }\n\n    // Extract Polygon\n    vector<Edge> edges;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                // Check 4 edges\n                // Top\n                if (r == 0 || !selected[r-1][c]) {\n                    edges.push_back({c * CELL_SIZE, r * CELL_SIZE, (c + 1) * CELL_SIZE, r * CELL_SIZE});\n                }\n                // Bottom\n                if (r == GH - 1 || !selected[r+1][c]) {\n                    edges.push_back({c * CELL_SIZE, (r + 1) * CELL_SIZE, (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE});\n                }\n                // Left\n                if (c == 0 || !selected[r][c-1]) {\n                    edges.push_back({c * CELL_SIZE, r * CELL_SIZE, c * CELL_SIZE, (r + 1) * CELL_SIZE});\n                }\n                // Right\n                if (c == GW - 1 || !selected[r][c+1]) {\n                    edges.push_back({(c + 1) * CELL_SIZE, r * CELL_SIZE, (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE});\n                }\n            }\n        }\n    }\n\n    // Link edges to form polygon\n    // Map start point to edge index\n    map<pair<int, int>, int> start_to_edge;\n    for (int i = 0; i < edges.size(); ++i) {\n        start_to_edge[{edges[i].x1, edges[i].y1}] = i;\n    }\n\n    vector<Point> poly;\n    if (!edges.empty()) {\n        int curr = 0;\n        while (true) {\n            poly.push_back({edges[curr].x1, edges[curr].y1});\n            int next_idx = -1;\n            // Find edge starting at edges[curr].x2, edges[curr].y2\n            // Since it's a closed loop, one edge must start where this one ends\n            // However, due to integer coordinates, exact match is expected\n            auto it = start_to_edge.find({edges[curr].x2, edges[curr].y2});\n            if (it != start_to_edge.end()) {\n                next_idx = it->second;\n            }\n            \n            if (next_idx == -1 || next_idx == 0) break; // Should not happen for valid polygon\n            // To avoid infinite loop if logic is flawed, check if we returned to start\n            if (edges[next_idx].x1 == edges[0].x1 && edges[next_idx].y1 == edges[0].y1) {\n                 // We completed the loop, but we added the start point of next edge which is end of curr\n                 // The loop condition handles adding points.\n                 // We need to add the last point manually or rely on loop closure\n                 break;\n            }\n            curr = next_idx;\n        }\n        // Add the last point to close the loop\n        if (!poly.empty()) {\n             poly.push_back({edges[curr].x2, edges[curr].y2});\n        }\n    }\n\n    // Remove collinear vertices\n    vector<Point> simplified;\n    if (poly.size() >= 3) {\n        simplified.push_back(poly[0]);\n        for (size_t i = 1; i < poly.size() - 1; ++i) {\n            Point p1 = simplified.back();\n            Point p2 = poly[i];\n            Point p3 = poly[i+1];\n            // Check if p1, p2, p3 are collinear\n            // For orthogonal polygon, check if x's are same or y's are same\n            bool collinear = false;\n            if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n            if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n            \n            if (!collinear) {\n                simplified.push_back(p2);\n            }\n        }\n        simplified.push_back(poly.back());\n        \n        // Check if first and last are collinear with second and second-last\n        // Since it's a loop, we should check wrap-around\n        // But simpler: just remove duplicates at ends if any\n        if (simplified.size() > 3) {\n             Point p1 = simplified[simplified.size()-2];\n             Point p2 = simplified.back();\n             Point p3 = simplified[0];\n             bool collinear = false;\n             if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n             if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n             if (collinear) {\n                 simplified.pop_back();\n                 // Also check start\n                 p1 = simplified.back();\n                 p2 = simplified[0];\n                 p3 = simplified[1];\n                 collinear = false;\n                 if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n                 if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n                 if (collinear) {\n                     // Remove simplified[0], but need to be careful with vector\n                     // Shift or just leave it, vertex limit is loose enough\n                 }\n             }\n        }\n    } else {\n        simplified = poly;\n    }\n    \n    // Ensure distinct coordinates (remove consecutive duplicates)\n    vector<Point> final_poly;\n    for (const auto& p : simplified) {\n        if (final_poly.empty() || !(final_poly.back().x == p.x && final_poly.back().y == p.y)) {\n            final_poly.push_back(p);\n        }\n    }\n    // Check loop closure duplicate\n    if (final_poly.size() > 1 && final_poly.front().x == final_poly.back().x && final_poly.front().y == final_poly.back().y) {\n        final_poly.pop_back();\n    }\n\n    // If polygon is too small (less than 4 vertices), it's invalid.\n    // But grid cells produce rectangles (4 vertices).\n    // If simplified reduced it, we might have issue.\n    // Restore if needed.\n    if (final_poly.size() < 4) {\n        // Fallback to the raw poly before simplification if it had 4+\n        if (poly.size() >= 4) {\n             final_poly.clear();\n             for (const auto& p : poly) {\n                if (final_poly.empty() || !(final_poly.back().x == p.x && final_poly.back().y == p.y)) {\n                    final_poly.push_back(p);\n                }\n            }\n            if (final_poly.size() > 1 && final_poly.front().x == final_poly.back().x && final_poly.front().y == final_poly.back().y) {\n                final_poly.pop_back();\n            }\n        } else {\n            // Fallback: Single cell rectangle\n            final_poly = {\n                {best_c * CELL_SIZE, best_r * CELL_SIZE},\n                {(best_c + 1) * CELL_SIZE, best_r * CELL_SIZE},\n                {(best_c + 1) * CELL_SIZE, (best_r + 1) * CELL_SIZE},\n                {best_c * CELL_SIZE, (best_r + 1) * CELL_SIZE}\n            };\n        }\n    }\n\n    // Verify constraints\n    // Vertices\n    if (final_poly.size() > MAX_VERTICES) {\n        // This should not happen with grid size 500 and perimeter limit\n        // But if it does, we need to simplify more aggressively.\n        // For this solution, we assume it fits.\n    }\n    \n    // Perimeter\n    long long perim = 0;\n    for (size_t i = 0; i < final_poly.size(); ++i) {\n        Point p1 = final_poly[i];\n        Point p2 = final_poly[(i + 1) % final_poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    \n    // Output\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>\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n};\n\nclass PackingSimulator {\npublic:\n    int N;\n    vector<Rectangle> rects;\n    vector<Placement> placements;\n    \n    PackingSimulator(int n, const vector<Rectangle>& r) : N(n), rects(r) {}\n    \n    void clear() {\n        placements.clear();\n    }\n    \n    void addPlacement(int rect_id, int rotation, char direction, int base) {\n        placements.push_back({rect_id, rotation, direction, base});\n    }\n    \n    pair<int, int> simulate() {\n        vector<pair<int, int>> pos(N, {-1, -1});\n        vector<pair<int, int>> dim(N, {-1, -1});\n        int max_x = 0, max_y = 0;\n        \n        for (size_t idx = 0; idx < placements.size(); idx++) {\n            const auto& p = placements[idx];\n            int w = rects[p.rect_id].w_obs;\n            int h = rects[p.rect_id].h_obs;\n            \n            if (p.rotation == 1) swap(w, h);\n            dim[p.rect_id] = {w, h};\n            \n            int x = 0, y = 0;\n            \n            if (p.direction == 'U') {\n                if (p.base == -1) {\n                    x = 0;\n                } else {\n                    x = pos[p.base].first + dim[p.base].first;\n                }\n                y = 0;\n                for (size_t i = 0; i < idx; i++) {\n                    int rid = placements[i].rect_id;\n                    int px = pos[rid].first, py = pos[rid].second;\n                    int pw = dim[rid].first, ph = dim[rid].second;\n                    if (x < px + pw && x + w > px) {\n                        y = max(y, py + ph);\n                    }\n                }\n            } else {\n                if (p.base == -1) {\n                    y = 0;\n                } else {\n                    y = pos[p.base].second + dim[p.base].second;\n                }\n                x = 0;\n                for (size_t i = 0; i < idx; i++) {\n                    int rid = placements[i].rect_id;\n                    int px = pos[rid].first, py = pos[rid].second;\n                    int pw = dim[rid].first, ph = dim[rid].second;\n                    if (y < py + ph && y + h > py) {\n                        x = max(x, px + pw);\n                    }\n                }\n            }\n            \n            pos[p.rect_id] = {x, y};\n            max_x = max(max_x, x + w);\n            max_y = max(max_y, y + h);\n        }\n        \n        return {max_x, max_y};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(0);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    PackingSimulator sim(N, rects);\n    vector<Placement> best_placements;\n    long long best_score = LLONG_MAX;\n    int best_turn = -1;\n    \n    mt19937 rng(42);\n    \n    for (int turn = 0; turn < T; turn++) {\n        sim.clear();\n        \n        // Greedy construction with some randomization\n        for (int i = 0; i < N; i++) {\n            int best_rot = 0;\n            char best_dir = 'U';\n            int best_base = -1;\n            long long best_local = LLONG_MAX;\n            \n            // Try all combinations for this rectangle\n            vector<int> bases;\n            bases.push_back(-1);\n            for (int j = 0; j < i; j++) bases.push_back(j);\n            \n            // Sample bases if too many\n            if (bases.size() > 10) {\n                shuffle(bases.begin(), bases.end(), rng);\n                bases.resize(10);\n            }\n            \n            for (int rot = 0; rot < 2; rot++) {\n                for (char dir : {'U', 'L'}) {\n                    for (int base : bases) {\n                        sim.addPlacement(i, rot, dir, base);\n                        auto dims = sim.simulate();\n                        long long score = (long long)dims.first + dims.second;\n                        \n                        if (score < best_local) {\n                            best_local = score;\n                            best_rot = rot;\n                            best_dir = dir;\n                            best_base = base;\n                        }\n                        \n                        sim.placements.pop_back();\n                    }\n                }\n            }\n            \n            sim.addPlacement(i, best_rot, best_dir, best_base);\n        }\n        \n        // Local search improvement\n        bool improved = true;\n        int search_limit = min(50, T - turn);\n        int search_iter = 0;\n        \n        while (improved && search_iter < search_limit) {\n            improved = false;\n            search_iter++;\n            \n            auto current_dims = sim.simulate();\n            long long current_score = (long long)current_dims.first + current_dims.second;\n            \n            // Try modifying each rectangle's placement\n            for (int i = 0; i < N && !improved; i++) {\n                int orig_rot = sim.placements[i].rotation;\n                char orig_dir = sim.placements[i].direction;\n                int orig_base = sim.placements[i].base;\n                \n                // Try alternative rotation\n                for (int rot = 0; rot < 2; rot++) {\n                    if (rot == orig_rot) continue;\n                    sim.placements[i].rotation = rot;\n                    auto dims = sim.simulate();\n                    long long score = (long long)dims.first + dims.second;\n                    \n                    if (score < current_score - 100) {\n                        current_score = score;\n                        orig_rot = rot;\n                        improved = true;\n                    }\n                }\n                sim.placements[i].rotation = orig_rot;\n                \n                // Try alternative direction\n                for (char dir : {'U', 'L'}) {\n                    if (dir == orig_dir) continue;\n                    sim.placements[i].direction = dir;\n                    auto dims = sim.simulate();\n                    long long score = (long long)dims.first + dims.second;\n                    \n                    if (score < current_score - 100) {\n                        current_score = score;\n                        orig_dir = dir;\n                        improved = true;\n                    }\n                }\n                sim.placements[i].direction = orig_dir;\n                \n                // Try alternative base\n                vector<int> test_bases;\n                test_bases.push_back(-1);\n                for (int j = 0; j < i; j++) test_bases.push_back(j);\n                if (test_bases.size() > 5) {\n                    shuffle(test_bases.begin(), test_bases.end(), rng);\n                    test_bases.resize(5);\n                }\n                \n                for (int base : test_bases) {\n                    if (base == orig_base) continue;\n                    sim.placements[i].base = base;\n                    auto dims = sim.simulate();\n                    long long score = (long long)dims.first + dims.second;\n                    \n                    if (score < current_score - 100) {\n                        current_score = score;\n                        orig_base = base;\n                        improved = true;\n                    }\n                }\n                sim.placements[i].base = orig_base;\n            }\n        }\n        \n        auto final_dims = sim.simulate();\n        long long estimated_score = (long long)final_dims.first + final_dims.second;\n        \n        // Output placements\n        cout << \"# Turn \" << turn << \" estimated: \" << final_dims.first << \"x\" << final_dims.second << \"\\n\";\n        cout << N << \"\\n\";\n        for (const auto& p : sim.placements) {\n            cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read feedback\n        int W_meas, H_meas;\n        cin >> W_meas >> H_meas;\n        long long measured_score = (long long)W_meas + H_meas;\n        \n        // Update best with noise margin\n        if (measured_score < best_score - (long long)sigma) {\n            best_score = measured_score;\n            best_placements = sim.placements;\n            best_turn = turn;\n            cout << \"# New best: \" << measured_score << \" at turn \" << turn << \"\\n\";\n        }\n    }\n    \n    // Submit best solution in remaining turns (if any)\n    // Note: We've already used all T turns in the loop above\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\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\n    // Skip coordinates as they are not needed for the graph structure logic\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // State: is_root[v] indicates if vertex v is a root of a tree\n    // We start with all vertices as roots, which is a valid state (height 0 for all)\n    vector<bool> is_root(N, true); \n    \n    // Buffer for distance calculation\n    vector<int> dist(N);\n\n    // Function to calculate score and check validity (max height <= H)\n    // Returns -1 if invalid\n    auto get_score_and_validity = [&](const vector<bool>& roots, vector<int>& d) -> long long {\n        fill(d.begin(), d.end(), -1);\n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (roots[i]) {\n                d[i] = 0;\n                q.push(i);\n            }\n        }\n\n        if (q.empty()) return -1; // Must have at least one root\n\n        int max_d = 0;\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (d[u] > max_d) max_d = d[u];\n            if (max_d > H) return -1; // Exceeds height limit\n\n            for (int v : adj[u]) {\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        \n        long long score = 0;\n        for (int i = 0; i < N; ++i) {\n            score += (long long)(d[i] + 1) * A[i];\n        }\n        return score;\n    };\n\n    vector<int> current_dist(N);\n    long long current_score = get_score_and_validity(is_root, current_dist);\n    \n    vector<int> nodes(N);\n    iota(nodes.begin(), nodes.end(), 0);\n    \n    // Random number generator seeded with time\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Greedy removal phase: Try to remove roots to increase depth (and score)\n    // while maintaining validity.\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        shuffle(nodes.begin(), nodes.end(), rng);\n        for (int u : nodes) {\n            if (is_root[u]) {\n                is_root[u] = false;\n                long long new_score = get_score_and_validity(is_root, current_dist);\n                if (new_score == -1) {\n                    is_root[u] = true; // Revert if invalid\n                } else {\n                    current_score = new_score;\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    // Simulated Annealing phase to explore the solution space\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // Leave margin for output\n\n    double T = 100.0;\n    double cooling_rate = 0.9995; \n    \n    vector<bool> best_roots = is_root;\n    long long best_score = current_score;\n    vector<int> best_dist = current_dist;\n\n    vector<int> next_dist(N);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // Propose a move: either remove a root or swap a root with a non-root\n        int move_type = rng() % 2;\n        bool accepted = false;\n\n        if (move_type == 0) {\n            // Try remove\n            vector<int> roots_list;\n            for(int i=0; i<N; ++i) if(is_root[i]) roots_list.push_back(i);\n            \n            if (!roots_list.empty()) {\n                int idx = rng() % roots_list.size();\n                int u = roots_list[idx];\n                \n                is_root[u] = false;\n                long long new_score = get_score_and_validity(is_root, next_dist);\n                \n                if (new_score != -1) {\n                    double delta = (double)(new_score - current_score);\n                    // Accept if better, or with probability based on temperature\n                    if (delta > 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        current_dist = next_dist;\n                        accepted = true;\n                    } else {\n                        is_root[u] = true; // Revert\n                    }\n                } else {\n                    is_root[u] = true; // Revert\n                }\n            }\n        } else {\n            // Try swap\n            vector<int> roots_list, non_roots_list;\n            for(int i=0; i<N; ++i) {\n                if(is_root[i]) roots_list.push_back(i);\n                else non_roots_list.push_back(i);\n            }\n            \n            if (!roots_list.empty() && !non_roots_list.empty()) {\n                int i1 = rng() % roots_list.size();\n                int i2 = rng() % non_roots_list.size();\n                int u = roots_list[i1];\n                int w = non_roots_list[i2];\n                \n                is_root[u] = false;\n                is_root[w] = true;\n                \n                long long new_score = get_score_and_validity(is_root, next_dist);\n                \n                if (new_score != -1) {\n                    double delta = (double)(new_score - current_score);\n                    if (delta > 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        current_dist = next_dist;\n                        accepted = true;\n                    } else {\n                        is_root[u] = true;\n                        is_root[w] = false; // Revert\n                    }\n                } else {\n                    is_root[u] = true;\n                    is_root[w] = false; // Revert\n                }\n            }\n        }\n\n        // Update best solution found so far\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_roots = is_root;\n            best_dist = current_dist;\n        }\n\n        T *= cooling_rate;\n    }\n\n    // Reconstruct parent pointers based on best_dist\n    // If v is root, p_v = -1. Else p_v is a neighbor with dist = dist[v] - 1.\n    vector<int> P(N);\n    for (int v = 0; v < N; ++v) {\n        if (best_roots[v]) {\n            P[v] = -1;\n        } else {\n            int d = best_dist[v];\n            int parent = -1;\n            for (int u : adj[v]) {\n                if (best_dist[u] == d - 1) {\n                    parent = u;\n                    break; // Pick the first valid parent\n                }\n            }\n            P[v] = parent;\n        }\n    }\n\n    // Output result\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cassert>\n\nusing namespace std;\n\nstruct Piece {\n    int r, c;\n    char type; // 'x' = Oni, 'o' = Fukunokami, '.' = empty\n};\n\nstruct Operation {\n    char dir;\n    int idx;\n};\n\nint N = 20;\nvector<string> board;\nvector<pair<int, int>> oni_positions;\nvector<pair<int, int>> fuku_positions;\n\n// Check if direction is safe for removing Oni at (r, c)\n// dir: 0=up, 1=down, 2=left, 3=right\nbool is_safe_direction(int r, int c, int dir, const vector<string>& bd) {\n    if (dir == 0) { // up\n        for (int i = 0; i < r; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 1) { // down\n        for (int i = r + 1; i < N; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 2) { // left\n        for (int j = 0; j < c; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    } else { // right\n        for (int j = c + 1; j < N; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    }\n}\n\n// Calculate cost to remove Oni at (r, c) in given direction\nint get_cost(int r, int c, int dir) {\n    if (dir == 0) return 2 * (r + 1); // up then down\n    if (dir == 1) return 2 * (N - r); // down then up\n    if (dir == 2) return 2 * (c + 1); // left then right\n    return 2 * (N - c); // right then left\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n    }\n    \n    // Find all Oni and Fukunokami positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == 'x') {\n                oni_positions.push_back({i, j});\n            } else if (board[i][j] == 'o') {\n                fuku_positions.push_back({i, j});\n            }\n        }\n    }\n    \n    vector<Operation> ops;\n    vector<string> current_board = board;\n    \n    // Process each Oni\n    // Sort by minimum cost to remove (greedy approach)\n    struct OniInfo {\n        int r, c, best_dir, cost;\n    };\n    \n    vector<OniInfo> oni_list;\n    for (auto& p : oni_positions) {\n        int best_dir = -1;\n        int min_cost = 1e9;\n        for (int dir = 0; dir < 4; dir++) {\n            if (is_safe_direction(p.first, p.second, dir, current_board)) {\n                int cost = get_cost(p.first, p.second, dir);\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_dir = dir;\n                }\n            }\n        }\n        oni_list.push_back({p.first, p.second, best_dir, min_cost});\n    }\n    \n    // Sort by cost (remove cheapest first)\n    sort(oni_list.begin(), oni_list.end(), [](const OniInfo& a, const OniInfo& b) {\n        return a.cost < b.cost;\n    });\n    \n    // Remove each Oni\n    for (auto& oni : oni_list) {\n        int r = oni.r, c = oni.c;\n        int dir = oni.best_dir;\n        \n        if (dir == 0) { // up\n            // Shift column c upward (r+1) times\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'U', c});\n                // Update board\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n            // Shift column c downward (r+1) times to restore\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'D', c});\n                // Update board\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n        } else if (dir == 1) { // down\n            // Shift column c downward (N-r) times\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'D', c});\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n            // Shift column c upward (N-r) times to restore\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'U', c});\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n        } else if (dir == 2) { // left\n            // Shift row r leftward (c+1) times\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n            // Shift row r rightward (c+1) times to restore\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n        } else { // right\n            // Shift row r rightward (N-c) times\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n            // Shift row r leftward (N-c) times to restore\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n        }\n    }\n    \n    // Output operations\n    for (auto& op : ops) {\n        cout << op.dir << \" \" << op.idx << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    long long L;\n    cin >> N >> L;\n    \n    vector<long long> T(N);\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n    \n    // Use fixed seed for reproducibility, or time-based for variety\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Create weighted candidate distribution based on target frequencies\n    vector<int> weighted_candidates;\n    for (int i = 0; i < N; i++) {\n        // Higher target = more likely to be chosen as next cleaner\n        int weight = max(1, (int)(T[i] / 500 + 1));\n        for (int j = 0; j < weight; j++) {\n            weighted_candidates.push_back(i);\n        }\n    }\n    \n    // Initialize a and b arrays\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; i++) {\n        a[i] = weighted_candidates[rng() % weighted_candidates.size()];\n        b[i] = weighted_candidates[rng() % weighted_candidates.size()];\n    }\n    \n    // Simulation function\n    auto simulate = [&]() -> vector<long long> {\n        vector<long long> count(N, 0);\n        int current = 0;\n        \n        for (long long week = 0; week < L; week++) {\n            count[current]++;\n            // t = count[current] is the number of times current has cleaned\n            // If t is odd (1st, 3rd, 5th...), use a[current]\n            // If t is even (2nd, 4th, 6th...), use b[current]\n            if (count[current] % 2 == 1) {\n                current = a[current];\n            } else {\n                current = b[current];\n            }\n        }\n        \n        return count;\n    };\n    \n    // Error calculation\n    auto calcError = [&](const vector<long long>& actual) -> long long {\n        long long error = 0;\n        for (int i = 0; i < N; i++) {\n            error += abs(actual[i] - T[i]);\n        }\n        return error;\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_error = 1e18;\n    vector<int> best_a = a, best_b = b;\n    \n    // Main optimization loop\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Stop with buffer time for output\n        if (elapsed > 1950) break;\n        \n        // Evaluate current solution\n        vector<long long> actual = simulate();\n        long long error = calcError(actual);\n        \n        // Track best solution\n        if (error < best_error) {\n            best_error = error;\n            best_a = a;\n            best_b = b;\n        }\n        \n        // Local search: modify one parameter\n        int i = rng() % N;\n        int choice = rng() % 2;  // 0 = modify a[i], 1 = modify b[i]\n        int old_val = (choice == 0) ? a[i] : b[i];\n        \n        // Try new value from weighted candidates\n        int new_val = weighted_candidates[rng() % weighted_candidates.size()];\n        \n        if (choice == 0) {\n            a[i] = new_val;\n        } else {\n            b[i] = new_val;\n        }\n        \n        // Evaluate new solution\n        vector<long long> new_actual = simulate();\n        long long new_error = calcError(new_actual);\n        \n        // Simulated annealing acceptance criterion\n        if (new_error < error) {\n            // Always accept improvements\n        } else {\n            // Accept worse solutions with decreasing probability over time\n            double progress = (double)elapsed / 2000.0;\n            double temperature = 1000.0 * (1.0 - progress);\n            temperature = max(1.0, temperature);\n            \n            double acceptance_prob = exp(-(double)(new_error - error) / temperature);\n            \n            if ((double)rng() / rng.max() > acceptance_prob) {\n                // Revert change\n                if (choice == 0) {\n                    a[i] = old_val;\n                } else {\n                    b[i] = old_val;\n                }\n            }\n        }\n    }\n    \n    // Output best solution found\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 <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\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 weight;\n    bool fromQuery;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(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        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\nint estimateDist(const City& a, const City& b) {\n    double dx = a.cx - b.cx;\n    double dy = a.cy - b.cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\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, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    \n    vector<int> G(M);\n    for (int i = 0; i < M; i++) {\n        cin >> G[i];\n    }\n    \n    vector<City> cities(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 center coordinates (spatial proximity)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (abs(cities[a].cx - cities[b].cx) > 1.0)\n            return cities[a].cx < cities[b].cx;\n        return cities[a].cy < cities[b].cy;\n    });\n    \n    // Assign cities to groups based on spatial ordering\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n    \n    // Track known edges globally\n    set<pair<int,int>> knownEdges;\n    vector<vector<pair<int,int>>> groupEdges(M);\n    \n    int queriesUsed = 0;\n    \n    // Prioritize larger groups for queries (more impact on total score)\n    vector<int> groupOrder(M);\n    iota(groupOrder.begin(), groupOrder.end(), 0);\n    sort(groupOrder.begin(), groupOrder.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n    \n    // Query each group strategically\n    for (int gi : groupOrder) {\n        // Time check - leave margin for output\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        if (elapsed > 1800 || queriesUsed >= Q) break;\n        \n        int groupSize = groups[gi].size();\n        if (groupSize < 2) continue;\n        \n        // Query this group in overlapping chunks\n        for (int start = 0; start < groupSize && queriesUsed < Q; ) {\n            // Use maximum chunk size, but ensure we cover the group\n            int remaining = groupSize - start;\n            int chunkSize = min(L, remaining);\n            \n            if (chunkSize < 2) break;\n            \n            // Make query\n            cout << \"?\" << \" \" << chunkSize;\n            for (int i = 0; i < chunkSize; i++) {\n                cout << \" \" << groups[gi][start + i];\n            }\n            cout << endl;\n            cout.flush();\n            \n            queriesUsed++;\n            \n            // Read MST edges from response\n            for (int i = 0; i < chunkSize - 1; i++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                knownEdges.insert({u, v});\n                groupEdges[gi].push_back({u, v});\n            }\n            \n            // Overlap by 1 to ensure connectivity across chunks\n            start += chunkSize - 1;\n        }\n    }\n    \n    // Build complete MST for each group\n    for (int g = 0; g < M; g++) {\n        int groupSize = groups[g].size();\n        if (groupSize < 2) continue;\n        \n        vector<Edge> allEdges;\n        \n        // Add edges from queries for this group\n        for (auto& e : groupEdges[g]) {\n            allEdges.push_back({e.first, e.second, estimateDist(cities[e.first], cities[e.second]), true});\n        }\n        \n        // Add estimated edges between all pairs in group\n        for (int i = 0; i < groupSize; i++) {\n            for (int j = i + 1; j < groupSize; j++) {\n                int u = groups[g][i];\n                int v = groups[g][j];\n                if (u > v) swap(u, v);\n                \n                // Only add if not already known from queries\n                if (knownEdges.find({u, v}) == knownEdges.end()) {\n                    allEdges.push_back({groups[g][i], groups[g][j], \n                                       estimateDist(cities[groups[g][i]], cities[groups[g][j]]), false});\n                }\n            }\n        }\n        \n        // Build MST - prefer query edges, then by weight\n        sort(allEdges.begin(), allEdges.end(), [&](const Edge& a, const Edge& b) {\n            if (a.fromQuery != b.fromQuery) return a.fromQuery > b.fromQuery;\n            return a.weight < b.weight;\n        });\n        \n        vector<pair<int,int>> mstEdges;\n        DSU dsu(N);\n        \n        for (auto& e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                mstEdges.push_back({e.u, e.v});\n                if ((int)mstEdges.size() == groupSize - 1) break;\n            }\n        }\n        \n        groupEdges[g] = mstEdges;\n    }\n    \n    // Output final answer\n    cout << \"!\" << endl;\n    cout.flush();\n    \n    for (int g = 0; g < M; g++) {\n        // Output cities in group\n        for (int i = 0; i < (int)groups[g].size(); i++) {\n            if (i > 0) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : groupEdges[g]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint cur_i, cur_j;\nvector<pair<int, int>> targets;\nset<pair<int, int>> blocks;\n\nstruct State {\n    int i, j;\n    int dist;\n    vector<pair<char, char>> path;\n};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && blocks.find({i, j}) == blocks.end();\n}\n\npair<int, int> getSlideEnd(int i, int j, int di, int dj) {\n    while (true) {\n        int ni = i + di, nj = j + dj;\n        if (!isValid(ni, nj)) break;\n        i = ni;\n        j = nj;\n    }\n    return {i, j};\n}\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nvoid solve() {\n    cin >> N >> M;\n    cin >> cur_i >> cur_j;\n    for (int k = 0; k < M; k++) {\n        int i, j;\n        cin >> i >> j;\n        targets.push_back({i, j});\n    }\n    \n    vector<pair<char, char>> allActions;\n    \n    for (int t = 0; t < M; t++) {\n        int ti = targets[t].first;\n        int tj = targets[t].second;\n        vector<pair<char, char>> targetActions;\n        \n        // BFS with priority on slides\n        priority_queue<tuple<int, int, int, vector<pair<char, char>>>, \n                      vector<tuple<int, int, int, vector<pair<char, char>>>>,\n                      greater<tuple<int, int, int, vector<pair<char, char>>>>> pq;\n        \n        vector<pair<char, char>> emptyPath;\n        pq.push({manhattan(cur_i, cur_j, ti, tj), 0, 0, emptyPath});\n        \n        set<tuple<int, int>> visited;\n        bool found = false;\n        \n        int iterations = 0;\n        const int MAX_ITER = 5000;\n        \n        while (!pq.empty() && !found && iterations < MAX_ITER) {\n            iterations++;\n            auto [heuristic, dist, ignored, path] = pq.top();\n            pq.pop();\n            \n            // Extract current position from path\n            int pi = cur_i, pj = cur_j;\n            set<pair<int, int>> tempBlocks = blocks;\n            \n            for (auto& [act, dir] : path) {\n                if (act == 'M') {\n                    if (dir == 'U') pi--;\n                    else if (dir == 'D') pi++;\n                    else if (dir == 'L') pj--;\n                    else if (dir == 'R') pj++;\n                } else if (act == 'S') {\n                    int di = 0, dj = 0;\n                    if (dir == 'U') di = -1;\n                    else if (dir == 'D') di = 1;\n                    else if (dir == 'L') dj = -1;\n                    else if (dir == 'R') dj = 1;\n                    tie(pi, pj) = getSlideEnd(pi, pj, di, dj);\n                } else if (act == 'A') {\n                    int bi = pi, bj = pj;\n                    if (dir == 'U') bi--;\n                    else if (dir == 'D') bi++;\n                    else if (dir == 'L') bj--;\n                    else if (dir == 'R') bj++;\n                    if (tempBlocks.count({bi, bj})) tempBlocks.erase({bi, bj});\n                    else tempBlocks.insert({bi, bj});\n                }\n            }\n            \n            if (pi == ti && pj == tj) {\n                targetActions = path;\n                found = true;\n                break;\n            }\n            \n            auto key = make_tuple(pi, pj);\n            if (visited.count(key)) continue;\n            visited.insert(key);\n            \n            if (dist > 100) continue; // Limit search depth\n            \n            // Try moves\n            int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n            char dirChars[4] = {'U', 'D', 'L', 'R'};\n            \n            for (int d = 0; d < 4; d++) {\n                int di = dirs[d][0], dj = dirs[d][1];\n                int ni = pi + di, nj = pj + dj;\n                \n                if (isValid(ni, nj)) {\n                    auto newPath = path;\n                    newPath.push_back({'M', dirChars[d]});\n                    int newDist = dist + 1;\n                    int h = manhattan(ni, nj, ti, tj);\n                    pq.push({h + newDist, newDist, 0, newPath});\n                }\n                \n                // Try slides\n                auto [si, sj] = getSlideEnd(pi, pj, di, dj);\n                if (si != pi || sj != pj) {\n                    auto newPath = path;\n                    newPath.push_back({'S', dirChars[d]});\n                    int newDist = dist + 1;\n                    int h = manhattan(si, sj, ti, tj);\n                    pq.push({h + newDist, newDist, 0, newPath});\n                }\n                \n                // Try alter (place block) - limited usage\n                if (dist < 50) {\n                    int bi = pi + di, bj = pj + dj;\n                    if (bi >= 0 && bi < N && bj >= 0 && bj < N && \n                        !tempBlocks.count({bi, bj}) && !(bi == ti && bj == tj)) {\n                        auto newPath = path;\n                        newPath.push_back({'A', dirChars[d]});\n                        int newDist = dist + 1;\n                        int h = manhattan(pi, pj, ti, tj);\n                        pq.push({h + newDist, newDist, 0, newPath});\n                    }\n                }\n            }\n        }\n        \n        // Fallback: simple greedy if BFS fails\n        if (!found) {\n            int pi = cur_i, pj = cur_j;\n            set<pair<int, int>> localBlocks = blocks;\n            \n            while (pi != ti || pj != tj) {\n                bool moved = false;\n                \n                // Try slides first\n                for (int d = 0; d < 4; d++) {\n                    int di = dirs[d][0], dj = dirs[d][1];\n                    auto [si, sj] = getSlideEnd(pi, pj, di, dj);\n                    \n                    if (si == ti && sj == tj) {\n                        targetActions.push_back({'S', dirChars[d]});\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                    \n                    int oldDist = manhattan(pi, pj, ti, tj);\n                    int newDist = manhattan(si, sj, ti, tj);\n                    \n                    if (newDist < oldDist && (si != pi || sj != pj)) {\n                        targetActions.push_back({'S', dirChars[d]});\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                }\n                \n                if (!moved) {\n                    // Use move\n                    if (pi < ti) {\n                        targetActions.push_back({'M', 'D'});\n                        pi++;\n                    } else if (pi > ti) {\n                        targetActions.push_back({'M', 'U'});\n                        pi--;\n                    } else if (pj < tj) {\n                        targetActions.push_back({'M', 'R'});\n                        pj++;\n                    } else if (pj > tj) {\n                        targetActions.push_back({'M', 'L'});\n                        pj--;\n                    }\n                }\n            }\n        }\n        \n        // Execute actions and update blocks\n        for (auto& [act, dir] : targetActions) {\n            if (act == 'M') {\n                if (dir == 'U') cur_i--;\n                else if (dir == 'D') cur_i++;\n                else if (dir == 'L') cur_j--;\n                else if (dir == 'R') cur_j++;\n            } else if (act == 'S') {\n                int di = 0, dj = 0;\n                if (dir == 'U') di = -1;\n                else if (dir == 'D') di = 1;\n                else if (dir == 'L') dj = -1;\n                else if (dir == 'R') dj = 1;\n                tie(cur_i, cur_j) = getSlideEnd(cur_i, cur_j, di, dj);\n            } else if (act == 'A') {\n                int bi = cur_i, bj = cur_j;\n                if (dir == 'U') bi--;\n                else if (dir == 'D') bi++;\n                else if (dir == 'L') bj--;\n                else if (dir == 'R') bj++;\n                if (blocks.count({bi, bj})) blocks.erase({bi, bj});\n                else blocks.insert({bi, bj});\n            }\n            allActions.push_back({act, dir});\n        }\n    }\n    \n    for (auto& [act, dir] : allActions) {\n        cout << act << \" \" << dir << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n    double satisfaction;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\ndouble calc_satisfaction(int r, int s, bool contains) {\n    if (!contains) return 0.0;\n    double ratio = min(r, s) / (double)max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Recursive space partitioning\nvoid partition(vector<int>& indices, const vector<Company>& companies, \n               Rect region, vector<Rect>& result) {\n    if (indices.empty()) return;\n    \n    if (indices.size() == 1) {\n        result[companies[indices[0]].id] = region;\n        return;\n    }\n    \n    // Calculate total area needed\n    long long total_area = 0;\n    for (int idx : indices) {\n        total_area += companies[idx].r;\n    }\n    \n    // Find split point that balances area\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        // Sort by x then y for vertical split, or y then x for horizontal\n        long long region_w = region.x2 - region.x1;\n        long long region_h = region.y2 - region.y1;\n        if (region_w > region_h) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        } else {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        }\n    });\n    \n    // Find best split point\n    long long left_area = 0;\n    int split_idx = 0;\n    long long best_diff = LLONG_MAX;\n    \n    for (int i = 0; i < (int)indices.size() - 1; i++) {\n        left_area += companies[indices[i]].r;\n        long long diff = abs(2 * left_area - total_area);\n        if (diff < best_diff) {\n            best_diff = diff;\n            split_idx = i + 1;\n        }\n    }\n    \n    // Create split\n    long long left_sum = 0;\n    for (int i = 0; i < split_idx; i++) {\n        left_sum += companies[indices[i]].r;\n    }\n    \n    Rect left_region = region, right_region = region;\n    \n    if (region.x2 - region.x1 > region.y2 - region.y1) {\n        // Vertical split\n        int split_x = region.x1 + (int)((left_sum * (region.x2 - region.x1) + total_area/2) / total_area);\n        split_x = max(region.x1 + 1, min(region.x2 - 1, split_x));\n        left_region.x2 = split_x;\n        right_region.x1 = split_x;\n    } else {\n        // Horizontal split\n        int split_y = region.y1 + (int)((left_sum * (region.y2 - region.y1) + total_area/2) / total_area);\n        split_y = max(region.y1 + 1, min(region.y2 - 1, split_y));\n        left_region.y2 = split_y;\n        right_region.y1 = split_y;\n    }\n    \n    vector<int> left_indices(indices.begin(), indices.begin() + split_idx);\n    vector<int> right_indices(indices.begin() + split_idx, indices.end());\n    \n    partition(left_indices, companies, left_region, result);\n    partition(right_indices, companies, right_region, result);\n}\n\n// Adjust rectangle to contain point and match area\nvoid adjust_rectangle(Company& comp, Rect& rect) {\n    int target_area = comp.r;\n    int px = comp.x, py = comp.y;\n    \n    // Ensure point is contained\n    if (rect.x1 > px) rect.x1 = px;\n    if (rect.x2 <= px) rect.x2 = px + 1;\n    if (rect.y1 > py) rect.y1 = py;\n    if (rect.y2 <= py) rect.y2 = py + 1;\n    \n    // Adjust to match area\n    long long current_area = rect.area();\n    \n    if (current_area < target_area) {\n        // Expand\n        int need = target_area - current_area;\n        int width = rect.x2 - rect.x1;\n        int height = rect.y2 - rect.y1;\n        \n        // Prefer expanding in direction with more space\n        int can_expand_left = rect.x1;\n        int can_expand_right = 10000 - rect.x2;\n        int can_expand_bottom = rect.y1;\n        int can_expand_top = 10000 - rect.y2;\n        \n        while (rect.area() < target_area) {\n            int best_dir = 0;\n            int best_gain = 0;\n            \n            if (can_expand_left > 0) {\n                int gain = height;\n                if (gain > best_gain) { best_gain = gain; best_dir = 1; }\n            }\n            if (can_expand_right > 0) {\n                int gain = height;\n                if (gain > best_gain) { best_gain = gain; best_dir = 2; }\n            }\n            if (can_expand_bottom > 0) {\n                int gain = width;\n                if (gain > best_gain) { best_gain = gain; best_dir = 3; }\n            }\n            if (can_expand_top > 0) {\n                int gain = width;\n                if (gain > best_gain) { best_gain = gain; best_dir = 4; }\n            }\n            \n            if (best_dir == 0) break;\n            if (best_dir == 1) { rect.x1--; can_expand_left--; }\n            else if (best_dir == 2) { rect.x2++; can_expand_right--; }\n            else if (best_dir == 3) { rect.y1--; can_expand_bottom--; }\n            else if (best_dir == 4) { rect.y2++; can_expand_top--; }\n            \n            width = rect.x2 - rect.x1;\n            height = rect.y2 - rect.y1;\n        }\n    } else if (current_area > target_area) {\n        // Shrink\n        while (rect.area() > target_area && rect.x2 - rect.x1 > 1 && rect.y2 - rect.y1 > 1) {\n            // Shrink from side opposite to point\n            int dist_left = px - rect.x1;\n            int dist_right = rect.x2 - 1 - px;\n            int dist_bottom = py - rect.y1;\n            int dist_top = rect.y2 - 1 - py;\n            \n            int max_dist = max({dist_left, dist_right, dist_bottom, dist_top});\n            \n            if (max_dist == dist_left && rect.x2 - rect.x1 > 1) rect.x1++;\n            else if (max_dist == dist_right && rect.x2 - rect.x1 > 1) rect.x2--;\n            else if (max_dist == dist_bottom && rect.y2 - rect.y1 > 1) rect.y1++;\n            else if (max_dist == dist_top && rect.y2 - rect.y1 > 1) rect.y2--;\n            else break;\n        }\n    }\n    \n    // Final bounds check\n    rect.x1 = max(0, min(9999, rect.x1));\n    rect.y1 = max(0, min(9999, rect.y1));\n    rect.x2 = max(1, min(10000, rect.x2));\n    rect.y2 = max(1, min(10000, rect.y2));\n    if (rect.x1 >= rect.x2) rect.x2 = rect.x1 + 1;\n    if (rect.y1 >= rect.y2) rect.y2 = rect.y1 + 1;\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    }\n    \n    // Sort by position for better spatial locality\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (companies[i].x != companies[j].x)\n            return companies[i].x < companies[j].x;\n        return companies[i].y < companies[j].y;\n    });\n    \n    // Initial partitioning\n    vector<Rect> rects(n);\n    Rect full_region = {0, 0, 10000, 10000};\n    partition(order, companies, full_region, rects);\n    \n    // Adjust each rectangle to contain point and match area\n    for (int i = 0; i < n; i++) {\n        adjust_rectangle(companies[i], rects[i]);\n        companies[i].a = rects[i].x1;\n        companies[i].b = rects[i].y1;\n        companies[i].c = rects[i].x2;\n        companies[i].d = rects[i].y2;\n    }\n    \n    // Local optimization: try to swap boundaries between adjacent rectangles\n    // Simple greedy improvement\n    for (int iter = 0; iter < 100; iter++) {\n        bool improved = false;\n        \n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                // Check if rectangles are adjacent\n                Rect& ri = rects[i];\n                Rect& rj = rects[j];\n                \n                // Simple adjacency check\n                bool adjacent = false;\n                if (ri.x2 == rj.x1 || rj.x2 == ri.x1) {\n                    if (max(ri.y1, rj.y1) < min(ri.y2, rj.y2)) adjacent = true;\n                }\n                if (ri.y2 == rj.y1 || rj.y2 == ri.y1) {\n                    if (max(ri.x1, rj.x1) < min(ri.x2, rj.x2)) adjacent = true;\n                }\n                \n                if (!adjacent) continue;\n                \n                // Try small adjustments\n                double current_score = calc_satisfaction(companies[i].r, ri.area(), ri.contains(companies[i].x, companies[i].y)) +\n                                      calc_satisfaction(companies[j].r, rj.area(), rj.contains(companies[j].x, companies[j].y));\n                \n                double best_score = current_score;\n                int best_ri = ri.x1, best_ri2 = ri.x2, best_ri3 = ri.y1, best_ri4 = ri.y2;\n                int best_rj = rj.x1, best_rj2 = rj.x2, best_rj3 = rj.y1, best_rj4 = rj.y2;\n                \n                // Try moving boundary by 1 pixel\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        if (dx == 0 && dy == 0) continue;\n                        \n                        Rect test_ri = ri, test_rj = rj;\n                        \n                        // Simple boundary adjustment\n                        if (ri.x2 == rj.x1 && dx != 0) {\n                            test_ri.x2 += dx;\n                            test_rj.x1 += dx;\n                        } else if (rj.x2 == ri.x1 && dx != 0) {\n                            test_rj.x2 += dx;\n                            test_ri.x1 += dx;\n                        } else if (ri.y2 == rj.y1 && dy != 0) {\n                            test_ri.y2 += dy;\n                            test_rj.y1 += dy;\n                        } else if (rj.y2 == ri.y1 && dy != 0) {\n                            test_rj.y2 += dy;\n                            test_ri.y1 += dy;\n                        }\n                        \n                        // Validate\n                        if (test_ri.x1 >= test_ri.x2 || test_ri.y1 >= test_ri.y2) continue;\n                        if (test_rj.x1 >= test_rj.x2 || test_rj.y1 >= test_rj.y2) continue;\n                        if (test_ri.x1 < 0 || test_ri.x2 > 10000 || test_ri.y1 < 0 || test_ri.y2 > 10000) continue;\n                        if (test_rj.x1 < 0 || test_rj.x2 > 10000 || test_rj.y1 < 0 || test_rj.y2 > 10000) continue;\n                        \n                        double new_score = calc_satisfaction(companies[i].r, test_ri.area(), test_ri.contains(companies[i].x, companies[i].y)) +\n                                          calc_satisfaction(companies[j].r, test_rj.area(), test_rj.contains(companies[j].x, companies[j].y));\n                        \n                        if (new_score > best_score) {\n                            best_score = new_score;\n                            best_ri = test_ri.x1; best_ri2 = test_ri.x2; best_ri3 = test_ri.y1; best_ri4 = test_ri.y2;\n                            best_rj = test_rj.x1; best_rj2 = test_rj.x2; best_rj3 = test_rj.y1; best_rj4 = test_rj.y2;\n                        }\n                    }\n                }\n                \n                if (best_score > current_score) {\n                    ri.x1 = best_ri; ri.x2 = best_ri2; ri.y1 = best_ri3; ri.y2 = best_ri4;\n                    rj.x1 = best_rj; rj.x2 = best_rj2; rj.y1 = best_rj3; rj.y2 = best_rj4;\n                    companies[i].a = ri.x1; companies[i].b = ri.y1; companies[i].c = ri.x2; companies[i].d = ri.y2;\n                    companies[j].a = rj.x1; companies[j].b = rj.y1; companies[j].c = rj.x2; companies[j].d = rj.y2;\n                    improved = true;\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" \n             << companies[i].c << \" \" << 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\nusing namespace std;\n\n// Global grid data\nconst int H = 50;\nconst int W = 50;\nvector<vector<int>> tile_id;\nvector<vector<int>> score_val;\nint max_tile = 0;\n\n// Search state\nvector<char> visited_tiles;\nmt19937 rng;\n\n// Heuristic extension of the path\nvoid extend_path(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    // Directions: U, D, L, R\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    \n    while (true) {\n        // Collect valid neighbors\n        struct Cand {\n            int r, c, score, degree;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    int s = score_val[nr][nc];\n                    int deg = 0;\n                    // Lookahead 1 step: count available moves from neighbor\n                    for(int k=0; k<4; ++k) {\n                        int nnr = nr + dr[k];\n                        int nnc = nc + dc[k];\n                        if(nnr >= 0 && nnr < H && nnc >= 0 && nnc < W) {\n                            if(!visited_tiles[tile_id[nnr][nnc]]) deg++;\n                        }\n                    }\n                    cands[count++] = {nr, nc, s, deg};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort candidates: higher (score + degree) first\n        // Since count <= 4, simple sort is very fast\n        for(int i=0; i<count-1; ++i) {\n            for(int j=0; j<count-1-i; ++j) {\n                int val1 = cands[j].score + cands[j].degree;\n                int val2 = cands[j+1].score + cands[j+1].degree;\n                if(val1 < val2) {\n                    swap(cands[j], cands[j+1]);\n                }\n            }\n        }\n        \n        // Pick from top min(3, count) to add randomness\n        int K = (count < 3) ? count : 3;\n        int idx = (int)(rng() % K);\n        \n        int nr = cands[idx].r;\n        int nc = cands[idx].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    tile_id.assign(H, vector<int>(W));\n    max_tile = 0;\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> tile_id[i][j];\n            if (tile_id[i][j] > max_tile) max_tile = tile_id[i][j];\n        }\n    }\n    \n    score_val.assign(H, vector<int>(W));\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> score_val[i][j];\n        }\n    }\n    \n    visited_tiles.assign(max_tile + 1, 0);\n    \n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Initial Solution\n    vector<pair<int, int>> current_path;\n    current_path.reserve(2500);\n    current_path.push_back({si, sj});\n    visited_tiles[tile_id[si][sj]] = 1;\n    long long current_score = score_val[si][sj];\n    \n    extend_path(current_path, current_score);\n    \n    vector<pair<int, int>> best_path = current_path;\n    long long best_score = current_score;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    double temperature = 500.0; \n    \n    // Main Search Loop (Simulated Annealing / Iterated Local Search)\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto ms = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (ms > 1900) break; // Stop at 1.9s to ensure output within 2.0s\n        \n        // Cooling schedule\n        temperature *= 0.9995;\n        if (temperature < 1.0) temperature = 1.0;\n        \n        // Backup current state to allow rollback if move is rejected\n        vector<pair<int, int>> path_backup = current_path;\n        long long score_backup = current_score;\n        \n        // Select a cut point uniformly\n        int cut_idx = (int)(rng() % current_path.size());\n        \n        // Rollback visited tiles for the part we are cutting\n        for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n            int r = current_path[i].first;\n            int c = current_path[i].second;\n            visited_tiles[tile_id[r][c]] = 0;\n        }\n        current_path.resize(cut_idx + 1);\n        \n        // Recalculate score for the prefix\n        long long temp_score = 0;\n        for(const auto& p : current_path) temp_score += score_val[p.first][p.second];\n        \n        // Extend path from cut point\n        extend_path(current_path, temp_score);\n        \n        // Simulated Annealing Acceptance Criterion\n        bool accept = false;\n        if (temp_score > current_score) {\n            accept = true;\n        } else {\n            double diff = (double)(temp_score - current_score);\n            double prob = exp(diff / temperature);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = temp_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n            }\n        } else {\n            // Revert to backup state\n            \n            // 1. Unmark the tiles added in the failed extension\n            for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 0;\n            }\n            \n            // 2. Restore path and score\n            current_path = path_backup;\n            current_score = score_backup;\n            \n            // 3. Re-mark the tiles of the original suffix that were unmarked at the start\n            for (size_t i = cut_idx + 1; i < current_path.size(); ++i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 1;\n            }\n        }\n    }\n    \n    // Construct Output String\n    string res;\n    if (best_path.size() > 1) {\n        res.reserve(best_path.size() - 1);\n        for (size_t i = 1; i < best_path.size(); ++i) {\n            int dr = best_path[i].first - best_path[i-1].first;\n            int dc = best_path[i].second - best_path[i-1].second;\n            if (dr == -1) res += 'U';\n            else if (dr == 1) res += 'D';\n            else if (dc == -1) res += 'L';\n            else if (dc == 1) res += 'R';\n        }\n    }\n    cout << res << endl;\n    \n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Solver {\n    double h[N][N-1];  // horizontal edges: h[i][j] = edge from (i,j) to (i,j+1)\n    double v[N-1][N];  // vertical edges: v[i][j] = edge from (i,j) to (i+1,j)\n    int h_cnt[N][N-1];\n    int v_cnt[N-1][N];\n    \n    Solver() {\n        for(int i = 0; i < N; i++) {\n            for(int j = 0; j < N-1; j++) {\n                h[i][j] = 5000.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for(int i = 0; i < N-1; i++) {\n            for(int j = 0; j < N; j++) {\n                v[i][j] = 5000.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n    \n    // Get edge weight with bounds checking\n    double get_weight(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v[i-1][j] : 1e9;\n        if(dir == 'D') return (i < N-1) ? v[i][j] : 1e9;\n        if(dir == 'L') return (j > 0) ? h[i][j-1] : 1e9;\n        if(dir == 'R') return (j < N-1) ? h[i][j] : 1e9;\n        return 1e9;\n    }\n    \n    // Get visit count for an edge\n    int get_count(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v_cnt[i-1][j] : 0;\n        if(dir == 'D') return (i < N-1) ? v_cnt[i][j] : 0;\n        if(dir == 'L') return (j > 0) ? h_cnt[i][j-1] : 0;\n        if(dir == 'R') return (j < N-1) ? h_cnt[i][j] : 0;\n        return 0;\n    }\n    \n    pair<string, double> dijkstra(int si, int sj, int ti, int tj, double temp) {\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<char>> move(N, vector<char>(N, 0));\n        \n        dist[si][sj] = 0;\n        pq.push({0.0, si, sj});\n        \n        const char dirs[] = {'U', 'D', 'L', 'R'};\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while(!pq.empty()) {\n            auto [d, i, j] = pq.top();\n            pq.pop();\n            \n            if(d > dist[i][j] + 1e-9) continue;\n            if(i == ti && j == tj) break;\n            \n            for(int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                \n                if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double w = get_weight(i, j, dirs[dir]);\n                if(w >= 1e9) continue;\n                \n                // Exploration bonus: prefer less-visited edges\n                int cnt = get_count(i, j, dirs[dir]);\n                double bonus = temp / (cnt + 1);\n                double new_dist = d + w + bonus;\n                \n                if(new_dist < dist[ni][nj]) {\n                    dist[ni][nj] = new_dist;\n                    prev[ni][nj] = {i, j};\n                    move[ni][nj] = dirs[dir];\n                    pq.push({new_dist, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path;\n        int ci = ti, cj = tj;\n        while(ci != si || cj != sj) {\n            path += move[ci][cj];\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        \n        return {path, dist[ti][tj]};\n    }\n    \n    void update(const string& path, int si, int sj, int observed, int query_num) {\n        if(path.empty()) return;\n        \n        // Calculate estimated cost and track vertices\n        double estimated = 0;\n        int ci = si, cj = sj;\n        vector<tuple<int, int, char>> edges;\n        \n        for(char c : path) {\n            double w = get_weight(ci, cj, c);\n            estimated += w;\n            edges.push_back({ci, cj, c});\n            \n            if(c == 'U') ci--;\n            else if(c == 'D') ci++;\n            else if(c == 'L') cj--;\n            else if(c == 'R') cj++;\n        }\n        \n        if(estimated < 1) estimated = 1;\n        double ratio = (double)observed / estimated;\n        \n        // Learning rate decreases over time\n        double lr = 0.30 * pow(0.992, query_num);\n        lr = max(lr, 0.01);\n        \n        // Update edges on path\n        for(auto& [i, j, c] : edges) {\n            if(c == 'U') {\n                v[i-1][j] = (1-lr) * v[i-1][j] + lr * v[i-1][j] * ratio;\n                v_cnt[i-1][j]++;\n            } else if(c == 'D') {\n                v[i][j] = (1-lr) * v[i][j] + lr * v[i][j] * ratio;\n                v_cnt[i][j]++;\n            } else if(c == 'L') {\n                h[i][j-1] = (1-lr) * h[i][j-1] + lr * h[i][j-1] * ratio;\n                h_cnt[i][j-1]++;\n            } else if(c == 'R') {\n                h[i][j] = (1-lr) * h[i][j] + lr * h[i][j] * ratio;\n                h_cnt[i][j]++;\n            }\n        }\n        \n        // Smoothing: propagate information to same row/column\n        smooth(query_num);\n    }\n    \n    void smooth(int query_num) {\n        double smooth_lr = 0.05 * pow(0.995, query_num);\n        \n        // Smooth horizontal edges within each row\n        for(int i = 0; i < N; i++) {\n            double row_avg = 0;\n            int row_cnt = 0;\n            for(int j = 0; j < N-1; j++) {\n                if(h_cnt[i][j] > 0) {\n                    row_avg += h[i][j];\n                    row_cnt++;\n                }\n            }\n            if(row_cnt > 0) {\n                row_avg /= row_cnt;\n                for(int j = 0; j < N-1; j++) {\n                    if(h_cnt[i][j] > 0) {\n                        h[i][j] = (1-smooth_lr) * h[i][j] + smooth_lr * row_avg;\n                    }\n                }\n            }\n        }\n        \n        // Smooth vertical edges within each column\n        for(int j = 0; j < N; j++) {\n            double col_avg = 0;\n            int col_cnt = 0;\n            for(int i = 0; i < N-1; i++) {\n                if(v_cnt[i][j] > 0) {\n                    col_avg += v[i][j];\n                    col_cnt++;\n                }\n            }\n            if(col_cnt > 0) {\n                col_avg /= col_cnt;\n                for(int i = 0; i < N-1; i++) {\n                    if(v_cnt[i][j] > 0) {\n                        v[i][j] = (1-smooth_lr) * v[i][j] + smooth_lr * col_avg;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    mt19937 rng(42);\n    Solver solver;\n    \n    for(int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Exploration temperature decreases over time\n        // Higher early for exploration, lower later for exploitation\n        double temp = 300.0 * pow(0.994, k);\n        \n        auto [path, est_cost] = solver.dijkstra(si, sj, ti, tj, temp);\n        \n        cout << path << \"\\n\";\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        solver.update(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> S[i];\n    }\n\n    vector<string> grid(N, string(N, '.'));\n    vector<int> indices(M);\n    for (int i = 0; i < M; ++i) indices[i] = i;\n\n    // Process longer strings first to lock in more constrained placements\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return S[a].size() > S[b].size();\n    });\n\n    for (int idx : indices) {\n        const string& s = S[idx];\n        int k = s.size();\n        int best_orient = -1;\n        int best_start_i = -1;\n        int best_start_j = -1;\n        int max_dot = -1;\n\n        // Check all horizontal placements\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int col = (j + p) % N;\n                    if (grid[i][col] != '.' && grid[i][col] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[i][col] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 0;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        // Check all vertical placements\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ++i) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int row = (i + p) % N;\n                    if (grid[row][j] != '.' && grid[row][j] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[row][j] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 1;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        if (max_dot >= 0) {\n            for (int p = 0; p < k; ++p) {\n                int i, j;\n                if (best_orient == 0) {\n                    i = best_start_i;\n                    j = (best_start_j + p) % N;\n                } else {\n                    i = (best_start_i + p) % N;\n                    j = best_start_j;\n                }\n                if (grid[i][j] == '.') {\n                    grid[i][j] = s[p];\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << grid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <map>\n#include <functional>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> h_id, v_id;\nint h_count = 0, v_count = 0;\n\nint flatten(int r, int c) {\n    return r * N + c;\n}\n\nPoint unflatten(int idx) {\n    return {idx / N, idx % N};\n}\n\nint get_cost(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N || grid[r][c] == '#') return 1e9;\n    return grid[r][c] - '0';\n}\n\n// Reconstruct path from parents\nstring reconstruct_path(int start_node, int end_node, const vector<int>& parent) {\n    if (start_node == end_node) return \"\";\n    vector<int> path;\n    int curr = end_node;\n    while (curr != start_node) {\n        if (curr == -1) return \"\";\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    \n    string res = \"\";\n    int curr_r = start_node / N;\n    int curr_c = start_node % N;\n    \n    for (int node : path) {\n        int nr = node / N;\n        int nc = node % N;\n        if (nr < curr_r) res += 'U';\n        else if (nr > curr_r) res += 'D';\n        else if (nc < curr_c) res += 'L';\n        else if (nc > curr_c) res += 'R';\n        curr_r = nr;\n        curr_c = nc;\n    }\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // 1. Identify Segments\n    h_id.assign(N, vector<int>(N, -1));\n    v_id.assign(N, vector<int>(N, -1));\n\n    // Horizontal\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            int start = j;\n            while (j < N && grid[i][j] != '#') j++;\n            for (int k = start; k < j; ++k) {\n                h_id[i][k] = h_count;\n            }\n            h_count++;\n        }\n    }\n\n    // Vertical\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            int start = i;\n            while (i < N && grid[i][j] != '#') i++;\n            for (int k = start; k < i; ++k) {\n                v_id[k][j] = v_count;\n            }\n            v_count++;\n        }\n    }\n\n    // 2. Build Bipartite Graph\n    vector<pair<int, int>> edges; \n    vector<Point> edge_to_point;\n    map<pair<int, int>, int> edge_index;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                int h = h_id[i][j];\n                int v = v_id[i][j];\n                if (edge_index.find({h, v}) == edge_index.end()) {\n                    edge_index[{h, v}] = (int)edges.size();\n                    edges.push_back({h, v});\n                    edge_to_point.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> bip_adj(h_count);\n    for (auto& e : edges) {\n        bip_adj[e.first].push_back(e.second);\n    }\n\n    // 3. Max Bipartite Matching (DFS)\n    vector<int> match_h(h_count, -1), match_v(v_count, -1);\n\n    function<bool(int, vector<bool>&)> dfs = [&](int u, vector<bool>& visited) {\n        for (int v : bip_adj[u]) {\n            if (visited[v]) continue;\n            visited[v] = true;\n            if (match_v[v] < 0 || dfs(match_v[v], visited)) {\n                match_h[u] = v;\n                match_v[v] = u;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    for (int i = 0; i < h_count; ++i) {\n        vector<bool> visited(v_count, false);\n        dfs(i, visited);\n    }\n\n    // 4. Construct Edge Cover\n    vector<bool> h_covered(h_count, false);\n    vector<bool> v_covered(v_count, false);\n    vector<bool> edge_in_cover(edges.size(), false);\n    vector<Point> selected_points;\n\n    // Add matching edges\n    for (int i = 0; i < h_count; ++i) {\n        if (match_h[i] != -1) {\n            auto it = edge_index.find({i, match_h[i]});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[match_h[i]] = true;\n            }\n        }\n    }\n\n    // Cover unmatched H\n    for (int i = 0; i < h_count; ++i) {\n        if (!h_covered[i] && !bip_adj[i].empty()) {\n            int v = bip_adj[i][0];\n            auto it = edge_index.find({i, v});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[v] = true;\n            }\n        }\n    }\n    // Cover unmatched V\n    for (int i = 0; i < v_count; ++i) {\n        if (!v_covered[i]) {\n            for (size_t j = 0; j < edges.size(); ++j) {\n                if (edges[j].second == i) {\n                    edge_in_cover[j] = true;\n                    v_covered[i] = true;\n                    h_covered[edges[j].first] = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    for (size_t i = 0; i < edges.size(); ++i) {\n        if (edge_in_cover[i]) {\n            selected_points.push_back(edge_to_point[i]);\n        }\n    }\n\n    // Add start point\n    Point start_p = {si, sj};\n    bool start_present = false;\n    for (auto& p : selected_points) {\n        if (p == start_p) {\n            start_present = true;\n            break;\n        }\n    }\n    if (!start_present) selected_points.push_back(start_p);\n\n    int K = (int)selected_points.size();\n    vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n    vector<vector<int>> parents(K, vector<int>(N * N, -1));\n\n    // 5. All-Pairs Shortest Paths\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < K; ++i) {\n        int sr = selected_points[i].r;\n        int sc = selected_points[i].c;\n        int start_node = flatten(sr, sc);\n        \n        vector<long long> d(N * N, -1);\n        vector<int> p(N * N, -1);\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n\n        d[start_node] = 0;\n        pq.push({0, start_node});\n\n        while (!pq.empty()) {\n            auto [dist_val, u] = pq.top();\n            pq.pop();\n\n            if (d[u] != -1 && dist_val > d[u]) continue;\n\n            Point pu = unflatten(u);\n            for (int k = 0; k < 4; ++k) {\n                int nr = pu.r + dr[k];\n                int nc = pu.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                    int v = flatten(nr, nc);\n                    long long new_dist = dist_val + get_cost(nr, nc);\n                    if (d[v] == -1 || new_dist < d[v]) {\n                        d[v] = new_dist;\n                        p[v] = u;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n        \n        for (int j = 0; j < K; ++j) {\n            int tr = selected_points[j].r;\n            int tc = selected_points[j].c;\n            int t_node = flatten(tr, tc);\n            dist_mat[i][j] = d[t_node];\n        }\n        parents[i] = p;\n    }\n\n    // 6. TSP\n    int start_idx = -1;\n    for(int i = 0; i < K; ++i) {\n        if(selected_points[i] == start_p) {\n            start_idx = i;\n            break;\n        }\n    }\n    \n    // Nearest Neighbor\n    vector<int> tour;\n    vector<bool> visited(K, false);\n    int curr = start_idx;\n    tour.push_back(curr);\n    visited[curr] = true;\n    \n    for (int i = 0; i < K - 1; ++i) {\n        int next = -1;\n        long long min_d = -1;\n        for (int j = 0; j < K; ++j) {\n            if (!visited[j]) {\n                if (next == -1 || dist_mat[curr][j] < min_d) {\n                    min_d = dist_mat[curr][j];\n                    next = j;\n                }\n            }\n        }\n        if (next != -1) {\n            tour.push_back(next);\n            visited[next] = true;\n            curr = next;\n        }\n    }\n    \n    // 2-opt\n    bool improved = true;\n    int iterations = 0;\n    while (improved && iterations < 2000) {\n        improved = false;\n        iterations++;\n        for (int i = 0; i < K - 1; ++i) {\n            for (int j = i + 1; j < K; ++j) {\n                if (i + 1 >= j) continue;\n                \n                int u = tour[i];\n                int v = tour[i+1];\n                int x = tour[j];\n                int y = tour[(j+1)%K];\n                \n                if (dist_mat[u][x] == -1 || dist_mat[v][y] == -1) continue;\n                if (dist_mat[u][v] == -1 || dist_mat[x][y] == -1) continue;\n\n                long long old_cost = dist_mat[u][v] + dist_mat[x][y];\n                long long new_cost = dist_mat[u][x] + dist_mat[v][y];\n                \n                if (new_cost < old_cost) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Reconstruct Full Path\n    string final_path = \"\";\n    for (int i = 0; i < K; ++i) {\n        int u = tour[i];\n        int v = tour[(i + 1) % K];\n        string segment = reconstruct_path(flatten(selected_points[u].r, selected_points[u].c), \n                                          flatten(selected_points[v].r, selected_points[v].c), \n                                          parents[u]);\n        final_path += segment;\n    }\n\n    cout << final_path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Maximum number of tasks as per constraints\nconst int MAX_N = 1005;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int in_degree = 0;\n    vector<int> dependents; \n    int priority = 0; \n    int status = -1; // -1: not started, 0: running, 1: done\n    int assigned_member = -1;\n};\n\nstruct Member {\n    int id;\n    vector<int> s; \n    int busy_until = 0; \n    int current_task = -1;\n    int start_day = 0;\n    int tasks_completed = 0;\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, K, R;\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // 1-based indexing for tasks\n    vector<Task> tasks(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int j = 0; j < K; ++j) {\n            cin >> tasks[i].d[j];\n        }\n    }\n\n    // Read dependencies\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        tasks[v].in_degree++;\n        tasks[u].dependents.push_back(v);\n    }\n\n    // Compute priority (downstream count) using bitsets for reachability\n    // Since u < v, we can process in reverse order to propagate reachability\n    vector<bitset<MAX_N>> reach(N + 1);\n    for (int i = N; i >= 1; --i) {\n        reach[i][i] = 1;\n        for (int v : tasks[i].dependents) {\n            reach[i] |= reach[v];\n        }\n        tasks[i].priority = (int)reach[i].count();\n    }\n\n    // Initialize members\n    vector<Member> members(M + 1);\n    for (int j = 1; j <= M; ++j) {\n        members[j].id = j;\n        members[j].s.assign(K, 0); // Initialize skill estimates to 0\n        members[j].busy_until = 0;\n    }\n\n    // Initial ready tasks (in_degree == 0)\n    vector<int> ready_tasks;\n    ready_tasks.reserve(N);\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            ready_tasks.push_back(i);\n        }\n    }\n\n    int current_day = 0;\n    const double ALPHA_BASE = 0.5;\n\n    while (true) {\n        current_day++;\n        \n        // 1. Decide assignments for free members\n        vector<pair<int, int>> assignments;\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int j = 1; j <= M; ++j) {\n            if (members[j].busy_until < current_day) {\n                free_members.push_back(j);\n            }\n        }\n\n        if (!free_members.empty() && !ready_tasks.empty()) {\n            // Filter ready_tasks to get valid candidates (status == -1)\n            vector<int> candidates;\n            candidates.reserve(ready_tasks.size());\n            for (int t_idx : ready_tasks) {\n                if (tasks[t_idx].status == -1) {\n                    candidates.push_back(t_idx);\n                }\n            }\n            \n            // Sort candidates by priority (descending) to schedule critical tasks first\n            sort(candidates.begin(), candidates.end(), [&](int a, int b) {\n                return tasks[a].priority > tasks[b].priority;\n            });\n\n            for (int t_idx : candidates) {\n                if (tasks[t_idx].status != -1) continue; \n                if (free_members.empty()) break;\n\n                int best_m = -1;\n                int min_t = 2000000000;\n                \n                // Find best member for this task based on estimated completion time\n                for (int m_idx : free_members) {\n                    int w = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                            w += tasks[t_idx].d[k] - members[m_idx].s[k];\n                        }\n                    }\n                    // Estimated time: if w=0 then 1, else approx w (ignoring noise for estimation)\n                    int t_est = max(1, w); \n                    if (t_est < min_t) {\n                        min_t = t_est;\n                        best_m = m_idx;\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_idx});\n                    tasks[t_idx].status = 0; // Running\n                    tasks[t_idx].assigned_member = best_m;\n                    members[best_m].busy_until = current_day + min_t - 1;\n                    members[best_m].current_task = t_idx;\n                    members[best_m].start_day = current_day;\n                    \n                    // Remove from free_members list\n                    for (auto it = free_members.begin(); it != free_members.end(); ++it) {\n                        if (*it == best_m) {\n                            free_members.erase(it);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << \"\\n\";\n        cout.flush();\n\n        // 2. Read completion info from Judge\n        int n_fin;\n        cin >> n_fin;\n        if (n_fin == -1) {\n            break;\n        }\n\n        vector<int> finished_members(n_fin);\n        for (int i = 0; i < n_fin; ++i) {\n            cin >> finished_members[i];\n        }\n\n        // 3. Update state and Skill Estimates\n        for (int m_idx : finished_members) {\n            int t_idx = members[m_idx].current_task;\n            if (t_idx == -1) continue; \n\n            // Calculate actual duration\n            int duration = current_day - members[m_idx].start_day + 1;\n            int t_obs = duration;\n            \n            // Skill Update Logic\n            // Model: t \u2248 1 + sum(max(0, d_k - s_k))\n            // We perform gradient descent on s_k to minimize (t_obs - t_pred)^2\n            int w_pred = 0;\n            vector<int> active_dims;\n            active_dims.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                    w_pred += tasks[t_idx].d[k] - members[m_idx].s[k];\n                    active_dims.push_back(k);\n                }\n            }\n            int t_pred = (w_pred == 0) ? 1 : w_pred;\n            \n            double error = (double)t_obs - t_pred;\n            \n            // Only update if there are active dimensions (deficits)\n            // If w_pred == 0 and t_obs > 1, it's likely noise, so we skip update to avoid destabilizing s_k >= d_k\n            if (!active_dims.empty()) {\n                // Learning rate decays with number of tasks completed\n                double alpha = ALPHA_BASE / sqrt(max(1, members[m_idx].tasks_completed + 1));\n                double update_per_dim = alpha * error / active_dims.size();\n                \n                for (int k : active_dims) {\n                    // If t_obs > t_pred (error > 0), we underestimated time -> overestimated skills -> decrease s_k\n                    // If t_obs < t_pred (error < 0), we overestimated time -> underestimated skills -> increase s_k\n                    // Update: s_new = s_old - alpha * error\n                    double new_s = members[m_idx].s[k] - update_per_dim;\n                    members[m_idx].s[k] = (int)round(new_s);\n                    if (members[m_idx].s[k] < 0) members[m_idx].s[k] = 0;\n                }\n            }\n\n            // Update Task Status\n            tasks[t_idx].status = 1; // Done\n            members[m_idx].current_task = -1;\n            members[m_idx].tasks_completed++;\n\n            // Update Dependencies\n            for (int v : tasks[t_idx].dependents) {\n                tasks[v].in_degree--;\n                if (tasks[v].in_degree == 0) {\n                    ready_tasks.push_back(v);\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n};\n\ninline int manhattan(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nconst Point CENTER = {400, 400};\nvector<Order> orders(1000);\nPoint pickups[1000], deliveries[1000];\n\n// Path: sequence of 100 nodes (50 pickups + 50 deliveries)\n// Each node: (order_id, type) where type 0=pickup, 1=delivery\nstruct Node {\n    int order_id;\n    int type; // 0=pickup, 1=delivery\n};\n\nvector<Node> path;\nbool selected[1000];\n\nint calc_cost(const vector<Node>& p) {\n    int cost = 0;\n    Point prev = CENTER;\n    for (const auto& node : p) {\n        Point curr = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cost += manhattan(prev, curr);\n        prev = curr;\n    }\n    cost += manhattan(prev, CENTER);\n    return cost;\n}\n\n// Validate path: each selected order has pickup before delivery\nbool validate_path(const vector<Node>& p, const bool* sel) {\n    int pickup_pos[1000];\n    fill(pickup_pos, pickup_pos + 1000, -1);\n    \n    for (int i = 0; i < 100; ++i) {\n        if (p[i].type == 0) {\n            pickup_pos[p[i].order_id] = i;\n        } else {\n            if (pickup_pos[p[i].order_id] == -1) return false;\n            if (pickup_pos[p[i].order_id] >= i) return false;\n        }\n    }\n    \n    // Check all selected orders are in path\n    for (int i = 0; i < 1000; ++i) {\n        if (sel[i]) {\n            if (pickup_pos[i] == -1) return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read input\n    for (int i = 0; i < 1000; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        pickups[i] = {orders[i].ax, orders[i].ay};\n        deliveries[i] = {orders[i].cx, orders[i].cy};\n    }\n    \n    mt19937 rng(1337);\n    \n    // Initial selection: pick 50 orders with smallest round-trip cost\n    vector<pair<int, int>> scores;\n    scores.reserve(1000);\n    for (int i = 0; i < 1000; ++i) {\n        int score = manhattan(CENTER, pickups[i]) + \n                    manhattan(pickups[i], deliveries[i]) + \n                    manhattan(deliveries[i], CENTER);\n        scores.push_back({score, i});\n    }\n    sort(scores.begin(), scores.end());\n    \n    fill(selected, selected + 1000, false);\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected[scores[i].second] = true;\n        selected_orders.push_back(scores[i].second);\n    }\n    \n    // Initial path: sort by angle from center, pickup then delivery for each\n    vector<pair<double, int>> angled;\n    angled.reserve(50);\n    for (int oid : selected_orders) {\n        int mx = (pickups[oid].x + deliveries[oid].x) / 2;\n        int my = (pickups[oid].y + deliveries[oid].y) / 2;\n        double angle = atan2(my - 400, mx - 400);\n        angled.push_back({angle, oid});\n    }\n    sort(angled.begin(), angled.end());\n    \n    path.clear();\n    path.reserve(100);\n    for (const auto& p : angled) {\n        path.push_back({p.second, 0}); // pickup\n        path.push_back({p.second, 1}); // delivery\n    }\n    \n    int best_cost = calc_cost(path);\n    vector<Node> best_path = path;\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.90;\n    \n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    uniform_int_distribution<int> dist_idx(0, 98);\n    \n    double temp = 5000.0;\n    int iter = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        temp *= 0.99995;\n        if (temp < 0.5) temp = 0.5;\n        \n        // Operation: swap two nodes while maintaining constraints\n        int i = dist_idx(rng);\n        int j = dist_idx(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        \n        // Ensure j > i\n        if (j <= i) { j = i + 1; if (j >= 100) { i = 98; j = 99; } }\n        \n        Node ni = path[i];\n        Node nj = path[j];\n        \n        // Find positions of complementary nodes\n        int ni_comp = -1, nj_comp = -1;\n        for (int k = 0; k < 100; ++k) {\n            if (k == i || k == j) continue;\n            if (path[k].order_id == ni.order_id) ni_comp = k;\n            if (path[k].order_id == nj.order_id) nj_comp = k;\n        }\n        \n        // Check if swap is valid\n        bool valid = true;\n        \n        // After swap: ni goes to position j, nj goes to position i\n        // For ni: if it's pickup (0), need comp (delivery) to be after j\n        //         if it's delivery (1), need comp (pickup) to be before j\n        if (ni.type == 0) { // pickup moving to j\n            if (ni_comp != -1 && ni_comp < j) valid = false;\n        } else { // delivery moving to j\n            if (ni_comp != -1 && ni_comp > j) valid = false;\n        }\n        \n        if (valid && nj.type == 0) { // pickup moving to i\n            if (nj_comp != -1 && nj_comp < i) valid = false;\n        } else if (valid) { // delivery moving to i\n            if (nj_comp != -1 && nj_comp > i) valid = false;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate delta cost (only affected edges)\n        auto get_point = [&](int idx, const vector<Node>& p) -> Point {\n            if (idx < 0 || idx >= 100) return CENTER;\n            if (p[idx].type == 0) return pickups[p[idx].order_id];\n            return deliveries[p[idx].order_id];\n        };\n        \n        int delta = 0;\n        \n        // Edges affected: (i-1,i), (i,i+1), (j-1,j), (j,j+1)\n        // But need to handle adjacency carefully\n        \n        vector<int> affected;\n        if (i > 0) affected.push_back(i - 1);\n        affected.push_back(i);\n        if (i < 99) affected.push_back(i + 1);\n        if (j > 0 && j - 1 != i) affected.push_back(j - 1);\n        if (j < 99 && j != i + 1) affected.push_back(j);\n        if (j < 99) affected.push_back(j + 1);\n        \n        // Remove duplicates and sort\n        sort(affected.begin(), affected.end());\n        affected.erase(unique(affected.begin(), affected.end()), affected.end());\n        \n        // Calculate old cost for affected edges\n        int old_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, path);\n                Point p2 = get_point(k + 1, path);\n                old_cost += manhattan(p1, p2);\n            }\n        }\n        \n        // Create new path (just for these positions)\n        vector<Node> new_path = path;\n        swap(new_path[i], new_path[j]);\n        \n        // Calculate new cost for affected edges\n        int new_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, new_path);\n                Point p2 = get_point(k + 1, new_path);\n                new_cost += manhattan(p1, p2);\n            }\n        }\n        \n        delta = new_cost - old_cost;\n        \n        if (delta < 0 || dist_01(rng) < exp(-delta / temp)) {\n            swap(path[i], path[j]);\n            int cur_cost = calc_cost(path);\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_path = path;\n            }\n        }\n        \n        iter++;\n        if (iter % 10000 == 0) {\n            // Occasionally try a different initialization\n            if (dist_01(rng) < 0.1) {\n                // Shuffle and rebuild\n                shuffle(selected_orders.begin(), selected_orders.end(), rng);\n                path.clear();\n                for (int oid : selected_orders) {\n                    path.push_back({oid, 0});\n                    path.push_back({oid, 1});\n                }\n                int c = calc_cost(path);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_path = path;\n                }\n            }\n        }\n    }\n    \n    // Final validation\n    if (!validate_path(best_path, selected)) {\n        // Rebuild path from selected orders\n        path.clear();\n        for (int i = 0; i < 1000; ++i) {\n            if (selected[i]) {\n                path.push_back({i, 0});\n                path.push_back({i, 1});\n            }\n        }\n        best_path = path;\n        best_cost = calc_cost(best_path);\n    }\n    \n    // Output\n    cout << 50;\n    for (int i = 0; i < 1000; ++i) {\n        if (selected[i]) cout << \" \" << (i + 1);\n    }\n    cout << \"\\n\";\n    \n    cout << 102;\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    for (const auto& node : best_path) {\n        Point p = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Disjoint Set Union with path compression and union by rank\nstruct DSU {\n    vector<int> parent, rank_, size_;\n    int components;\n    \n    DSU(int n) : parent(n), rank_(n, 0), size_(n, 1), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    \n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        size_[x] += size_[y];\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        components--;\n        return true;\n    }\n    \n    int getSize(int x) {\n        return size_[find(x)];\n    }\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    // Read vertex coordinates\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    // Read edge endpoints and precompute expected distances\n    vector<pair<int, int>> edges(M);\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n        int u = edges[i].first, v = edges[i].second;\n        double dist = hypot(coords[u].first - coords[v].first, \n                           coords[u].second - coords[v].second);\n        d[i] = (int)round(dist);\n    }\n    \n    DSU dsu(N);\n    \n    // Process each edge online\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first, v = edges[i].second;\n        int remaining = M - 1 - i;  // Edges after this one (including current = remaining + 1)\n        int needed = dsu.components - 1;  // Minimum edges needed for connectivity\n        \n        bool connects = (dsu.find(u) != dsu.find(v));\n        bool accept = false;\n        \n        if (connects) {\n            // Edge quality ratio (actual length / minimum possible length)\n            double ratio = (double)l / max(1, d[i]);\n            \n            // Connectivity urgency: how critical is it to accept connecting edges?\n            // Use remaining + 1 to include current edge in available count\n            int available = remaining + 1;\n            double urgency = (double)needed / max(1, available);\n            \n            // Progress through the edge stream (0.0 to 1.0)\n            double progress = (double)i / (M - 1);\n            \n            // Base threshold: expected value is 2.0, max is 3.0\n            // We want to accept edges with ratio <= threshold\n            double threshold = 2.3;\n            \n            // Phase 1: Early phase (first 30%) - be selective but not too aggressive\n            if (progress < 0.3) {\n                threshold = 2.0 + urgency * 0.5;\n            }\n            // Phase 2: Middle phase (30-60%) - moderate selectivity\n            else if (progress < 0.6) {\n                threshold = 2.2 + urgency * 0.6;\n            }\n            // Phase 3: Late phase (60-80%) - prioritize connectivity\n            else if (progress < 0.8) {\n                threshold = 2.5 + urgency * 0.5;\n            }\n            // Phase 4: Critical phase (80%+) - very aggressive on connectivity\n            else {\n                threshold = 2.8 + urgency * 0.2;\n            }\n            \n            // Safety mechanism 1: Large buffer when running low on edges\n            // With M=1995 and N=400, we need 399 edges minimum\n            // But many edges will be redundant, so we need significant buffer\n            int safety_margin = 80;\n            if (available <= needed + safety_margin) {\n                threshold = 3.0;  // Accept any connecting edge\n            }\n            \n            // Safety mechanism 2: Critical zone - must accept all connecting edges\n            if (available <= needed + 30) {\n                accept = true;\n            }\n            // Safety mechanism 3: Very urgent - almost always accept\n            else if (urgency > 0.6) {\n                threshold = 3.0;\n            }\n            // Safety mechanism 4: Moderate urgency\n            else if (urgency > 0.4) {\n                threshold = max(threshold, 2.7);\n            }\n            \n            // Apply threshold if not already forced to accept\n            if (!accept && ratio <= threshold) {\n                accept = true;\n            }\n            \n            // Component size bonus: prefer edges connecting larger components\n            // This helps reduce components faster\n            if (!accept && connects) {\n                int combined_size = dsu.getSize(u) + dsu.getSize(v);\n                if (combined_size > N / 2 && ratio <= threshold + 0.3) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept && connects) {\n            dsu.unite(u, v);\n            cout << 1 << \"\\n\";\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        cout.flush();  // Ensure output is sent immediately\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nclass Solver {\nprivate:\n    int N, M;\n    vector<Position> petPos;\n    vector<int> petType;\n    vector<Position> humanPos;\n    vector<vector<bool>> impassable;\n    vector<vector<bool>> humanTarget;\n    \n    bool isValid(int x, int y) const {\n        return x >= 1 && x <= GRID_SIZE && y >= 1 && y <= GRID_SIZE;\n    }\n    \n    bool isPassable(int x, int y) const {\n        if (!isValid(x, y)) return false;\n        return !impassable[x-1][y-1];\n    }\n    \n    bool hasPetAdjacent(int x, int y) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (const auto& pet : petPos) {\n                    if (pet.x == nx && pet.y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    bool hasHumanAdjacent(int x, int y, int excludeIdx = -1) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (int i = 0; i < M; i++) {\n                    if (i == excludeIdx) continue;\n                    if (humanPos[i].x == nx && humanPos[i].y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    vector<vector<bool>> computeReachable(const Position& start) const {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        queue<Position> q;\n        \n        if (isPassable(start.x, start.y)) {\n            visited[start.x-1][start.y-1] = true;\n            q.push(start);\n        }\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        \n        while (!q.empty()) {\n            Position cur = q.front();\n            q.pop();\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = cur.x + dx[d], ny = cur.y + dy[d];\n                if (isPassable(nx, ny) && !visited[nx-1][ny-1]) {\n                    visited[nx-1][ny-1] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        \n        return visited;\n    }\n    \n    int countPetsInRegion(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (const auto& pet : petPos) {\n            if (region[pet.x-1][pet.y-1]) {\n                count++;\n            }\n        }\n        return count;\n    }\n    \n    int countReachable(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (region[i][j]) count++;\n            }\n        }\n        return count;\n    }\n    \n    // Calculate minimum distance from position to any pet\n    int minPetDistance(int x, int y) const {\n        int minDist = 1000;\n        for (const auto& pet : petPos) {\n            int dist = abs(pet.x - x) + abs(pet.y - y);\n            minDist = min(minDist, dist);\n        }\n        return minDist;\n    }\n    \n    // Check if blocking this square would help create a partition\n    double evaluateBlockScore(int x, int y, int humanIdx) const {\n        double score = 0;\n        \n        // Base score for blocking\n        score += 100;\n        \n        // Bonus for being far from pets (safer)\n        int petDist = minPetDistance(x, y);\n        score += petDist * 5;\n        \n        // Bonus for continuing existing walls\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int wallCount = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny) && impassable[nx-1][ny-1]) {\n                wallCount++;\n            }\n        }\n        score += wallCount * 20;\n        \n        // Prefer edges and corners for better partitioning\n        if (x == 1 || x == GRID_SIZE || y == 1 || y == GRID_SIZE) {\n            score += 15;\n        }\n        if ((x == 1 || x == GRID_SIZE) && (y == 1 || y == GRID_SIZE)) {\n            score += 10;\n        }\n        \n        // Penalize if too close to this human (want to expand)\n        int humanDist = abs(x - humanPos[humanIdx].x) + abs(y - humanPos[humanIdx].y);\n        if (humanDist < 3) {\n            score -= (3 - humanDist) * 10;\n        }\n        \n        return score;\n    }\n    \n    // Evaluate move score\n    double evaluateMoveScore(int newX, int newY, int humanIdx) const {\n        double score = 0;\n        \n        // Count potential blocking opportunities from new position\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int blockOptions = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = newX + dx[d], ny = newY + dy[d];\n            if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !hasPetAdjacent(nx, ny)) {\n                blockOptions++;\n            }\n        }\n        score += blockOptions * 30;\n        \n        // Distance from pets\n        int petDist = minPetDistance(newX, newY);\n        score += petDist * 3;\n        \n        // Spread humans out\n        for (int i = 0; i < M; i++) {\n            if (i == humanIdx) continue;\n            int dist = abs(newX - humanPos[i].x) + abs(newY - humanPos[i].y);\n            if (dist < 5) {\n                score -= (5 - dist) * 5;\n            }\n        }\n        \n        return score;\n    }\n    \npublic:\n    void readInput() {\n        cin >> N;\n        petPos.resize(N);\n        petType.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petPos[i].x >> petPos[i].y >> petType[i];\n        }\n        \n        cin >> M;\n        humanPos.resize(M);\n        for (int i = 0; i < M; i++) {\n            cin >> humanPos[i].x >> humanPos[i].y;\n        }\n        \n        impassable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        humanTarget.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    }\n    \n    void readPetMoves() {\n        for (int i = 0; i < N; i++) {\n            string move;\n            cin >> move;\n            if (move != \".\") {\n                int x = petPos[i].x, y = petPos[i].y;\n                for (char c : move) {\n                    int nx = x, ny = y;\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    \n                    if (isValid(nx, ny) && isPassable(nx, ny)) {\n                        x = nx;\n                        y = ny;\n                    }\n                }\n                petPos[i] = {x, y};\n            }\n        }\n    }\n    \n    string decideActions(int turn) {\n        string actions(M, '.');\n        \n        // Track which squares will be blocked this turn (to avoid conflicts)\n        vector<vector<bool>> willBlock(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        char blockChars[] = {'u', 'd', 'l', 'r'};\n        char moveChars[] = {'U', 'D', 'L', 'R'};\n        \n        // First pass: identify best blocking opportunities\n        vector<pair<double, int>> humanScores(M);\n        for (int i = 0; i < M; i++) {\n            int x = humanPos[i].x, y = humanPos[i].y;\n            double bestScore = -1e18;\n            int bestD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1]) {\n                    if (!hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                        double score = evaluateBlockScore(nx, ny, i);\n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestD = d;\n                        }\n                    }\n                }\n            }\n            \n            humanScores[i] = {bestScore, bestD};\n        }\n        \n        // Second pass: execute actions (prioritize high-score humans)\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return humanScores[a].first > humanScores[b].first;\n        });\n        \n        for (int idx : order) {\n            int i = idx;\n            int x = humanPos[i].x, y = humanPos[i].y;\n            int bestD = humanScores[i].second;\n            \n            if (bestD >= 0) {\n                int nx = x + dx[bestD], ny = y + dy[bestD];\n                // Double check it's still available\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1] &&\n                    !hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                    actions[i] = blockChars[bestD];\n                    impassable[nx-1][ny-1] = true;\n                    willBlock[nx-1][ny-1] = true;\n                    continue;\n                }\n            }\n            \n            // Try to move to better position\n            double bestMoveScore = -1e18;\n            int bestMoveD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && isPassable(nx, ny)) {\n                    // Check if this square won't be blocked by others\n                    bool willBeBlocked = false;\n                    for (int j = 0; j < M; j++) {\n                        if (j == i) continue;\n                        int jd = humanScores[j].second;\n                        if (jd >= 0) {\n                            int tx = humanPos[j].x + dx[jd], ty = humanPos[j].y + dy[jd];\n                            if (tx == nx && ty == ny) {\n                                willBeBlocked = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (!willBeBlocked) {\n                        double score = evaluateMoveScore(nx, ny, i);\n                        if (score > bestMoveScore) {\n                            bestMoveScore = score;\n                            bestMoveD = d;\n                        }\n                    }\n                }\n            }\n            \n            if (bestMoveD >= 0 && bestMoveScore > 0) {\n                actions[i] = moveChars[bestMoveD];\n                humanPos[i].x += dx[bestMoveD];\n                humanPos[i].y += dy[bestMoveD];\n            }\n        }\n        \n        return actions;\n    }\n    \n    void solve() {\n        readInput();\n        \n        for (int turn = 0; turn < MAX_TURNS; turn++) {\n            string actions = decideActions(turn);\n            cout << actions << endl;\n            \n            if (turn < MAX_TURNS - 1) {\n                readPetMoves();\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}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 20;\nconst int MAX_STEPS = 200;\n\nstruct Problem {\n    int si, sj, ti, tj;\n    double p;\n    vector<string> h; // horizontal walls: h[i][j] = wall between (i,j) and (i,j+1)\n    vector<string> v; // vertical walls: v[i][j] = wall between (i,j) and (i+1,j)\n};\n\n// Direction vectors: U, D, L, R\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dirChar[4] = {'U', 'D', 'L', 'R'};\n\nbool canMove(const Problem& prob, int i, int j, int dir) {\n    int ni = i + di[dir];\n    int nj = j + dj[dir];\n    \n    // Check bounds\n    if (ni < 0 || ni >= GRID_SIZE || nj < 0 || nj >= GRID_SIZE) return false;\n    \n    // Check walls\n    if (dir == 0) { // U\n        if (prob.v[ni][j] == '1') return false;\n    } else if (dir == 1) { // D\n        if (prob.v[i][j] == '1') return false;\n    } else if (dir == 2) { // L\n        if (prob.h[i][nj] == '1') return false;\n    } else { // R\n        if (prob.h[i][j] == '1') return false;\n    }\n    return true;\n}\n\npair<int, int> movePos(int i, int j, int dir) {\n    return {i + di[dir], j + dj[dir]};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Problem prob;\n    cin >> prob.si >> prob.sj >> prob.ti >> prob.tj >> prob.p;\n    \n    prob.h.resize(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; i++) {\n        cin >> prob.h[i];\n    }\n    \n    prob.v.resize(GRID_SIZE - 1);\n    for (int i = 0; i < GRID_SIZE - 1; i++) {\n        cin >> prob.v[i];\n    }\n    \n    // DP: V[i][j][k] = expected score from position (i,j) with k steps remaining\n    // We use 2 layers to save memory\n    vector<vector<double>> V_cur(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    vector<vector<double>> V_next(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    \n    // Initialize: at target, remaining steps don't matter (already arrived)\n    // But we need to handle the scoring: 401 - t where t is arrival time\n    // If we're at target with k steps remaining in a L-step path, arrival was at step L-k\n    // Score = 401 - (L - k) = 401 - L + k\n    \n    // We'll build the path greedily, computing values backwards\n    // For path length L, V[i][j][k] = expected score with k steps remaining\n    \n    // Strategy: Try different path lengths and pick the best\n    string bestPath = \"\";\n    double bestScore = 0.0;\n    \n    for (int pathLen = 50; pathLen <= MAX_STEPS; pathLen += 5) {\n        // Initialize value function for 0 remaining steps\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                V_cur[i][j] = 0.0; // Can't reach target with 0 steps if not already there\n            }\n        }\n        V_cur[prob.ti][prob.tj] = 401.0 - pathLen; // Arrived exactly at last step\n        \n        // Backward DP\n        for (int k = 1; k <= pathLen; k++) {\n            for (int i = 0; i < GRID_SIZE; i++) {\n                for (int j = 0; j < GRID_SIZE; j++) {\n                    if (i == prob.ti && j == prob.tj) {\n                        // Already at target, score based on when we arrived\n                        V_next[i][j] = 401.0 - (pathLen - k);\n                        continue;\n                    }\n                    \n                    double bestVal = 0.0;\n                    for (int dir = 0; dir < 4; dir++) {\n                        double val = 0.0;\n                        int ni = i + di[dir];\n                        int nj = j + dj[dir];\n                        \n                        // With probability p: stay (forget)\n                        val += prob.p * V_cur[i][j];\n                        \n                        // With probability 1-p: try to move\n                        if (canMove(prob, i, j, dir)) {\n                            val += (1.0 - prob.p) * V_cur[ni][nj];\n                        } else {\n                            val += (1.0 - prob.p) * V_cur[i][j];\n                        }\n                        \n                        bestVal = max(bestVal, val);\n                    }\n                    V_next[i][j] = bestVal;\n                }\n            }\n            swap(V_cur, V_next);\n        }\n        \n        double startScore = V_cur[prob.si][prob.sj];\n        \n        // If this is better, construct the path\n        if (startScore > bestScore) {\n            bestScore = startScore;\n            \n            // Reconstruct path greedily\n            // Need to recompute DP to get the policy\n            vector<vector<vector<double>>> V_all(pathLen + 1, \n                vector<vector<double>>(GRID_SIZE, vector<double>(GRID_SIZE, 0.0)));\n            \n            // Initialize\n            for (int i = 0; i < GRID_SIZE; i++) {\n                for (int j = 0; j < GRID_SIZE; j++) {\n                    V_all[0][i][j] = 0.0;\n                }\n            }\n            V_all[0][prob.ti][prob.tj] = 401.0 - pathLen;\n            \n            // Forward DP (backwards in time)\n            for (int k = 1; k <= pathLen; k++) {\n                for (int i = 0; i < GRID_SIZE; i++) {\n                    for (int j = 0; j < GRID_SIZE; j++) {\n                        if (i == prob.ti && j == prob.tj) {\n                            V_all[k][i][j] = 401.0 - (pathLen - k);\n                            continue;\n                        }\n                        \n                        double bestVal = 0.0;\n                        for (int dir = 0; dir < 4; dir++) {\n                            double val = 0.0;\n                            int ni = i + di[dir];\n                            int nj = j + dj[dir];\n                            \n                            val += prob.p * V_all[k-1][i][j];\n                            \n                            if (canMove(prob, i, j, dir)) {\n                                val += (1.0 - prob.p) * V_all[k-1][ni][nj];\n                            } else {\n                                val += (1.0 - prob.p) * V_all[k-1][i][j];\n                            }\n                            \n                            bestVal = max(bestVal, val);\n                        }\n                        V_all[k][i][j] = bestVal;\n                    }\n                }\n            }\n            \n            // Greedy path construction\n            string path = \"\";\n            int ci = prob.si, cj = prob.sj;\n            int remaining = pathLen;\n            \n            while (remaining > 0 && (ci != prob.ti || cj != prob.tj)) {\n                int bestDir = 1; // Default D (towards target)\n                double bestVal = -1e18;\n                \n                for (int dir = 0; dir < 4; dir++) {\n                    double val = 0.0;\n                    int ni = ci + di[dir];\n                    int nj = cj + dj[dir];\n                    \n                    val += prob.p * V_all[remaining - 1][ci][cj];\n                    \n                    if (canMove(prob, ci, cj, dir)) {\n                        val += (1.0 - prob.p) * V_all[remaining - 1][ni][nj];\n                    } else {\n                        val += (1.0 - prob.p) * V_all[remaining - 1][ci][cj];\n                    }\n                    \n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestDir = dir;\n                    }\n                }\n                \n                path += dirChar[bestDir];\n                \n                // Update position (accounting for possible forget/wall)\n                // For path construction, we assume successful move for simplicity\n                // The actual execution is stochastic\n                int ni = ci + di[bestDir];\n                int nj = cj + dj[bestDir];\n                if (canMove(prob, ci, cj, bestDir)) {\n                    ci = ni;\n                    cj = nj;\n                }\n                \n                remaining--;\n            }\n            \n            // Fill remaining steps if needed (stay at target)\n            while (path.length() < pathLen) {\n                path += 'R'; // Arbitrary, won't matter if at target\n            }\n            \n            bestPath = path;\n        }\n    }\n    \n    // Also try a direct BFS path as baseline\n    vector<pair<int, int>> bfsPath;\n    {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n        vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n        vector<pair<int, int>> queue;\n        queue.push_back({prob.si, prob.sj});\n        visited[prob.si][prob.sj] = true;\n        \n        int head = 0;\n        while (head < (int)queue.size()) {\n            auto [ci, cj] = queue[head++];\n            if (ci == prob.ti && cj == prob.tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (canMove(prob, ci, cj, dir)) {\n                    int ni = ci + di[dir];\n                    int nj = cj + dj[dir];\n                    if (!visited[ni][nj]) {\n                        visited[ni][nj] = true;\n                        parent[ni][nj] = {ci, cj};\n                        parentDir[ni][nj] = dir;\n                        queue.push_back({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (visited[prob.ti][prob.tj]) {\n            string bfsStr = \"\";\n            int ci = prob.ti, cj = prob.tj;\n            while (ci != prob.si || cj != prob.sj) {\n                int dir = parentDir[ci][cj];\n                bfsStr += dirChar[dir];\n                auto [pi, pj] = parent[ci][cj];\n                ci = pi;\n                cj = pj;\n            }\n            reverse(bfsStr.begin(), bfsStr.end());\n            \n            // Pad to reasonable length for comparison\n            while (bfsStr.length() < 50) bfsStr += 'R';\n            if (bfsStr.length() < bestPath.length() || bestPath.empty()) {\n                // Evaluate BFS path\n                // Simple heuristic: shorter path with some padding\n                if ((int)bfsStr.length() <= MAX_STEPS) {\n                    bestPath = bfsStr;\n                }\n            }\n        }\n    }\n    \n    // Ensure path is within limits\n    if ((int)bestPath.length() > MAX_STEPS) {\n        bestPath = bestPath.substr(0, MAX_STEPS);\n    }\n    \n    cout << bestPath << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entering_direction] = exiting_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0: curve\n    {3, -1, -1, 0},  // 1: curve\n    {-1, -1, 3, 2},  // 2: curve\n    {-1, 2, 1, -1},  // 3: curve\n    {1, 0, 3, 2},    // 4: double curve\n    {3, 2, 1, 0},    // 5: double curve\n    {2, -1, 0, -1},  // 6: straight\n    {-1, 3, -1, 1},  // 7: straight\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint grid[N][N];\nint rot[N][N];\n\ninline int rotate_tile(int t, int r) {\n    if (t <= 3) return (t + r) % 4;\n    else if (t <= 5) return 4 + ((t - 4 + r) % 2);\n    else return 6 + ((t - 6 + r) % 2);\n}\n\ninline int get_tile(int i, int j) {\n    return rotate_tile(grid[i][j], rot[i][j]);\n}\n\n// Fast loop tracing with step limit\nint trace_loop(int si, int sj, int sd, int max_steps = 500) {\n    int i = si, j = sj, d = sd;\n    for (int len = 1; len <= max_steps; len++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 == -1) return 0;\n        i += di[d2];\n        j += dj[d2];\n        d = (d2 + 2) % 4;\n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        if (i == si && j == sj && d == sd) return len;\n    }\n    return 0;\n}\n\n// Sample-based loop detection (faster than full scan)\npair<long long, long long> sample_loops(mt19937& rng, int samples = 200) {\n    vector<int> loops;\n    \n    for (int s = 0; s < samples; s++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        int d = rng() % 4;\n        \n        int len = trace_loop(i, j, d, 600);\n        if (len > 1) {\n            loops.push_back(len);\n        }\n    }\n    \n    // Also check strategic points (edges, corners)\n    for (int i = 0; i < N; i += 5) {\n        for (int j = 0; j < N; j += 5) {\n            for (int d = 0; d < 4; d++) {\n                int len = trace_loop(i, j, d, 600);\n                if (len > 1) loops.push_back(len);\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    // Get unique top 2\n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Full scan for final evaluation\npair<long long, long long> full_scan_loops() {\n    vector<int> loops;\n    static bool vis[N][N][4];\n    memset(vis, 0, sizeof(vis));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                if (vis[i][j][d]) continue;\n                \n                vector<tuple<int,int,int>> path;\n                int ci = i, cj = j, cd = d;\n                \n                while (ci >= 0 && ci < N && cj >= 0 && cj < N && !vis[ci][cj][cd]) {\n                    vis[ci][cj][cd] = true;\n                    path.push_back({ci, cj, cd});\n                    \n                    int t = get_tile(ci, cj);\n                    int d2 = to[t][cd];\n                    if (d2 == -1) break;\n                    \n                    ci += di[d2];\n                    cj += dj[d2];\n                    cd = (d2 + 2) % 4;\n                }\n                \n                if (ci >= 0 && ci < N && cj >= 0 && cj < N) {\n                    for (int k = 0; k < (int)path.size(); k++) {\n                        if (get<0>(path[k]) == ci && \n                            get<1>(path[k]) == cj && \n                            get<2>(path[k]) == cd) {\n                            int loop_len = path.size() - k;\n                            if (loop_len > 1) {\n                                loops.push_back(loop_len);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Evaluate connectivity score for a tile (heuristic)\nint connectivity_score(int i, int j, int r) {\n    int score = 0;\n    int old_rot = rot[i][j];\n    rot[i][j] = r;\n    \n    // Check all 4 directions\n    for (int d = 0; d < 4; d++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 != -1) {\n            int ni = i + di[d2];\n            int nj = j + dj[d2];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nt = get_tile(ni, nj);\n                int back_d = (d2 + 2) % 4;\n                if (to[nt][back_d] != -1) {\n                    score += 10;\n                }\n            }\n        }\n    }\n    \n    rot[i][j] = old_rot;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Multiple restarts with different seeds\n    long long global_best = 0;\n    int best_rot[N][N];\n    memset(best_rot, 0, sizeof(best_rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    int restart = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Leave 150ms for final output\n        if (elapsed >= 1850) break;\n        \n        // Initialize rotations\n        memset(rot, 0, sizeof(rot));\n        \n        // Smart initialization: try to create connections\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int best_r = 0;\n                int best_score = -1;\n                for (int r = 0; r < 4; r++) {\n                    int score = connectivity_score(i, j, r);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n        \n        // Add some randomness to initial configuration\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (rng() % 3 == 0) {\n                    rot[i][j] = rng() % 4;\n                }\n            }\n        }\n        \n        // Get initial score\n        auto [l1, l2] = sample_loops(rng, 100);\n        long long current_score = l1 * l2;\n        long long local_best = current_score;\n        \n        // Simulated annealing with adaptive temperature\n        double temp = 500.0;\n        int iterations = 0;\n        int no_improve = 0;\n        \n        while (elapsed < 1850) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1850) break;\n            \n            // Adaptive temperature based on time remaining\n            double time_ratio = (1850.0 - elapsed) / 1850.0;\n            temp = 500.0 * pow(time_ratio, 2.0) + 1.0;\n            \n            // Number of tiles to change (increases with temperature)\n            int num_changes = 1 + (int)(3.0 * temp / 500.0);\n            num_changes = min(num_changes, 5);\n            \n            vector<pair<int,int>> changes;\n            vector<int> old_rots;\n            \n            for (int c = 0; c < num_changes; c++) {\n                int i = rng() % N;\n                int j = rng() % N;\n                changes.push_back({i, j});\n                old_rots.push_back(rot[i][j]);\n                rot[i][j] = (old_rots.back() + 1 + rng() % 3) % 4;\n            }\n            \n            auto [nl1, nl2] = sample_loops(rng, 80);\n            long long new_score = nl1 * nl2;\n            \n            bool accept = false;\n            if (new_score >= current_score) {\n                accept = true;\n                if (new_score > local_best) {\n                    local_best = new_score;\n                    no_improve = 0;\n                    memcpy(best_rot, rot, sizeof(rot));\n                }\n            } else if (temp > 0.5) {\n                double prob = exp((double)(new_score - current_score) / temp);\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (!accept) {\n                for (int c = 0; c < num_changes; c++) {\n                    rot[changes[c].first][changes[c].second] = old_rots[c];\n                }\n            } else {\n                current_score = new_score;\n            }\n            \n            iterations++;\n            no_improve++;\n            \n            // Restart if stuck\n            if (no_improve > 5000 && restart < 3) {\n                break;\n            }\n        }\n        \n        if (local_best > global_best) {\n            global_best = local_best;\n        }\n        \n        restart++;\n    }\n    \n    // Restore best configuration\n    memcpy(rot, best_rot, sizeof(rot));\n    \n    // Final full evaluation\n    auto [fl1, fl2] = full_scan_loops();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << rot[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Direction masks: 1=left, 2=up, 4=right, 8=down\nconst int LEFT = 1, UP = 2, RIGHT = 4, DOWN = 8;\nconst int dr[4] = {-1, 1, 0, 0};  // U, D, L, R\nconst int dc[4] = {0, 0, -1, 1};\nconst char dirs[4] = {'U', 'D', 'L', 'R'};\n\nint N;\nlong long T;\nvector<vector<int>> board;\nint empty_r, empty_c;\nstring operations;\n\n// Check if two adjacent cells have matching connections\nbool connects(int r1, int c1, int r2, int c2) {\n    if (board[r1][c1] == 0 || board[r2][c2] == 0) return false;\n    \n    if (r2 == r1 + 1) {  // r2 is below r1\n        return (board[r1][c1] & DOWN) && (board[r2][c2] & UP);\n    } else if (r2 == r1 - 1) {  // r2 is above r1\n        return (board[r1][c1] & UP) && (board[r2][c2] & DOWN);\n    } else if (c2 == c1 + 1) {  // c2 is right of c1\n        return (board[r1][c1] & RIGHT) && (board[r2][c2] & LEFT);\n    } else if (c2 == c1 - 1) {  // c2 is left of c1\n        return (board[r1][c1] & LEFT) && (board[r2][c2] & RIGHT);\n    }\n    return false;\n}\n\n// Compute size of largest tree (connected component)\nint computeMaxTree() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int maxTree = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] != 0 && !visited[i][j]) {\n                int treeSize = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                \n                while (!q.empty()) {\n                    auto [r, c] = q.front();\n                    q.pop();\n                    treeSize++;\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                            board[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                \n                maxTree = max(maxTree, treeSize);\n            }\n        }\n    }\n    \n    return maxTree;\n}\n\n// Find shortest path for empty square to reach target position\nstring findPath(int target_r, int target_c) {\n    if (empty_r == target_r && empty_c == target_c) return \"\";\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int, int>>> parent(N, vector<pair<int, int>>(N, {-1, -1}));\n    vector<vector<int>> dir_used(N, vector<int>(N, -1));\n    \n    queue<pair<int, int>> q;\n    q.push({empty_r, empty_c});\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 == target_r && c == target_c) {\n            string path = \"\";\n            int cr = r, cc = c;\n            while (parent[cr][cc].first != -1) {\n                int d = dir_used[cr][cc];\n                path += dirs[d];\n                int pr = parent[cr][cc].first;\n                int pc = parent[cr][cc].second;\n                cr = pr;\n                cc = pc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\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 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                dir_used[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return \"\";\n}\n\n// Execute a single move\nvoid executeMove(char move) {\n    int d;\n    if (move == 'U') d = 0;\n    else if (move == 'D') d = 1;\n    else if (move == 'L') d = 2;\n    else d = 3;  // 'R'\n    \n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    board[empty_r][empty_c] = board[nr][nc];\n    board[nr][nc] = 0;\n    empty_r = nr;\n    empty_c = nc;\n    operations += move;\n}\n\n// Move empty square to target and execute slide\nvoid moveAndSlide(int target_r, int target_c, int slide_dir) {\n    string path = findPath(target_r, target_c);\n    for (char c : path) {\n        executeMove(c);\n    }\n    executeMove(dirs[slide_dir]);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> T;\n    \n    board.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') {\n                board[i][j] = c - '0';\n            } else {\n                board[i][j] = c - 'a' + 10;\n            }\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    int currentScore = computeMaxTree();\n    int maxScore = currentScore;\n    int noImprovementCount = 0;\n    \n    // Greedy hill-climbing with timeout protection\n    // Reserve 200ms buffer for system test variations\n    while (operations.size() < (size_t)T) {\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        \n        if (elapsed > 2800) break;  // Time limit protection\n        \n        int bestScore = currentScore;\n        int bestTargetR = -1, bestTargetC = -1, bestSlideDir = -1;\n        \n        // Try all possible moves\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (board[r][c] == 0) continue;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    \n                    // Check if this would move tile at (r,c) into empty at (nr,nc)\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (board[nr][nc] != 0) continue;\n                    \n                    // Temporarily make the move\n                    int temp = board[r][c];\n                    board[r][c] = 0;\n                    board[nr][nc] = temp;\n                    int old_er = empty_r, old_ec = empty_c;\n                    empty_r = nr;\n                    empty_c = nc;\n                    \n                    int newScore = computeMaxTree();\n                    \n                    // Restore state\n                    board[nr][nc] = 0;\n                    board[r][c] = temp;\n                    empty_r = old_er;\n                    empty_c = old_ec;\n                    \n                    // Prioritize moves that improve score, then by operation count\n                    if (newScore > bestScore || \n                        (newScore == bestScore && bestScore == N * N - 1)) {\n                        bestScore = newScore;\n                        bestTargetR = r;\n                        bestTargetC = c;\n                        bestSlideDir = d;\n                    }\n                }\n            }\n        }\n        \n        // If we found complete tree, try to minimize operations\n        if (bestScore == N * N - 1 && currentScore == N * N - 1) {\n            break;  // Already optimal\n        }\n        \n        if (bestTargetR == -1) {\n            // No improving move found, try random move to escape local optimum\n            noImprovementCount++;\n            if (noImprovementCount > 100) break;\n            \n            // Make a random valid move\n            vector<tuple<int, int, int>> validMoves;\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    if (board[r][c] == 0) continue;\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 < N && nc >= 0 && nc < N && board[nr][nc] == 0) {\n                            validMoves.push_back({r, c, d});\n                        }\n                    }\n                }\n            }\n            \n            if (!validMoves.empty()) {\n                auto [tr, tc, td] = validMoves[rand() % validMoves.size()];\n                moveAndSlide(tr, tc, td);\n                int newScore = computeMaxTree();\n                if (newScore >= currentScore) {\n                    currentScore = newScore;\n                    maxScore = max(maxScore, currentScore);\n                    noImprovementCount = 0;\n                }\n            } else {\n                break;\n            }\n        } else {\n            // Execute best move\n            moveAndSlide(bestTargetR, bestTargetC, bestSlideDir);\n            currentScore = bestScore;\n            maxScore = max(maxScore, currentScore);\n            noImprovementCount = 0;\n        }\n    }\n    \n    cout << operations << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Strawberry {\n    long long x, y;\n    int id;\n    bool active;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n    \n    // Returns which side of the line a point is on\n    // Positive = one side, Negative = other side, 0 = on line\n    long long side(long long x, long long y) const {\n        return (qx - px) * (y - py) - (qy - py) * (x - px);\n    }\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> cuts;\nmt19937 rng(12345);\n\n// Check if line is too close to any active strawberry\nbool lineIsSafe(const Line& line, long long margin = 1) {\n    for (const auto& s : strawberries) {\n        if (!s.active) continue;\n        long long side = line.side(s.x, s.y);\n        if (abs(side) <= margin * 1000LL) {  // Rough distance check\n            return false;\n        }\n    }\n    return true;\n}\n\n// Count strawberries on each side of a line within a region\npair<int, int> countStrawberries(const Line& line, const vector<int>& regionStraws) {\n    int left = 0, right = 0;\n    for (int idx : regionStraws) {\n        if (!strawberries[idx].active) continue;\n        long long side = line.side(strawberries[idx].x, strawberries[idx].y);\n        if (side > 0) left++;\n        else if (side < 0) right++;\n        // If side == 0, strawberry is cut (becomes inactive)\n    }\n    return {left, right};\n}\n\n// Try to find a line that separates a region into desired sizes\nbool findGoodCut(const vector<int>& regionStraws, int targetLeft, int targetRight, Line& bestLine) {\n    if (regionStraws.size() < 2) return false;\n    \n    int bestScore = -1;\n    \n    // Try random lines through pairs of points\n    for (int trial = 0; trial < 500; trial++) {\n        // Pick two random strawberries to define line direction\n        int i1 = regionStraws[rng() % regionStraws.size()];\n        int i2 = regionStraws[rng() % regionStraws.size()];\n        \n        if (i1 == i2) continue;\n        \n        // Create line perpendicular to the vector between them\n        long long dx = strawberries[i2].x - strawberries[i1].x;\n        long long dy = strawberries[i2].y - strawberries[i1].y;\n        \n        // Perpendicular direction\n        long long px = strawberries[i1].x;\n        long long py = strawberries[i1].y;\n        long long qx = px - dy;\n        long long qy = py + dx;\n        \n        // Offset the line to different positions\n        for (int offset = -50; offset <= 50; offset += 5) {\n            Line testLine = {px + offset * dx / 10, py + offset * dy / 10, \n                           qx + offset * dx / 10, qy + offset * dy / 10};\n            \n            if (!lineIsSafe(testLine, 10)) continue;\n            \n            auto [left, right] = countStrawberries(testLine, regionStraws);\n            \n            // Score based on how close we are to target\n            int score = 0;\n            if (left == targetLeft && right == targetRight) score = 1000;\n            else if (left == targetLeft || right == targetRight) score = 500;\n            else if (left > 0 && right > 0) score = 100;\n            \n            if (score > bestScore) {\n                bestScore = score;\n                bestLine = testLine;\n            }\n        }\n    }\n    \n    return bestScore > 0;\n}\n\n// Find a line that creates a piece with exactly d strawberries\nbool findCutForSize(const vector<int>& regionStraws, int d, Line& bestLine) {\n    if (regionStraws.size() <= d) return false;\n    \n    int bestScore = -1;\n    \n    for (int trial = 0; trial < 1000; trial++) {\n        // Random line through cake\n        long long angle = rng() % 360;\n        double rad = angle * 3.14159265359 / 180.0;\n        long long dx = (long long)(cos(rad) * 10000);\n        long long dy = (long long)(sin(rad) * 10000);\n        \n        // Random offset from center\n        long long offset = (rng() % 20001) - 10000;\n        \n        Line testLine = {offset, 0, offset + dx, dy};\n        \n        if (!lineIsSafe(testLine, 50)) continue;\n        \n        auto [left, right] = countStrawberries(testLine, regionStraws);\n        \n        int score = 0;\n        if (left == d || right == d) score = 1000;\n        else if (abs(left - d) <= 2 || abs(right - d) <= 2) score = 500;\n        else if (left > 0 && right > 0) score = 100;\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestLine = testLine;\n        }\n    }\n    \n    return bestScore > 0;\n}\n\n// Get all strawberries in a region defined by existing cuts\nvector<int> getRegion(const vector<int>& allStraws, const vector<int>& signature) {\n    vector<int> result;\n    for (int idx : allStraws) {\n        if (!strawberries[idx].active) continue;\n        bool match = true;\n        for (size_t i = 0; i < cuts.size() && i < signature.size(); i++) {\n            long long side = cuts[i].side(strawberries[idx].x, strawberries[idx].y);\n            int expected = signature[i];\n            if ((side > 0 && expected != 1) || (side < 0 && expected != -1) || (side == 0)) {\n                match = false;\n                break;\n            }\n        }\n        if (match) result.push_back(idx);\n    }\n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    vector<int> allStraws(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n        strawberries[i].id = i;\n        strawberries[i].active = true;\n        allStraws[i] = i;\n    }\n    \n    // Priority: create pieces matching demand\n    // Start with smaller d values (easier to achieve)\n    vector<pair<int, int>> targets;\n    for (int d = 1; d <= 10; d++) {\n        for (int j = 0; j < a[d]; j++) {\n            targets.push_back({d, j});\n        }\n    }\n    \n    // Sort by d (smaller first - easier to isolate)\n    sort(targets.begin(), targets.end());\n    \n    // Track regions as sets of strawberry indices\n    vector<vector<int>> regions = {allStraws};\n    \n    int cutsUsed = 0;\n    \n    // Greedy: try to satisfy demands one by one\n    for (auto [targetD, targetIdx] : targets) {\n        if (cutsUsed >= K) break;\n        \n        // Find a region with enough strawberries\n        int bestRegion = -1;\n        int bestRegionSize = targetD + 10;  // Want region not much larger than target\n        \n        for (size_t r = 0; r < regions.size(); r++) {\n            int count = 0;\n            for (int idx : regions[r]) {\n                if (strawberries[idx].active) count++;\n            }\n            if (count >= targetD && count < bestRegionSize) {\n                bestRegionSize = count;\n                bestRegion = r;\n            }\n        }\n        \n        if (bestRegion < 0) continue;\n        \n        // Try to find a cut that isolates exactly targetD strawberries\n        Line bestLine;\n        bool found = false;\n        \n        for (int attempt = 0; attempt < 5 && !found; attempt++) {\n            if (findCutForSize(regions[bestRegion], targetD, bestLine)) {\n                // Verify the cut works\n                auto [left, right] = countStrawberries(bestLine, regions[bestRegion]);\n                if (left == targetD || right == targetD) {\n                    found = true;\n                }\n            }\n        }\n        \n        if (!found) continue;\n        \n        // Apply the cut\n        cuts.push_back(bestLine);\n        cutsUsed++;\n        \n        // Update regions and strawberry status\n        vector<vector<int>> newRegions;\n        for (size_t r = 0; r < regions.size(); r++) {\n            if ((int)r != bestRegion) {\n                newRegions.push_back(regions[r]);\n                continue;\n            }\n            \n            vector<int> leftStraws, rightStraws;\n            for (int idx : regions[r]) {\n                if (!strawberries[idx].active) continue;\n                long long side = bestLine.side(strawberries[idx].x, strawberries[idx].y);\n                if (side > 0) leftStraws.push_back(idx);\n                else if (side < 0) rightStraws.push_back(idx);\n                else strawberries[idx].active = false;  // Cut through strawberry\n            }\n            \n            if (!leftStraws.empty()) newRegions.push_back(leftStraws);\n            if (!rightStraws.empty()) newRegions.push_back(rightStraws);\n        }\n        regions = newRegions;\n    }\n    \n    // Output the cuts\n    cout << cuts.size() << \"\\n\";\n    for (const auto& line : cuts) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Global variables\nint N, M;\nbool has_dot[65][65];\nbool used_edge[65][65][4]; // 0: X+, 1: Y+, 2: Diag /, 3: Diag \\\nvector<int> row_dots[65]; // row_dots[y] contains list of x\nvector<int> col_dots[65]; // col_dots[x] contains list of y\n\nstruct Point {\n    int x, y;\n    long long w;\n};\n\nvector<Point> sorted_points;\nvector<array<int, 8>> result_moves;\n\nauto start_time = chrono::steady_clock::now();\nconst double TIME_LIMIT = 4.8;\n\n// Check if an edge is used\n// Edge types:\n// 0: (x, y) to (x+1, y) -> stored at (x, y)\n// 1: (x, y) to (x, y+1) -> stored at (x, y)\n// 2: (x, y) to (x+1, y+1) -> stored at (x, y)\n// 3: (x, y) to (x-1, y+1) -> stored at (x, y) (start point has larger x)\nbool is_edge_used(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        if (y < 0 || y >= N - 1) return false;\n        return used_edge[x1][y][1];\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        if (x < 0 || x >= N - 1) return false;\n        return used_edge[x][y1][0];\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) { // Diag /\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][2];\n            } else { // Diag \\ (x1 < x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][3];\n            }\n        } else { // x1 > x2\n            if (y1 < y2) { // Diag \\ (x1 > x2, y1 < y2) -> Start is (x1, y1)\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][3];\n            } else { // Diag / (x1 > x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][2];\n            }\n        }\n    }\n    return false;\n}\n\nvoid mark_edge(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        used_edge[x1][y][1] = true;\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        used_edge[x][y1][0] = true;\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) used_edge[x1][y1][2] = true;\n            else used_edge[x2][y2][3] = true;\n        } else {\n            if (y1 < y2) used_edge[x1][y1][3] = true;\n            else used_edge[x2][y2][2] = true;\n        }\n    }\n}\n\n// Check perimeter constraints\n// pts: 4 vertices in order\n// dots: 3 existing dots that are allowed to be on perimeter\nbool check_perimeter(const vector<pair<int,int>>& pts, const vector<pair<int,int>>& dots) {\n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        \n        if (is_edge_used(x1, y1, x2, y2)) return false;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0) ? 0 : (dx / steps);\n        int sy = (dy == 0) ? 0 : (dy / steps);\n        \n        for (int k = 1; k < steps; ++k) {\n            int cx = x1 + k * sx;\n            int cy = y1 + k * sy;\n            if (has_dot[cx][cy]) {\n                bool allowed = false;\n                for (const auto& d : dots) {\n                    if (d.first == cx && d.second == cy) {\n                        allowed = true;\n                        break;\n                    }\n                }\n                if (!allowed) return false;\n            }\n        }\n    }\n    return true;\n}\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    vector<pair<int,int>> rect_pts;\n    vector<pair<int,int>> dot_pts;\n};\n\n// Try to find a valid rectangle for empty point (x, y)\n// Returns true if found, and fills 'move'\nbool try_fill(int x, int y, Move& out_move) {\n    // 1. Axis Aligned\n    // We need (x, yp), (xp, y), (xp, yp) to be dots.\n    // To avoid iterator invalidation, we copy relevant parts or just use indices.\n    // Since we return immediately, we can just use references but NOT modify vectors.\n    \n    for (int yp : row_dots[y]) {\n        if (yp == y) continue;\n        for (int xp : col_dots[x]) {\n            if (xp == x) continue;\n            if (has_dot[xp][yp]) {\n                // Candidate found\n                // Vertices: (x, y), (xp, y), (xp, yp), (x, yp)\n                vector<pair<int,int>> rect = {{x, y}, {xp, y}, {xp, yp}, {x, yp}};\n                vector<pair<int,int>> dots = {{xp, y}, {xp, yp}, {x, yp}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xp, y, xp, yp, x, yp, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // 2. 45-degree\n    // Case A: Vertical Diagonal (x, y) and (x, yd)\n    for (int yd : col_dots[x]) {\n        if (yd == y) continue;\n        int dy = yd - y;\n        if (abs(dy) % 2 != 0) continue;\n        int w = abs(dy) / 2;\n        int ym = y + dy / 2;\n        int x2 = x - w;\n        int x3 = x + w;\n        \n        if (x2 >= 0 && x2 < N && x3 >= 0 && x3 < N) {\n            if (has_dot[x2][ym] && has_dot[x3][ym]) {\n                // Vertices: (x, y), (x3, ym), (x, yd), (x2, ym)\n                vector<pair<int,int>> rect = {{x, y}, {x3, ym}, {x, yd}, {x2, ym}};\n                vector<pair<int,int>> dots = {{x, yd}, {x2, ym}, {x3, ym}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, x3, ym, x, yd, x2, ym, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    // Case B: Horizontal Diagonal (x, y) and (xd, y)\n    for (int xd : row_dots[y]) {\n        if (xd == x) continue;\n        int dx = xd - x;\n        if (abs(dx) % 2 != 0) continue;\n        int w = abs(dx) / 2;\n        int xm = x + dx / 2;\n        int y2 = y - w;\n        int y3 = y + w;\n        \n        if (y2 >= 0 && y2 < N && y3 >= 0 && y3 < N) {\n            if (has_dot[xm][y2] && has_dot[xm][y3]) {\n                // Vertices: (x, y), (xm, y3), (xd, y), (xm, y2)\n                vector<pair<int,int>> rect = {{x, y}, {xm, y3}, {xd, y}, {xm, y2}};\n                vector<pair<int,int>> dots = {{xd, y}, {xm, y2}, {xm, y3}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xm, y3, xd, y, xm, y2, rect, dots};\n                    return true;\n                }\n            }\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 >> M)) return 0;\n    \n    long long c = (N - 1) / 2;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        has_dot[x][y] = true;\n        row_dots[y].push_back(x);\n        col_dots[x].push_back(y);\n    }\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            sorted_points.push_back({x, y, w});\n        }\n    }\n    \n    sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n        return a.w > b.w;\n    });\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        bool found = false;\n        Move best_move;\n        \n        for (const auto& p : sorted_points) {\n            if (has_dot[p.x][p.y]) continue;\n            if (row_dots[p.y].empty() && col_dots[p.x].empty()) continue;\n            \n            if (try_fill(p.x, p.y, best_move)) {\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) break;\n        \n        // Apply move\n        result_moves.push_back({best_move.x1, best_move.y1, best_move.x2, best_move.y2, \n                                best_move.x3, best_move.y3, best_move.x4, best_move.y4});\n        \n        has_dot[best_move.x1][best_move.y1] = true;\n        row_dots[best_move.y1].push_back(best_move.x1);\n        col_dots[best_move.x1].push_back(best_move.y1);\n        \n        for (size_t i = 0; i < 4; ++i) {\n            mark_edge(best_move.rect_pts[i].first, best_move.rect_pts[i].second, \n                      best_move.rect_pts[(i + 1) % 4].first, best_move.rect_pts[(i + 1) % 4].second);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& m : result_moves) {\n        cout << m[0] << \" \" << m[1] << \" \" << m[2] << \" \" << m[3] << \" \" \n             << m[4] << \" \" << m[5] << \" \" << m[6] << \" \" << m[7] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 10;\n\nstruct Candy {\n    int flavor;\n    int row, col;\n};\n\nclass GameState {\npublic:\n    array<array<int, N>, N> grid;  // 0 = empty, 1-3 = flavor\n    vector<Candy> candies;\n    \n    GameState() {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = 0;\n    }\n    \n    GameState(const GameState& other) = default;\n    \n    void placeCandy(int row, int col, int flavor) {\n        grid[row][col] = flavor;\n        candies.push_back({flavor, row, col});\n    }\n    \n    vector<pair<int,int>> getEmptyCells() const {\n        vector<pair<int,int>> empty;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    empty.push_back({i, j});\n                }\n            }\n        }\n        return empty;\n    }\n    \n    GameState tilt(char dir) const {\n        GameState result = *this;\n        auto& g = result.grid;\n        \n        if (dir == 'F') {  // Forward (up)\n            for (int j = 0; j < N; j++) {\n                int writeRow = 0;\n                for (int i = 0; i < N; i++) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow++;\n                    }\n                }\n            }\n        } else if (dir == 'B') {  // Backward (down)\n            for (int j = 0; j < N; j++) {\n                int writeRow = N - 1;\n                for (int i = N - 1; i >= 0; i--) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow--;\n                    }\n                }\n            }\n        } else if (dir == 'L') {  // Left\n            for (int i = 0; i < N; i++) {\n                int writeCol = 0;\n                for (int j = 0; j < N; j++) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol++;\n                    }\n                }\n            }\n        } else if (dir == 'R') {  // Right\n            for (int i = 0; i < N; i++) {\n                int writeCol = N - 1;\n                for (int j = N - 1; j >= 0; j--) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol--;\n                    }\n                }\n            }\n        }\n        \n        // Update candy positions\n        result.candies.clear();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (g[i][j] != 0) {\n                    result.candies.push_back({g[i][j], i, j});\n                }\n            }\n        }\n        \n        return result;\n    }\n    \n    int countSameFlavorAdjacency() const {\n        int count = 0;\n        const int dr[] = {-1, 1, 0, 0};\n        const int dc[] = {0, 0, -1, 1};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) continue;\n                for (int d = 0; d < 4; d++) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (grid[ni][nj] == grid[i][j]) {\n                            count++;\n                        }\n                    }\n                }\n            }\n        }\n        return count / 2;  // Each adjacency counted twice\n    }\n    \n    vector<int> getComponentSizes() const {\n        vector<int> sizes;\n        array<array<bool, N>, N> visited{};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0 && !visited[i][j]) {\n                    int flavor = grid[i][j];\n                    int size = 0;\n                    vector<pair<int,int>> stack = {{i, j}};\n                    visited[i][j] = true;\n                    \n                    while (!stack.empty()) {\n                        auto [r, c] = stack.back();\n                        stack.pop_back();\n                        size++;\n                        \n                        const int dr[] = {-1, 1, 0, 0};\n                        const int dc[] = {0, 0, -1, 1};\n                        \n                        for (int d = 0; d < 4; d++) {\n                            int nr = r + dr[d], nc = c + dc[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                if (!visited[nr][nc] && grid[nr][nc] == flavor) {\n                                    visited[nr][nc] = true;\n                                    stack.push_back({nr, nc});\n                                }\n                            }\n                        }\n                    }\n                    sizes.push_back(size);\n                }\n            }\n        }\n        return sizes;\n    }\n    \n    double evaluateScore() const {\n        auto sizes = getComponentSizes();\n        array<int, 4> flavorCount{};\n        \n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] != 0)\n                    flavorCount[grid[i][j]]++;\n        \n        double numerator = 0;\n        for (int s : sizes) numerator += s * s;\n        \n        double denominator = 0;\n        for (int f = 1; f <= 3; f++) denominator += flavorCount[f] * flavorCount[f];\n        \n        if (denominator == 0) return 0;\n        return 1e6 * numerator / denominator;\n    }\n    \n    // Heuristic evaluation for greedy selection\n    double heuristicEvaluate(const vector<int>& futureFlavors, int lookAhead) const {\n        double score = countSameFlavorAdjacency() * 10.0;\n        \n        // Add component size bonus\n        auto sizes = getComponentSizes();\n        for (int s : sizes) {\n            score += s * s * 0.5;\n        }\n        \n        // Consider future flavors - prefer tilts that create space for upcoming flavors\n        if (lookAhead > 0 && !futureFlavors.empty()) {\n            array<int, 4> flavorCount{};\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (grid[i][j] != 0)\n                        flavorCount[grid[i][j]]++;\n            \n            // Bonus for having clusters of flavors that appear soon\n            for (int f = 1; f <= 3; f++) {\n                if (flavorCount[f] > 0) {\n                    int upcoming = 0;\n                    for (int i = 0; i < min(lookAhead, (int)futureFlavors.size()); i++) {\n                        if (futureFlavors[i] == f) upcoming++;\n                    }\n                    score += upcoming * flavorCount[f] * 0.3;\n                }\n            }\n        }\n        \n        return score;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read flavor sequence\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    GameState state;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Find the p-th empty cell (1-indexed)\n        auto empty = state.getEmptyCells();\n        int row = empty[p - 1].first;\n        int col = empty[p - 1].second;\n        \n        // Place the candy\n        state.placeCandy(row, col, flavors[t]);\n        \n        // Skip tilt on last candy (nothing happens)\n        if (t == 99) {\n            cout << 'F' << endl;\n            continue;\n        }\n        \n        // Evaluate all 4 tilt directions\n        vector<pair<double, char>> evaluations;\n        \n        for (char dir : dirs) {\n            GameState next = state.tilt(dir);\n            \n            // Base heuristic score\n            double score = next.heuristicEvaluate(\n                vector<int>(flavors.begin() + t + 1, flavors.end()),\n                5\n            );\n            \n            // Add some randomness for exploration\n            score += (rng() % 100) * 0.01;\n            \n            evaluations.push_back({score, dir});\n        }\n        \n        // Select best direction\n        sort(evaluations.begin(), evaluations.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        char bestDir = evaluations[0].second;\n        cout << bestDir << endl;\n        \n        // Update state\n        state = state.tilt(bestDir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n#include <map>\n\nusing namespace std;\n\n// Compute degree sequence from edge string (sorted)\nvector<int> computeDegreeSeq(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Count edges\nint countEdges(const string& edges) {\n    int cnt = 0;\n    for (char c : edges) {\n        if (c == '1') cnt++;\n    }\n    return cnt;\n}\n\n// Compute degree variance (more stable than triangles)\ndouble computeDegreeVariance(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    double mean = accumulate(deg.begin(), deg.end(), 0.0) / deg.size();\n    double var = 0;\n    for (int d : deg) {\n        var += (d - mean) * (d - mean);\n    }\n    return var / deg.size();\n}\n\n// Compute sum of squared degrees (very stable invariant)\nlong long computeSumSqDegrees(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2 (more stable than triangles)\nint count2Paths(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    // Number of 2-paths = sum of C(deg, 2) = sum of deg*(deg-1)/2\n    int paths = 0;\n    for (int d : deg) {\n        paths += d * (d - 1) / 2;\n    }\n    return paths;\n}\n\n// Compute connectivity-related features\nint countConnectedComponents(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    \n    vector<bool> visited(N, false);\n    int components = 0;\n    for (int i = 0; i < N; i++) {\n        if (!visited[i]) {\n            components++;\n            vector<int> q = {i};\n            visited[i] = true;\n            int head = 0;\n            while (head < (int)q.size()) {\n                int u = q[head++];\n                for (int v = 0; v < N; v++) {\n                    if (adj[u][v] && !visited[v]) {\n                        visited[v] = true;\n                        q.push_back(v);\n                    }\n                }\n            }\n        }\n    }\n    return components;\n}\n\nstruct GraphInfo {\n    string edges;\n    int edge_count;\n    vector<int> degree_seq;\n    long long sum_sq_deg;\n    int two_paths;\n    int components;\n    double degree_var;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n    \n    // Calculate required N based on separation needs\n    // Need: edge_separation > k * noise_std\n    // edge_separation = N*(N-1)/2 / (M-1)\n    // noise_std = sqrt(N*(N-1)/2 * eps * (1-eps))\n    // \n    // For reliable discrimination, aim for separation >= 3 * noise_std\n    // This gives: N*(N-1) >= 18 * (M-1)^2 * eps * (1-eps)\n    \n    double noise_factor = eps * (1.0 - eps);\n    double required_NN = 18.0 * (M - 1) * (M - 1) * noise_factor;\n    \n    // Base N calculation\n    int N;\n    if (eps < 0.02) {\n        N = 20;  // Very low noise, small N is fine\n    } else if (eps < 0.05) {\n        N = 28;\n    } else if (eps < 0.10) {\n        N = 38;\n    } else if (eps < 0.15) {\n        N = 50;\n    } else if (eps < 0.20) {\n        N = 62;\n    } else if (eps < 0.25) {\n        N = 72;\n    } else if (eps < 0.30) {\n        N = 82;\n    } else if (eps < 0.35) {\n        N = 90;\n    } else {\n        N = 98;  // Maximum for very high noise\n    }\n    \n    // For very large M, may need to increase N further\n    if (M >= 80 && N < 90) {\n        N = min(100, N + 10);\n    }\n    \n    // Ensure N is in valid range and has good properties\n    N = max(4, min(100, N));\n    \n    int total_edges = N * (N - 1) / 2;\n    \n    // Store graph information for matching\n    vector<GraphInfo> graphs(M);\n    \n    // Generate M graphs with well-separated properties\n    // Key innovation: Use multiple orthogonal features, not just edge count\n    for (int k = 0; k < M; k++) {\n        GraphInfo& info = graphs[k];\n        \n        // Target edge count - evenly distributed for maximum separation\n        int target_edges = M > 1 ? (k * total_edges) / (M - 1) : total_edges / 2;\n        target_edges = max(0, min(total_edges, target_edges));\n        info.edge_count = target_edges;\n        \n        // Create edge string with structured pattern for additional discrimination\n        string g(total_edges, '0');\n        vector<int> positions(total_edges);\n        iota(positions.begin(), positions.end(), 0);\n        \n        // Use different deterministic patterns for different graphs\n        // This creates additional structure beyond just edge count\n        mt19937 kg(10000 + k * 17 + M * 31);\n        \n        // For some graphs, create more structured patterns\n        if (k < M / 3) {\n            // First third: prefer edges near start (lower vertex indices)\n            // This creates different degree distributions\n            for (int i = 0; i < total_edges; i++) {\n                positions[i] = i;\n            }\n            // Slight shuffle\n            for (int i = total_edges - 1; i > total_edges - 20; i--) {\n                swap(positions[i], positions[uniform_int_distribution<>(0, i)(kg)]);\n            }\n        } else if (k < 2 * M / 3) {\n            // Middle third: shuffle moderately\n            shuffle(positions.begin(), positions.end(), kg);\n        } else {\n            // Last third: prefer edges near end (higher vertex indices)\n            reverse(positions.begin(), positions.end());\n            for (int i = 0; i < 20 && i < total_edges; i++) {\n                swap(positions[i], positions[uniform_int_distribution<>(0, total_edges-1)(kg)]);\n            }\n        }\n        \n        for (int i = 0; i < target_edges && i < total_edges; i++) {\n            g[positions[i]] = '1';\n        }\n        \n        info.edges = g;\n        info.degree_seq = computeDegreeSeq(g, N);\n        info.sum_sq_deg = computeSumSqDegrees(info.degree_seq);\n        info.two_paths = count2Paths(g, N);\n        info.components = countConnectedComponents(g, N);\n        info.degree_var = computeDegreeVariance(info.degree_seq);\n    }\n    \n    // Output N and graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << graphs[k].edges << \"\\n\";\n    }\n    cout << flush;\n    \n    // Process 100 queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        if (h.empty() || h.length() != (size_t)total_edges) {\n            cout << 0 << \"\\n\";\n            cout << flush;\n            continue;\n        }\n        \n        // Compute invariants for query graph\n        int h_edges = countEdges(h);\n        vector<int> h_deg = computeDegreeSeq(h, N);\n        long long h_sum_sq = computeSumSqDegrees(h_deg);\n        int h_2paths = count2Paths(h, N);\n        int h_components = countConnectedComponents(h, N);\n        double h_deg_var = computeDegreeVariance(h_deg);\n        \n        // Find best matching graph using weighted distance\n        int best_k = 0;\n        double best_score = 1e18;\n        \n        // Normalize factors for different feature scales\n        double edge_scale = max(1.0, total_edges / 10.0);\n        double deg_scale = max(1.0, N * N / 10.0);\n        double path_scale = max(1.0, total_edges * N / 100.0);\n        \n        for (int k = 0; k < M; k++) {\n            double score = 0;\n            \n            // Edge count difference (most robust, weight heavily)\n            double edge_diff = abs(h_edges - graphs[k].edge_count);\n            score += (edge_diff / edge_scale) * (edge_diff / edge_scale) * 10.0;\n            \n            // Sum of squared degrees (very stable under permutation)\n            double sq_deg_diff = abs(h_sum_sq - graphs[k].sum_sq_deg);\n            score += (sq_deg_diff / deg_scale) * (sq_deg_diff / deg_scale) * 5.0;\n            \n            // 2-path count (more stable than triangles)\n            double path_diff = abs(h_2paths - graphs[k].two_paths);\n            score += (path_diff / path_scale) * (path_diff / path_scale) * 3.0;\n            \n            // Degree variance\n            double var_diff = abs(h_deg_var - graphs[k].degree_var);\n            score += var_diff * var_diff * 100.0;\n            \n            // Connected components (discrete, use as tiebreaker)\n            if (h_components != graphs[k].components) {\n                score += 50.0;\n            }\n            \n            if (score < best_score) {\n                best_score = score;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nstruct Edge {\n    int id;\n    int u, v;\n    long long w;\n    double mid_x, mid_y;\n    double importance;\n};\n\nclass Solver {\npublic:\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<vector<pair<int, int>>> adj;\n    vector<pair<int, int>> coords;\n    vector<vector<long long>> base_dist;\n    chrono::steady_clock::time_point start_time;\n    \n    static constexpr long long INF = 1e18;\n    static constexpr long long UNREACHABLE = 1000000000;\n    \n    void compute_base_distances() {\n        base_dist.assign(N, vector<long long>(N, INF));\n        \n        for (int src = 0; src < N; src++) {\n            base_dist[src][src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > base_dist[src][u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < base_dist[src][v]) {\n                        base_dist[src][v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n    }\n    \n    void compute_edge_importance() {\n        vector<double> importance(M, 0);\n        \n        int samples = min(N, 25);\n        vector<int> sources(samples);\n        for (int i = 0; i < samples; i++) {\n            sources[i] = i * N / samples;\n        }\n        \n        for (int src : sources) {\n            vector<long long> dist(N, INF);\n            vector<int> parent_edge(N, -1);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        parent_edge[v] = edge_idx;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int v = 0; v < N; v++) {\n                if (v != src && parent_edge[v] != -1) {\n                    importance[parent_edge[v]] += 1.0;\n                }\n            }\n        }\n        \n        for (int i = 0; i < M; i++) {\n            edges[i].importance = importance[i];\n        }\n    }\n    \n    double compute_frustration_fast(const vector<int>& edges_to_remove) {\n        if (edges_to_remove.empty()) return 0.0;\n        \n        vector<bool> edge_removed(M, false);\n        for (int idx : edges_to_remove) {\n            edge_removed[idx] = true;\n        }\n        \n        double total_increase = 0;\n        int sample_vertices = min(N, 20);\n        vector<int> samples(sample_vertices);\n        for (int i = 0; i < sample_vertices; i++) {\n            samples[i] = i * N / sample_vertices;\n        }\n        \n        for (int src : samples) {\n            vector<long long> dist(N, INF);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    if (edge_removed[edge_idx]) continue;\n                    \n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int dst : samples) {\n                if (src == dst) continue;\n                \n                long long d_k = (dist[dst] >= INF) ? UNREACHABLE : dist[dst];\n                long long d_base = (base_dist[src][dst] >= INF) ? UNREACHABLE : base_dist[src][dst];\n                \n                total_increase += max(0LL, d_k - d_base);\n            }\n        }\n        \n        double scale = (double)(N * (N - 1)) / (sample_vertices * (sample_vertices - 1));\n        return total_increase * scale / (N * (N - 1));\n    }\n    \n    double compute_total_frustration(const vector<int>& assignment) {\n        vector<vector<int>> day_edges(D);\n        for (int i = 0; i < M; i++) {\n            day_edges[assignment[i] - 1].push_back(i);\n        }\n        \n        double total = 0;\n        for (int d = 0; d < D; d++) {\n            total += compute_frustration_fast(day_edges[d]);\n        }\n        return total / D;\n    }\n    \n    vector<int> solve() {\n        start_time = chrono::steady_clock::now();\n        \n        compute_base_distances();\n        compute_edge_importance();\n        \n        // Sort edges by importance (descending)\n        vector<int> edge_order(M);\n        iota(edge_order.begin(), edge_order.end(), 0);\n        sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n            return edges[a].importance > edges[b].importance;\n        });\n        \n        // Greedy assignment: spread important edges across days\n        vector<int> assignment(M);\n        vector<vector<int>> day_edges(D);\n        vector<double> day_importance(D, 0);\n        \n        for (int edge_idx : edge_order) {\n            int best_day = 0;\n            double min_importance = 1e18;\n            \n            for (int d = 0; d < D; d++) {\n                if ((int)day_edges[d].size() < K) {\n                    if (day_importance[d] < min_importance) {\n                        min_importance = day_importance[d];\n                        best_day = d;\n                    }\n                }\n            }\n            \n            assignment[edge_idx] = best_day + 1;\n            day_edges[best_day].push_back(edge_idx);\n            day_importance[best_day] += edges[edge_idx].importance;\n        }\n        \n        // Local search optimization\n        local_search(assignment);\n        \n        return assignment;\n    }\n    \n    void local_search(vector<int>& assignment) {\n        mt19937 rng(42);\n        \n        int iterations = 0;\n        int max_iterations = 500;\n        double current_score = compute_total_frustration(assignment);\n        double best_score = current_score;\n        vector<int> best_assignment = assignment;\n        \n        while (iterations < max_iterations) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 5.5) {\n                break;\n            }\n            \n            // Try swapping two edges\n            int i = uniform_int_distribution<>(0, M - 1)(rng);\n            int j = uniform_int_distribution<>(0, M - 1)(rng);\n            \n            if (i == j) continue;\n            \n            int day_i = assignment[i] - 1;\n            int day_j = assignment[j] - 1;\n            \n            if (day_i == day_j) continue;\n            \n            // Try swap\n            assignment[i] = day_j + 1;\n            assignment[j] = day_i + 1;\n            \n            double new_score = compute_total_frustration(assignment);\n            \n            if (new_score < best_score) {\n                best_score = new_score;\n                best_assignment = assignment;\n                iterations = 0;\n            } else {\n                // Revert\n                assignment[i] = day_i + 1;\n                assignment[j] = day_j + 1;\n                iterations++;\n            }\n        }\n        \n        assignment = best_assignment;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    Solver solver;\n    solver.N = N;\n    solver.M = M;\n    solver.D = D;\n    solver.K = K;\n    \n    solver.edges.resize(M);\n    solver.adj.resize(N);\n    solver.coords.resize(N);\n    \n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        solver.edges[i] = {i, u, v, (long long)w, 0, 0, 0};\n        solver.adj[u].push_back({v, i});\n        solver.adj[v].push_back({u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    \n    // Compute edge midpoints for potential spatial clustering\n    for (int i = 0; i < M; i++) {\n        int u = solver.edges[i].u;\n        int v = solver.edges[i].v;\n        solver.edges[i].mid_x = (solver.coords[u].first + solver.coords[v].first) / 2.0;\n        solver.edges[i].mid_y = (solver.coords[u].second + solver.coords[v].second) / 2.0;\n    }\n    \n    auto assignment = solver.solve();\n    \n    for (int i = 0; i < M; i++) {\n        cout << assignment[i] << (i == M - 1 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D;\n    cin >> D;\n    \n    // Read silhouettes\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; i++) cin >> f1[i];\n    for (int i = 0; i < D; i++) cin >> r1[i];\n    for (int i = 0; i < D; i++) cin >> f2[i];\n    for (int i = 0; i < D; i++) cin >> r2[i];\n    \n    // Compute valid positions for each silhouette\n    // valid[z][y][x] = true if block can be placed at (x,y,z)\n    vector<vector<vector<bool>>> valid1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> valid2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[z][y][x] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Find common valid positions\n    vector<vector<vector<bool>>> common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                common[z][y][x] = valid1[z][y][x] && valid2[z][y][x];\n            }\n        }\n    }\n    \n    // Output grids - store as b[z][y][x] for easier indexing\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    int block_id = 1;\n    \n    // Strategy: Use 1x1x1 blocks for common positions (guaranteed same shape)\n    // Use connected components for non-common positions to reduce block count\n    \n    // Step 1: Common positions - each gets unique block ID (1x1x1)\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x]) {\n                    b1[z][y][x] = block_id;\n                    b2[z][y][x] = block_id;\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Step 2: Valid only in arrangement 1 - use connected components\n    vector<vector<vector<bool>>> visited1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (valid1[z][y][x] && !common[z][y][x] && !visited1[z][y][x]) {\n                    // BFS to find connected component\n                    vector<tuple<int,int,int>> component;\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    visited1[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front();\n                        q.pop();\n                        component.push_back({cx, cy, cz});\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cx + dx[dir];\n                            int ny = cy + dy[dir];\n                            int nz = cz + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                valid1[nz][ny][nx] && !common[nz][ny][nx] && !visited1[nz][ny][nx]) {\n                                visited1[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& [cx, cy, cz] : component) {\n                        b1[cz][cy][cx] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Step 3: Valid only in arrangement 2 - use connected components\n    vector<vector<vector<bool>>> visited2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (valid2[z][y][x] && !common[z][y][x] && !visited2[z][y][x]) {\n                    // BFS to find connected component\n                    vector<tuple<int,int,int>> component;\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    visited2[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front();\n                        q.pop();\n                        component.push_back({cx, cy, cz});\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cx + dx[dir];\n                            int ny = cy + dy[dir];\n                            int nz = cz + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                valid2[nz][ny][nx] && !common[nz][ny][nx] && !visited2[nz][ny][nx]) {\n                                visited2[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& [cx, cy, cz] : component) {\n                        b2[cz][cy][cx] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    \n    // Output b1 in correct order: x*D^2 + y*D + z\n    // Loop order: x, y, z\n    vector<int> output1;\n    output1.reserve(D * D * D);\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                output1.push_back(b1[z][y][x]);\n            }\n        }\n    }\n    \n    for (int i = 0; i < (int)output1.size(); i++) {\n        cout << output1[i] << (i == (int)output1.size() - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    // Output b2 in correct order: x*D^2 + y*D + z\n    vector<int> output2;\n    output2.reserve(D * D * D);\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                output2.push_back(b2[z][y][x]);\n            }\n        }\n    }\n    \n    for (int i = 0; i < (int)output2.size(); i++) {\n        cout << output2[i] << (i == (int)output2.size() - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <numeric>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        return parent[x] == x ? x : parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        parent[y] = x;\n        return true;\n    }\n};\n\nlong long dist_ll(Point a, Point b) {\n    long long dx = a.x - b.x;\n    long long dy = a.y - b.y;\n    return round(sqrt(dx * dx + dy * dy));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    vector<Point> stations(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n    }\n    \n    vector<Point> residents(K);\n    for (int i = 0; i < K; i++) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n    \n    // Precompute distances from each resident to each station\n    vector<vector<long long>> resident_station_dist(K, vector<long long>(N));\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            resident_station_dist[k][i] = dist_ll(residents[k], stations[i]);\n        }\n    }\n    \n    // Build MST from station 0 for initial connectivity\n    vector<pair<long long, int>> mst_edges;\n    vector<Edge> sorted_edges = edges;\n    sort(sorted_edges.begin(), sorted_edges.end(), \n         [](const Edge& a, const Edge& b) { return a.w < b.w; });\n    \n    DSU dsu(N);\n    vector<int> edge_in_mst(M, 0);\n    long long mst_cost = 0;\n    int edges_added = 0;\n    \n    for (int i = 0; i < M && edges_added < N - 1; i++) {\n        int idx = -1;\n        for (int j = 0; j < M; j++) {\n            if (edge_in_mst[j]) continue;\n            if (edges[j].w == sorted_edges[i].w && \n                dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                idx = j;\n                break;\n            }\n        }\n        if (idx == -1) {\n            for (int j = 0; j < M; j++) {\n                if (edge_in_mst[j]) continue;\n                if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                    idx = j;\n                    break;\n                }\n            }\n        }\n        if (idx != -1) {\n            dsu.unite(edges[idx].u, edges[idx].v);\n            edge_in_mst[idx] = 1;\n            mst_cost += edges[idx].w;\n            edges_added++;\n        }\n    }\n    \n    // Find connected component from station 0\n    vector<int> reachable(N, 0);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (edge_in_mst[i]) {\n            adj[edges[i].u].push_back(edges[i].v);\n            adj[edges[i].v].push_back(edges[i].u);\n        }\n    }\n    \n    queue<int> q;\n    q.push(0);\n    reachable[0] = 1;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (!reachable[v]) {\n                reachable[v] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Assign residents to nearest reachable station\n    vector<long long> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        long long min_dist = 1e18;\n        int best_station = -1;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i]) {\n                if (resident_station_dist[k][i] < min_dist) {\n                    min_dist = resident_station_dist[k][i];\n                    best_station = i;\n                }\n            }\n        }\n        if (best_station != -1 && min_dist <= 5000) {\n            P[best_station] = max(P[best_station], min_dist);\n        }\n    }\n    \n    // Calculate initial cost\n    auto calc_cost = [&]() -> long long {\n        long long cost = 0;\n        for (int i = 0; i < N; i++) {\n            cost += P[i] * P[i];\n        }\n        for (int i = 0; i < M; i++) {\n            if (edge_in_mst[i]) {\n                cost += edges[i].w;\n            }\n        }\n        return cost;\n    };\n    \n    auto check_coverage = [&]() -> bool {\n        for (int k = 0; k < K; k++) {\n            bool covered = false;\n            for (int i = 0; i < N; i++) {\n                if (reachable[i] && resident_station_dist[k][i] <= P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n            if (!covered) return false;\n        }\n        return true;\n    };\n    \n    long long best_cost = calc_cost();\n    vector<int> best_edge_state = edge_in_mst;\n    vector<long long> best_P = P;\n    \n    // Try adding beneficial edges\n    mt19937 rng(42);\n    for (int iter = 0; iter < 500; iter++) {\n        vector<int> current_edge_state = best_edge_state;\n        vector<long long> current_P = best_P;\n        \n        // Recompute reachable\n        vector<int> cur_reachable(N, 0);\n        vector<vector<int>> cur_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (current_edge_state[i]) {\n                cur_adj[edges[i].u].push_back(edges[i].v);\n                cur_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> cq;\n        cq.push(0);\n        cur_reachable[0] = 1;\n        while (!cq.empty()) {\n            int u = cq.front(); cq.pop();\n            for (int v : cur_adj[u]) {\n                if (!cur_reachable[v]) {\n                    cur_reachable[v] = 1;\n                    cq.push(v);\n                }\n            }\n        }\n        \n        // Try adding a random edge\n        int edge_to_add = uniform_int_distribution<>(0, M-1)(rng);\n        if (!current_edge_state[edge_to_add]) {\n            current_edge_state[edge_to_add] = 1;\n            \n            // Recompute reachable\n            fill(cur_reachable.begin(), cur_reachable.end(), 0);\n            for (int i = 0; i < N; i++) cur_adj[i].clear();\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    cur_adj[edges[i].u].push_back(edges[i].v);\n                    cur_adj[edges[i].v].push_back(edges[i].u);\n                }\n            }\n            cq = queue<int>();\n            cq.push(0);\n            cur_reachable[0] = 1;\n            while (!cq.empty()) {\n                int u = cq.front(); cq.pop();\n                for (int v : cur_adj[u]) {\n                    if (!cur_reachable[v]) {\n                        cur_reachable[v] = 1;\n                        cq.push(v);\n                    }\n                }\n            }\n            \n            // Recalculate P\n            fill(current_P.begin(), current_P.end(), 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    current_P[best_station] = max(current_P[best_station], min_dist);\n                }\n            }\n            \n            // Calculate new cost\n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += current_P[i] * current_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            // Check if all residents covered\n            bool all_covered = true;\n            for (int k = 0; k < K; k++) {\n                bool covered = false;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i] && resident_station_dist[k][i] <= current_P[i]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    all_covered = false;\n                    break;\n                }\n            }\n            \n            if (all_covered && new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = current_edge_state;\n                best_P = current_P;\n            }\n        }\n    }\n    \n    // Try removing expensive edges if possible\n    vector<pair<long long, int>> edge_by_cost;\n    for (int i = 0; i < M; i++) {\n        if (best_edge_state[i]) {\n            edge_by_cost.push_back({edges[i].w, i});\n        }\n    }\n    sort(edge_by_cost.rbegin(), edge_by_cost.rend());\n    \n    for (auto& [w, idx] : edge_by_cost) {\n        vector<int> test_edge_state = best_edge_state;\n        test_edge_state[idx] = 0;\n        \n        // Check if still connected\n        vector<int> test_reachable(N, 0);\n        vector<vector<int>> test_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (test_edge_state[i]) {\n                test_adj[edges[i].u].push_back(edges[i].v);\n                test_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> tq;\n        tq.push(0);\n        test_reachable[0] = 1;\n        while (!tq.empty()) {\n            int u = tq.front(); tq.pop();\n            for (int v : test_adj[u]) {\n                if (!test_reachable[v]) {\n                    test_reachable[v] = 1;\n                    tq.push(v);\n                }\n            }\n        }\n        \n        // Check if all residents still coverable\n        bool all_coverable = true;\n        for (int k = 0; k < K; k++) {\n            bool can_cover = false;\n            for (int i = 0; i < N; i++) {\n                if (test_reachable[i] && resident_station_dist[k][i] <= 5000) {\n                    can_cover = true;\n                    break;\n                }\n            }\n            if (!can_cover) {\n                all_coverable = false;\n                break;\n            }\n        }\n        \n        if (all_coverable) {\n            vector<long long> test_P(N, 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (test_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    test_P[best_station] = max(test_P[best_station], min_dist);\n                }\n            }\n            \n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += test_P[i] * test_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (test_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = test_edge_state;\n                best_P = test_P;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << best_P[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << best_edge_state[i] << (i == M-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cstring>\n\nusing namespace std;\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\nint N = 30;\nint grid[30][30];\nPoint pos[465]; \n\nvector<tuple<int, int, int, int>> ops;\n\n// Directions for neighbors\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid swap_balls(int x1, int y1, int x2, int y2) {\n    int v1 = grid[x1][y1];\n    int v2 = grid[x2][y2];\n    grid[x1][y1] = v2;\n    grid[x2][y2] = v1;\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n}\n\n// Anchor marks cells in the current row that already contain a correct value\nbool anchor[30][30];\n\n// BFS to find closest needed value and move it to (tr, tc)\nint find_and_move(int tr, int tc, int val_min, int val_max) {\n    Point target = {tr, tc};\n    \n    static int dist[30][30];\n    static Point parent[30][30];\n    static bool visited[30][30];\n    \n    // Reset visited\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            visited[i][j] = false;\n        }\n    }\n    \n    queue<Point> q;\n    q.push(target);\n    visited[tr][tc] = true;\n    dist[tr][tc] = 0;\n    parent[tr][tc] = {-1, -1};\n    \n    Point best_pos = {-1, -1};\n    \n    while(!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n        \n        // Check if this cell has a needed value\n        int val = grid[curr.x][curr.y];\n        if (val >= val_min && val <= val_max) {\n            best_pos = curr;\n            break; \n        }\n        \n        // Expand neighbors\n        for(int i=0; i<6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (is_valid(nx, ny)) {\n                // Obstacle checks\n                if (nx < tr) continue; // Rows above are fixed\n                if (nx == tr && ny < tc) continue; // Cols left in current row are fixed\n                if (nx == tr && anchor[nx][ny]) continue; // Anchors in current row are fixed\n                \n                if (!visited[nx][ny]) {\n                    visited[nx][ny] = true;\n                    dist[nx][ny] = dist[curr.x][curr.y] + 1;\n                    parent[nx][ny] = curr;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n    \n    if (best_pos.x == -1) return -1;\n    \n    // Reconstruct path from best_pos to target\n    vector<Point> path;\n    Point curr = best_pos;\n    while (true) {\n        path.push_back(curr);\n        if (curr == target) break;\n        curr = parent[curr.x][curr.y];\n    }\n    \n    // Execute swaps: move value from path[0] to path.back()\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        swap_balls(path[i].x, path[i].y, path[i+1].x, path[i+1].y);\n    }\n    \n    return grid[tr][tc];\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> grid[i][j];\n            pos[grid[i][j]] = {i, j};\n        }\n    }\n    \n    ops.reserve(10000);\n    \n    // Process each row from top to bottom\n    for (int r = 0; r < N; ++r) {\n        int row_min = r * (r + 1) / 2;\n        int row_max = (r + 1) * (r + 2) / 2 - 1;\n        \n        // Identify anchors: cells in Row r that already have a value belonging to Row r\n        memset(anchor, 0, sizeof(anchor));\n        for (int c = 0; c <= r; ++c) {\n            if (grid[r][c] >= row_min && grid[r][c] <= row_max) {\n                anchor[r][c] = true;\n            }\n        }\n        \n        // Fill row r positions 0 to r\n        for (int c = 0; c <= r; ++c) {\n            // If this cell is an anchor, it already has a valid value for this row.\n            // We keep it in place to minimize swaps.\n            if (anchor[r][c]) continue;\n            \n            // Otherwise, find the closest value belonging to this row from the free region\n            // and move it here.\n            int val = find_and_move(r, c, row_min, row_max);\n            if (val == -1) {\n                // Should not happen as there are exactly enough values\n                return 1;\n            }\n            // After move, grid[r][c] contains a value in [row_min, row_max].\n            // It is effectively fixed for subsequent steps in this row (handled by ny < tc check).\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \" << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0;\nconst int ENTRANCE_J = 4;\n\nstruct Container {\n    int id;\n    int pi, pj;\n};\n\n// Check if a cell is reachable from entrance through empty cells\nbool isReachable(int di, int dj, int D, const vector<vector<bool>>& obstacle, \n                 const vector<vector<bool>>& occupied, const vector<vector<bool>>& exclude) {\n    if (obstacle[di][dj] || occupied[di][dj] || exclude[di][dj]) return false;\n    if (di == ENTRANCE_I && dj == ENTRANCE_J) return true;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == di && cj == dj) return true;\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && \n                !occupied[ni][nj] && !exclude[ni][nj]) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return false;\n}\n\n// Get all reachable empty cells from entrance\nvector<pair<int,int>> getReachableEmpty(int D, const vector<vector<bool>>& obstacle,\n                                         const vector<vector<bool>>& occupied) {\n    vector<pair<int,int>> result;\n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && !occupied[ni][nj]) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n                result.push_back({ni, nj});\n            }\n        }\n    }\n    return result;\n}\n\n// Compute BFS distance from entrance\nint bfsDistance(int ti, int tj, int D, const vector<vector<bool>>& obstacle) {\n    if (ti == ENTRANCE_I && tj == ENTRANCE_J) return 0;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    dist[ENTRANCE_I][ENTRANCE_J] = 0;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                dist[ni][nj] == -1 && !obstacle[ni][nj]) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                if (ni == ti && nj == tj) return dist[ni][nj];\n                q.push({ni, nj});\n            }\n        }\n    }\n    return D * D;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    int D_val;\n    cin >> D_val >> N;\n    \n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n    \n    // Pre-compute distances for all cells\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (!obstacle[i][j] && !(i == ENTRANCE_I && j == ENTRANCE_J)) {\n                dist[i][j] = bfsDistance(i, j, D, obstacle);\n                cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Sort cells by distance (farthest first for storage)\n    sort(cells.begin(), cells.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        return dist[a.first][a.second] > dist[b.first][b.second];\n    });\n    \n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n    vector<Container> containers;\n    int totalContainers = D * D - 1 - N;\n    \n    // Storage phase\n    for (int d = 0; d < totalContainers; d++) {\n        int t;\n        cin >> t;\n        \n        // Find farthest reachable empty cell\n        int bestI = -1, bestJ = -1;\n        for (auto& [i, j] : cells) {\n            if (!occupied[i][j]) {\n                // Temporarily mark as occupied to check reachability\n                occupied[i][j] = true;\n                \n                // Check if still reachable (for future containers)\n                auto reachable = getReachableEmpty(D, obstacle, occupied);\n                \n                // Check if we can still reach all currently occupied cells\n                bool allReachable = true;\n                for (auto& c : containers) {\n                    occupied[c.pi][c.pj] = false;\n                    if (!isReachable(c.pi, c.pj, D, obstacle, occupied, {{}})) {\n                        allReachable = false;\n                    }\n                    occupied[c.pi][c.pj] = true;\n                }\n                \n                occupied[i][j] = false;\n                \n                if (allReachable && reachable.size() >= (totalContainers - d - 1)) {\n                    bestI = i;\n                    bestJ = j;\n                    break;\n                }\n            }\n        }\n        \n        // Fallback: just pick first reachable\n        if (bestI == -1) {\n            auto reachable = getReachableEmpty(D, obstacle, occupied);\n            if (!reachable.empty()) {\n                // Pick farthest reachable\n                pair<int,int> best = reachable[0];\n                for (auto& [i, j] : reachable) {\n                    if (dist[i][j] > dist[best.first][best.second]) {\n                        best = {i, j};\n                    }\n                }\n                bestI = best.first;\n                bestJ = best.second;\n            }\n        }\n        \n        occupied[bestI][bestJ] = true;\n        containers.push_back({t, bestI, bestJ});\n        cout << bestI << \" \" << bestJ << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval phase - output containers in ID order\n    sort(containers.begin(), containers.end(), [](const Container& a, const Container& b) {\n        return a.id < b.id;\n    });\n    \n    for (auto& c : containers) {\n        cout << c.pi << \" \" << c.pj << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    // Use a 2D vector to store the grid. \n    // n=50 is small, so memory usage is negligible.\n    vector<vector<int>> grid(n, vector<int>(n));\n\n    // Read the input grid\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    // Output the grid exactly as is.\n    // Reasoning:\n    // 1. The input constraints state 1 <= c_{i,j} <= m, so there are no 0s in the input.\n    // 2. The score is (number of 0s) + 1. Since input has 0 zeros, Score = 1.\n    // 3. Score 1 is the theoretical minimum (count cannot be negative).\n    // 4. The input is guaranteed to satisfy connectivity for colors 1..m.\n    // 5. Color 0 connectivity is satisfied via the \"outside\" region (as per problem note).\n    // 6. Adjacencies are preserved because the map is identical.\n    // Thus, echoing the input is the optimal and safest strategy.\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 <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Weight estimates using Elo-style rating\n    vector<double> rating(N, 1000.0);\n    const double K = 20.0; // Learning rate\n    \n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int queries_used = 0;\n    \n    // Phase 1: Systematic pairwise comparisons\n    // First, compare each item with several others to get baseline estimates\n    vector<vector<int>> comparison_count(N, vector<int>(N, 0));\n    \n    // Create a comparison schedule\n    vector<pair<int, int>> comparisons;\n    \n    // Round-robin style comparisons for good coverage\n    for (int offset = 1; offset < N && (int)comparisons.size() < Q; offset++) {\n        for (int i = 0; i < N && (int)comparisons.size() < Q; i++) {\n            int j = (i + offset) % N;\n            if (i < j) {\n                comparisons.push_back({i, j});\n            }\n        }\n    }\n    \n    // Execute comparisons\n    for (auto& [i, j] : comparisons) {\n        if (queries_used >= Q) break;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        // Expected score based on current ratings\n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        // Actual score\n        double actual_i, actual_j;\n        if (result == \"<\") {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result == \">\") {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else { // \"=\"\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        // Update ratings\n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n        comparison_count[i][j]++;\n        comparison_count[j][i]++;\n    }\n    \n    // Use remaining queries for additional random comparisons\n    // Focus on items with fewer comparisons\n    while (queries_used < Q) {\n        // Find items with fewer comparisons\n        vector<int> comparison_total(N, 0);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                comparison_total[i] += comparison_count[i][j];\n            }\n        }\n        \n        // Weighted random selection (prefer less compared items)\n        vector<double> weights(N);\n        double weight_sum = 0;\n        for (int i = 0; i < N; i++) {\n            weights[i] = 1.0 / (1.0 + comparison_total[i]);\n            weight_sum += weights[i];\n        }\n        \n        uniform_real_distribution<> dist(0, weight_sum);\n        double r = dist(rng);\n        int i = 0;\n        for (; i < N - 1; i++) {\n            r -= weights[i];\n            if (r <= 0) break;\n        }\n        \n        int j;\n        do {\n            j = rng() % N;\n        } while (j == i);\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        double actual_i, actual_j;\n        if (result == \"<\") {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result == \">\") {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else {\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n        comparison_count[i][j]++;\n        comparison_count[j][i]++;\n    }\n    \n    // Phase 2: Partition items into D groups\n    // Sort items by rating (descending - heaviest first)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return rating[a] > rating[b];\n    });\n    \n    // Greedy assignment: assign heaviest items to lightest groups\n    vector<double> group_weight(D, 0.0);\n    vector<int> assignment(N);\n    vector<vector<int>> groups(D);\n    \n    for (int idx : indices) {\n        // Find group with minimum weight\n        int best_group = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] < group_weight[best_group]) {\n                best_group = g;\n            }\n        }\n        assignment[idx] = best_group;\n        group_weight[best_group] += rating[idx];\n        groups[best_group].push_back(idx);\n    }\n    \n    // Phase 3: Local search optimization\n    // Try swapping items between groups to reduce variance\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        // Calculate current variance\n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        double current_variance = 0;\n        for (int g = 0; g < D; g++) {\n            current_variance += (group_weight[g] - mean) * (group_weight[g] - mean);\n        }\n        \n        // Try swapping pairs of items from different groups\n        for (int g1 = 0; g1 < D && !improved; g1++) {\n            for (int g2 = g1 + 1; g2 < D && !improved; g2++) {\n                for (int i1 : groups[g1]) {\n                    for (int i2 : groups[g2]) {\n                        // Calculate new weights if we swap\n                        double new_w1 = group_weight[g1] - rating[i1] + rating[i2];\n                        double new_w2 = group_weight[g2] - rating[i2] + rating[i1];\n                        \n                        // Calculate new variance contribution\n                        double old_contrib = (group_weight[g1] - mean) * (group_weight[g1] - mean) +\n                                            (group_weight[g2] - mean) * (group_weight[g2] - mean);\n                        double new_contrib = (new_w1 - mean) * (new_w1 - mean) +\n                                            (new_w2 - mean) * (new_w2 - mean);\n                        \n                        if (new_contrib < old_contrib - 1e-9) {\n                            // Perform swap\n                            assignment[i1] = g2;\n                            assignment[i2] = g1;\n                            \n                            // Update groups\n                            auto it1 = find(groups[g1].begin(), groups[g1].end(), i1);\n                            auto it2 = find(groups[g2].begin(), groups[g2].end(), i2);\n                            *it1 = i2;\n                            *it2 = i1;\n                            \n                            group_weight[g1] = new_w1;\n                            group_weight[g2] = new_w2;\n                            \n                            improved = true;\n                            break;\n                        }\n                    }\n                    if (improved) break;\n                }\n                if (improved) break;\n            }\n        }\n        \n        // Also try moving single items\n        if (!improved) {\n            for (int g1 = 0; g1 < D && !improved; g1++) {\n                for (int g2 = 0; g2 < D && !improved; g2++) {\n                    if (g1 == g2) continue;\n                    if (groups[g1].empty()) continue;\n                    \n                    for (int i : groups[g1]) {\n                        double new_w1 = group_weight[g1] - rating[i];\n                        double new_w2 = group_weight[g2] + rating[i];\n                        \n                        double old_contrib = (group_weight[g1] - mean) * (group_weight[g1] - mean) +\n                                            (group_weight[g2] - mean) * (group_weight[g2] - mean);\n                        double new_contrib = (new_w1 - mean) * (new_w1 - mean) +\n                                            (new_w2 - mean) * (new_w2 - mean);\n                        \n                        if (new_contrib < old_contrib - 1e-9) {\n                            assignment[i] = g2;\n                            \n                            auto it = find(groups[g1].begin(), groups[g1].end(), i);\n                            groups[g1].erase(it);\n                            groups[g2].push_back(i);\n                            \n                            group_weight[g1] = new_w1;\n                            group_weight[g2] = new_w2;\n                            \n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output 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\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    \n    int bps = n / m;  // boxes per stack (20 for n=200, m=10)\n    \n    // Stack representation: stacks[i] = boxes from bottom to top (0-indexed)\n    vector<vector<int>> stacks(m);\n    // Position tracking for O(1) lookup\n    vector<int> box_stack(n + 1);   // which stack contains box v\n    vector<int> box_height(n + 1);  // height in that stack (0 = bottom)\n    \n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < bps; j++) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            box_stack[box] = i;\n            box_height[box] = j;\n        }\n    }\n    \n    vector<pair<int, int>> ops;\n    \n    // Helper function to update position tracking for a stack\n    auto update_positions = [&](int s) {\n        for (size_t i = 0; i < stacks[s].size(); i++) {\n            int b = stacks[s][i];\n            box_stack[b] = s;\n            box_height[b] = (int)i;\n        }\n    };\n    \n    // Helper function to find best destination stack for moving boxes\n    auto find_best_destination = [&](int exclude_stack, const vector<int>& moving_boxes, int current_target) -> int {\n        int best = -1;\n        long long best_score = -1000000000000LL;\n        \n        for (int d = 0; d < m; d++) {\n            if (d == exclude_stack) continue;\n            \n            long long score = 0;\n            \n            // Strong preference for empty stacks (no future blocking)\n            if (stacks[d].empty()) {\n                score += 10000000;\n            } else {\n                int dest_top = stacks[d].back();\n                // Prefer stacks where top box has larger number (won't block soon)\n                if (dest_top > current_target) {\n                    score += (long long)dest_top * 100;\n                } else {\n                    score -= (long long)(current_target - dest_top) * 500;\n                }\n            }\n            \n            // Bonus for moving high-numbered boxes to this stack\n            for (int b : moving_boxes) {\n                if (b > n) continue;  // already removed\n                if (b > current_target + 100) {\n                    score += 10000;\n                } else if (b > current_target + 50) {\n                    score += 5000;\n                } else if (b > current_target + 20) {\n                    score += 2000;\n                } else if (b > current_target) {\n                    score += 500;\n                } else {\n                    // Box with smaller number - will block future targets!\n                    score -= 50000;\n                }\n            }\n            \n            // Penalty for blocking future targets\n            int dest_size = (int)stacks[d].size();\n            for (int f = current_target + 1; f <= min(current_target + 30, n); f++) {\n                if (box_stack[f] == d && box_height[f] >= dest_size) {\n                    // This future target would be blocked by our move\n                    score -= 200000;\n                }\n            }\n            \n            // Prefer stacks with fewer boxes (maintain flexibility)\n            score -= (long long)stacks[d].size() * 200;\n            \n            // Prefer stacks with high-value boxes at bottom\n            if (!stacks[d].empty() && stacks[d][0] > current_target + 50) {\n                score += 1000;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best = d;\n            }\n        }\n        \n        // Fallback if no destination found\n        if (best == -1) {\n            for (int d = 0; d < m; d++) {\n                if (d != exclude_stack) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n        \n        return best;\n    };\n    \n    // Process each target box in ascending order\n    for (int target = 1; target <= n; target++) {\n        int s = box_stack[target];\n        int h = box_height[target];\n        int top = (int)stacks[s].size() - 1;\n        \n        // While target is not at the top, move boxes above it\n        while (h < top) {\n            // Move the box immediately above target (and all boxes above that)\n            int move_box = stacks[s][h + 1];\n            \n            // Collect all boxes that will be moved\n            vector<int> moving_boxes;\n            for (int i = h + 1; i <= top; i++) {\n                moving_boxes.push_back(stacks[s][i]);\n            }\n            \n            // Find best destination stack\n            int dest = find_best_destination(s, moving_boxes, target);\n            \n            // Output operation 1: move move_box and all above it to dest stack\n            ops.push_back({move_box, dest + 1});\n            \n            // Execute the move: remove from source stack\n            stacks[s].resize(h + 1);\n            update_positions(s);\n            \n            // Add to destination stack\n            for (int b : moving_boxes) {\n                stacks[dest].push_back(b);\n            }\n            update_positions(dest);\n            \n            // Update top for next iteration\n            top = (int)stacks[s].size() - 1;\n        }\n        \n        // Now target is at top, remove it (operation 2)\n        ops.push_back({target, 0});\n        stacks[s].pop_back();\n        update_positions(s);\n    }\n    \n    // Output all operations\n    for (const auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    vector<vector<int>> d(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    const int DI[] = {-1, 0, 1, 0};\n    const int DJ[] = {0, 1, 0, -1};\n    const char DIR[] = {'U', 'R', 'D', 'L'};\n    \n    // Check if move is valid (no wall)\n    auto can_move = [&](int i, int j, int dir) -> bool {\n        int ni = i + DI[dir], nj = j + DJ[dir];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        \n        if (dir == 0 && i > 0 && h[i-1][j] == '1') return false;\n        if (dir == 1 && v[i][j] == '1') return false;\n        if (dir == 2 && h[i][j] == '1') return false;\n        if (dir == 3 && j > 0 && v[i][j-1] == '1') return false;\n        \n        return true;\n    };\n    \n    // BFS to find shortest path from (si,sj) to (ti,tj)\n    auto find_path = [&](int si, int sj, int ti, int tj) -> string {\n        if (si == ti && sj == tj) return \"\";\n        \n        vector<vector<int>> bd(N, vector<int>(N, -1));\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n        vector<vector<int>> pdir(N, vector<int>(N, -1));\n        queue<pair<int,int>> bq;\n        \n        bd[si][sj] = 0;\n        bq.push({si, sj});\n        \n        while (!bq.empty()) {\n            auto [i, j] = bq.front();\n            bq.pop();\n            \n            if (i == ti && j == tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (can_move(i, j, dir)) {\n                    int ni = i + DI[dir], nj = j + DJ[dir];\n                    if (bd[ni][nj] == -1) {\n                        bd[ni][nj] = bd[i][j] + 1;\n                        parent[ni][nj] = {i, j};\n                        pdir[ni][nj] = dir;\n                        bq.push({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (bd[ti][tj] == -1) return \"\";\n        \n        string path = \"\";\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path += DIR[pdir[ci][cj]];\n            auto [pi, pj] = parent[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    // Create priority list of squares (higher d = higher priority for revisits)\n    vector<tuple<int, int, int>> squares;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            squares.push_back({d[i][j], i, j});\n        }\n    }\n    sort(squares.rbegin(), squares.rend());\n    \n    // DFS to create initial route that visits all squares and returns to (0,0)\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string route = \"\";\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        // Sort neighbors by d value (visit high-d squares first in spanning tree)\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            if (can_move(i, j, dir)) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        \n        for (auto [val, dir] : neighbors) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            route += DIR[dir];\n            dfs(ni, nj);\n            // Return: opposite direction - this ensures we return to (i,j)\n            int opp_dir = (dir + 2) % 4;\n            route += DIR[opp_dir];\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Verify the route ends at (0,0)\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    // If not at (0,0), add return path\n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        route += back;\n    }\n    \n    // Now optimize: add revisits to high-priority squares\n    // Strategy: insert round-trips to high-d squares at strategic points\n    const int MAX_LEN = 100000;\n    \n    if ((int)route.length() < MAX_LEN - 1000) {\n        // Calculate current visit counts\n        vector<vector<int>> visit_count(N, vector<int>(N, 0));\n        int pi = 0, pj = 0;\n        visit_count[0][0]++;\n        \n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            visit_count[pi][pj]++;\n        }\n        \n        // Try to add revisits to high-priority squares\n        // We'll insert round-trips at positions where we're close to target squares\n        string optimized = route;\n        \n        // Find all positions in the route\n        vector<pair<int,int>> positions;\n        positions.push_back({0, 0});\n        pi = 0; pj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            positions.push_back({pi, pj});\n        }\n        \n        // Add revisits to top priority squares\n        for (auto [val, ti, tj] : squares) {\n            if ((int)optimized.length() >= MAX_LEN - 500) break;\n            \n            // Find the closest position in route to this square\n            int best_idx = -1;\n            int best_dist = N * N;\n            for (int idx = 0; idx < (int)positions.size(); idx++) {\n                int dist = abs(positions[idx].first - ti) + abs(positions[idx].second - tj);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_idx = idx;\n                }\n            }\n            \n            if (best_idx >= 0 && best_dist < N) {\n                // Check if we should add a revisit\n                int current_visits = visit_count[ti][tj];\n                int target_visits = max(2, (int)(val * optimized.length() / 50000));\n                \n                if (current_visits < target_visits) {\n                    // Insert a round-trip to (ti, tj) at position best_idx\n                    int pi_pos = positions[best_idx].first;\n                    int pj_pos = positions[best_idx].second;\n                    \n                    string to_target = find_path(pi_pos, pj_pos, ti, tj);\n                    string back = find_path(ti, tj, pi_pos, pj_pos);\n                    \n                    if (!to_target.empty() && !back.empty() && \n                        (int)optimized.length() + (int)to_target.length() + (int)back.length() < MAX_LEN - 100) {\n                        // Insert at position best_idx\n                        string new_route = optimized.substr(0, best_idx);\n                        new_route += to_target + back;\n                        new_route += optimized.substr(best_idx);\n                        optimized = new_route;\n                        visit_count[ti][tj]++;\n                        \n                        // Update positions (simplified - just add the detour positions)\n                        // This is approximate but should work for validation\n                    }\n                }\n            }\n        }\n        \n        route = optimized;\n    }\n    \n    // Final validation: ensure route ends at (0,0)\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n            route += back;\n        } else {\n            // Truncate and add return path\n            route = route.substr(0, MAX_LEN - (int)back.length() - 10);\n            route += back;\n        }\n    }\n    \n    // Final validation: ensure all squares visited\n    vector<vector<bool>> final_visited(N, vector<bool>(N, false));\n    int vi = 0, vj = 0;\n    final_visited[0][0] = true;\n    \n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                vi += DI[dir];\n                vj += DJ[dir];\n                break;\n            }\n        }\n        if (vi < 0 || vi >= N || vj < 0 || vj >= N) {\n            // Invalid move - this shouldn't happen\n            cerr << \"Invalid move detected!\" << endl;\n            return 1;\n        }\n        final_visited[vi][vj] = true;\n    }\n    \n    // If any square not visited, we have a problem - but DFS should have visited all\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!final_visited[i][j]) {\n                cerr << \"Square (\" << i << \",\" << j << \") not visited!\" << endl;\n                // Try to add it if possible\n                if ((int)route.length() < MAX_LEN - 500) {\n                    string to_sq = find_path(0, 0, i, j);\n                    string back = find_path(i, j, 0, 0);\n                    if (!to_sq.empty() && !back.empty()) {\n                        route = to_sq + back + route;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure length constraint\n    if ((int)route.length() > MAX_LEN) {\n        route = route.substr(0, MAX_LEN);\n        // Re-validate end position\n        ci = 0; cj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n        }\n        if (ci != 0 || cj != 0) {\n            string back = find_path(ci, cj, 0, 0);\n            if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n                route += back;\n            }\n        }\n    }\n    \n    // One final check\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        // This is a critical error - truncate to make it valid\n        cerr << \"Warning: Route does not end at (0,0), truncating\" << endl;\n        // Find the last position that was at (0,0)\n        int last_zero = 0;\n        ci = 0; cj = 0;\n        for (int idx = 0; idx < (int)route.length(); idx++) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == route[idx]) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n            if (ci == 0 && cj == 0) {\n                last_zero = idx + 1;\n            }\n        }\n        route = route.substr(0, last_zero);\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<string> grid;\nvector<string> targets;\nvector<vector<pair<int, int>>> char_positions;\nvector<vector<int>> overlap;\nvector<vector<bool>> contains;\n\ninline int dist(pair<int, int> p1, pair<int, int> p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\nint calc_overlap(const string& a, const string& b) {\n    int max_ov = 0;\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = 1; len <= max_len; len++) {\n        if (a.substr(a.size() - len) == b.substr(0, len)) {\n            max_ov = len;\n        }\n    }\n    return max_ov;\n}\n\nbool string_contains(const string& a, const string& b) {\n    return a.find(b) != string::npos;\n}\n\npair<string, vector<pair<int, int>>> build_solution_fast(const vector<int>& order, int& total_cost) {\n    string S;\n    S.reserve(1000);\n    vector<pair<int, int>> positions;\n    positions.reserve(5000);\n    pair<int, int> cur_pos = {si, sj};\n    total_cost = 0;\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        int overlap_len = 0;\n        \n        if ((int)S.size() >= 4) {\n            for (int len = min(5, (int)S.size()); len >= 1; len--) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    if (S[S.size() - len + k] != t[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        for (int i = overlap_len; i < 5; i++) {\n            char c = t[i];\n            int c_idx = c - 'A';\n            const auto& positions_c = char_positions[c_idx];\n            \n            pair<int, int> best_pos = positions_c[0];\n            int best_d = dist(cur_pos, best_pos);\n            \n            for (size_t k = 1; k < positions_c.size(); k++) {\n                int d = dist(cur_pos, positions_c[k]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_pos = positions_c[k];\n                }\n            }\n            \n            total_cost += best_d + 1;\n            positions.push_back(best_pos);\n            S += c;\n            cur_pos = best_pos;\n        }\n    }\n    \n    return {S, positions};\n}\n\nbool check_coverage_fast(const string& S) {\n    for (int i = 0; i < M; i++) {\n        if (S.find(targets[i]) == string::npos) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvector<int> build_greedy_order(mt19937& rng, bool randomize = false) {\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    \n    uniform_int_distribution<int> dist_int(0, M - 1);\n    int start = randomize ? dist_int(rng) : 0;\n    \n    order.push_back(start);\n    used[start] = true;\n    \n    for (int step = 1; step < M; step++) {\n        int last = order.back();\n        int best_next = -1;\n        int best_score = -1;\n        \n        vector<pair<int, int>> candidates;\n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                candidates.push_back({overlap[last][i], i});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first > b.first;\n        });\n        \n        int top_k = randomize ? min((int)candidates.size(), 20) : 1;\n        uniform_int_distribution<int> pick_dist(0, top_k - 1);\n        int pick_idx = randomize ? pick_dist(rng) : 0;\n        best_next = candidates[pick_idx].second;\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\npair<int, int> two_opt_swap(const vector<int>& order, int i, int j) {\n    int gain = 0;\n    \n    if (i > 0) {\n        gain += overlap[order[i]][order[j]] - overlap[order[i-1]][order[i]];\n        gain -= overlap[order[i-1]][order[j]] - overlap[order[i-1]][order[i]];\n    }\n    \n    if (j < (int)order.size() - 1) {\n        gain += overlap[order[j-1]][order[j+1]] - overlap[order[j]][order[j+1]];\n    }\n    \n    if (i > 0 && j < (int)order.size() - 1) {\n        gain += overlap[order[j]][order[j+1]] + overlap[order[i-1]][order[i]];\n        gain -= overlap[order[i-1]][order[j]] + overlap[order[j-1]][order[j+1]];\n    }\n    \n    return {j, gain};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    grid.resize(N);\n    char_positions.resize(26);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    overlap.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) {\n                overlap[i][j] = calc_overlap(targets[i], targets[j]);\n            }\n        }\n    }\n    \n    contains.assign(M, vector<bool>(M, false));\n    vector<bool> needed(M, true);\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j && string_contains(targets[i], targets[j])) {\n                contains[i][j] = true;\n            }\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> best_order;\n    vector<pair<int, int>> best_positions;\n    int best_cost = INT_MAX;\n    \n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // Phase 1: Generate diverse initial solutions (0-800ms)\n    int trial = 0;\n    while (get_elapsed_ms() < 800) {\n        bool randomize = (trial % 3 != 0);\n        vector<int> order = build_greedy_order(rng, randomize);\n        \n        int cost;\n        auto [S, positions] = build_solution_fast(order, cost);\n        \n        if ((int)positions.size() <= 5000 && check_coverage_fast(S)) {\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_order = order;\n                best_positions = positions;\n            }\n        }\n        trial++;\n    }\n    \n    // Phase 2: Local search with 2-opt (800-1500ms)\n    if (!best_order.empty()) {\n        while (get_elapsed_ms() < 1500) {\n            bool improved = false;\n            \n            for (int i = 0; i < M - 1 && get_elapsed_ms() < 1500; i++) {\n                for (int j = i + 2; j < M; j++) {\n                    vector<int> new_order = best_order;\n                    reverse(new_order.begin() + i + 1, new_order.begin() + j + 1);\n                    \n                    int cost;\n                    auto [S, positions] = build_solution_fast(new_order, cost);\n                    \n                    if ((int)positions.size() <= 5000 && check_coverage_fast(S) && cost < best_cost) {\n                        best_cost = cost;\n                        best_order = new_order;\n                        best_positions = positions;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Phase 3: Simulated annealing (1500-1850ms)\n    if (!best_order.empty()) {\n        double temperature = best_cost * 0.1;\n        double cooling_rate = 0.95;\n        uniform_real_distribution<double> dist_real(0.0, 1.0);\n        uniform_int_distribution<int> swap_dist(0, M - 2);\n        \n        vector<int> current_order = best_order;\n        int current_cost = best_cost;\n        \n        while (get_elapsed_ms() < 1850) {\n            int i = swap_dist(rng);\n            int j = i + 1 + (rng() % (M - i - 1));\n            j = min(j, M - 1);\n            \n            vector<int> new_order = current_order;\n            swap(new_order[i], new_order[j]);\n            \n            int cost;\n            auto [S, positions] = build_solution_fast(new_order, cost);\n            \n            bool accept = false;\n            if ((int)positions.size() <= 5000 && check_coverage_fast(S)) {\n                if (cost < current_cost) {\n                    accept = true;\n                } else {\n                    double delta = (double)(cost - current_cost);\n                    double prob = exp(-delta / temperature);\n                    if (dist_real(rng) < prob) {\n                        accept = true;\n                    }\n                }\n            }\n            \n            if (accept) {\n                current_order = new_order;\n                current_cost = cost;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n    }\n    \n    // Final rebuild with best order\n    if (!best_order.empty()) {\n        int cost;\n        auto [S, positions] = build_solution_fast(best_order, cost);\n        best_positions = positions;\n    }\n    \n    // Fallback\n    if (best_positions.empty()) {\n        pair<int, int> cur_pos = {si, sj};\n        for (int i = 0; i < M; i++) {\n            for (char c : targets[i]) {\n                int c_idx = c - 'A';\n                pair<int, int> best_pos = char_positions[c_idx][0];\n                for (auto& pos : char_positions[c_idx]) {\n                    if (dist(cur_pos, pos) < dist(cur_pos, best_pos)) {\n                        best_pos = pos;\n                    }\n                }\n                best_positions.push_back(best_pos);\n                cur_pos = best_pos;\n            }\n        }\n    }\n    \n    for (auto& p : best_positions) {\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 <random>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for problem data\nint N, M;\ndouble eps;\nstruct Shape {\n    int id;\n    vector<pair<int, int>> cells;\n    int max_r, max_c;\n};\nvector<Shape> shapes;\n\n// Interaction functions\nvoid query_drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n}\n\nint read_drill() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid query_divine(const vector<pair<int, int>>& pts) {\n    cout << \"q \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_divine() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid guess(const vector<pair<int, int>>& pts) {\n    cout << \"a \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_guess() {\n    int res;\n    cin >> res;\n    return res;\n}\n\n// Solver state\nvector<double> target_row_sum, target_col_sum;\nvector<int> current_pos; // r0, c0, r1, c1, ...\n\n// Evaluate loss\ndouble evaluate_loss(const vector<int>& pos) {\n    vector<int> r_sum(N, 0), c_sum(N, 0);\n    for (int k = 0; k < M; ++k) {\n        int r = pos[2 * k];\n        int c = pos[2 * k + 1];\n        const auto& shape = shapes[k];\n        for (auto& cell : shape.cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            // Bounds check technically not needed if pos is valid, but safe\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                r_sum[rr]++;\n                c_sum[cc]++;\n            }\n        }\n    }\n    double loss = 0;\n    for (int i = 0; i < N; ++i) {\n        double diff = r_sum[i] - target_row_sum[i];\n        loss += diff * diff;\n        diff = c_sum[i] - target_col_sum[i];\n        loss += diff * diff;\n    }\n    return loss;\n}\n\nint main() {\n    // Fast IO\n    cin.tie(NULL);\n    cout.tie(NULL);\n\n    // Read Input\n    if (!(cin >> N >> M >> eps)) return 0;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shapes[k].id = k;\n        shapes[k].cells.resize(d);\n        int max_r = -1, max_c = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n            max_r = max(max_r, shapes[k].cells[i].first);\n            max_c = max(max_c, shapes[k].cells[i].second);\n        }\n        shapes[k].max_r = max_r;\n        shapes[k].max_c = max_c;\n    }\n\n    // 1. Query Rows and Cols\n    target_row_sum.resize(N);\n    target_col_sum.resize(N);\n    \n    // Helper to get target sum from observation\n    auto get_target = [&](int obs, int k) {\n        double mu = k * eps;\n        double scale = 1.0 - 2.0 * eps;\n        if (abs(scale) < 1e-9) return 0.0; \n        double est = (obs - mu) / scale;\n        return max(0.0, est);\n    };\n\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_pts;\n        row_pts.reserve(N);\n        for (int j = 0; j < N; ++j) row_pts.push_back({i, j});\n        query_divine(row_pts);\n        int obs = read_divine();\n        target_row_sum[i] = get_target(obs, N);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_pts;\n        col_pts.reserve(N);\n        for (int i = 0; i < N; ++i) col_pts.push_back({i, j});\n        query_divine(col_pts);\n        int obs = read_divine();\n        target_col_sum[j] = get_target(obs, N);\n    }\n\n    // 2. Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    current_pos.resize(2 * M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = N - 1 - shapes[k].max_r;\n        int max_c = N - 1 - shapes[k].max_c;\n        // Ensure non-negative range\n        if (max_r < 0) max_r = 0;\n        if (max_c < 0) max_c = 0;\n        current_pos[2 * k] = uniform_int_distribution<>(0, max_r)(rng);\n        current_pos[2 * k + 1] = uniform_int_distribution<>(0, max_c)(rng);\n    }\n\n    double current_loss = evaluate_loss(current_pos);\n    double best_loss = current_loss;\n    vector<int> best_pos = current_pos;\n\n    double temp = 100.0;\n    double cooling_rate = 0.995;\n    auto start_time = chrono::steady_clock::now();\n    \n    // Run SA for up to 2.0 seconds\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 2.0) break;\n        \n        // Propose move\n        int k = uniform_int_distribution<>(0, M - 1)(rng);\n        int dim = uniform_int_distribution<>(0, 1)(rng); // 0 for r, 1 for c\n        int delta = uniform_int_distribution<>(-1, 1)(rng);\n        if (delta == 0) delta = 1;\n        \n        int idx = 2 * k + dim;\n        int old_val = current_pos[idx];\n        int new_val = old_val + delta;\n        \n        int max_val = N - 1 - (dim == 0 ? shapes[k].max_r : shapes[k].max_c);\n        if (new_val < 0 || new_val > max_val) continue;\n        \n        current_pos[idx] = new_val;\n        double new_loss = evaluate_loss(current_pos);\n        \n        double diff = new_loss - current_loss;\n        \n        if (diff < 0 || exp(-diff / temp) > uniform_real_distribution<>(0.0, 1.0)(rng)) {\n            current_loss = new_loss;\n            if (new_loss < best_loss) {\n                best_loss = new_loss;\n                best_pos = current_pos;\n            }\n        } else {\n            current_pos[idx] = old_val; // Revert\n        }\n        \n        temp *= cooling_rate;\n        if (temp < 1e-3) break;\n    }\n\n    // 3. Generate Prediction\n    vector<pair<int, int>> s_cand;\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        int r = best_pos[2 * k];\n        int c = best_pos[2 * k + 1];\n        for (auto& cell : shapes[k].cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                grid[rr][cc]++;\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                s_cand.push_back({i, j});\n            }\n        }\n    }\n\n    // 4. Verify Rest (Drill all cells not in s_cand)\n    // This ensures we don't miss any oil (False Negatives).\n    // False Positives in s_cand are risked but unlikely if loss is low.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 0) {\n                query_drill(i, j);\n                int v = read_drill();\n                if (v > 0) {\n                    s_cand.push_back({i, j});\n                    grid[i][j] = v;\n                }\n            }\n        }\n    }\n\n    // 5. Guess\n    // Sort s_cand for consistency\n    sort(s_cand.begin(), s_cand.end());\n    // Remove duplicates just in case (logic shouldn't produce any)\n    s_cand.erase(unique(s_cand.begin(), s_cand.end()), s_cand.end());\n    \n    guess(s_cand);\n    int res = read_guess();\n    if (res == 1) return 0;\n    \n    // If wrong, we could try to recover, but for this solution we exit.\n    // In a contest, one might fallback to drilling everything if guess fails.\n    // But we already drilled s_rest. The only error source is s_cand false positives.\n    // To fix, we would need to drill s_cand cells to check if v=0.\n    // Given time limit, we stop.\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global constants\nconst int W = 1000;\n\n// Problem data\nint D, N;\nvector<vector<int>> a; // a[d][k]\n\n// Grid dimensions\nint R, C;\n\n// State: H[d][r], W[d][c]\n// Using vector of vectors\nvector<vector<int>> H;\nvector<vector<int>> W_vec; // Renamed to W_vec to avoid conflict with constant W\n\n// Mapping from k to (r, c)\npair<int, int> get_rc(int k) {\n    return {k / C, k % C};\n}\n\n// Calculate total cost\nlong long calculate_cost() {\n    long long total_cost = 0;\n    \n    // Area costs\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                total_cost += 100LL * (a[d][k] - area);\n            }\n        }\n    }\n    \n    // Partition costs\n    for (int d = 1; d < D; ++d) {\n        // Horizontal lines\n        int y_prev = 0;\n        int y_curr = 0;\n        for (int r = 0; r < R; ++r) {\n            y_prev += H[d-1][r];\n            y_curr += H[d][r];\n            total_cost += (long long)W * abs(y_prev - y_curr);\n        }\n        // Vertical lines\n        int x_prev = 0;\n        int x_curr = 0;\n        for (int c = 0; c < C; ++c) {\n            x_prev += W_vec[d-1][c];\n            x_curr += W_vec[d][c];\n            total_cost += (long long)W * abs(x_prev - x_curr);\n        }\n    }\n    \n    return total_cost;\n}\n\n// Calculate delta cost for a change in H[d][r] or W_vec[d][c]\n// This is more efficient for SA\nlong long calculate_delta_cost(int d, int type, int idx, int delta) {\n    // type 0: H, 1: W_vec\n    long long delta_cost = 0;\n    \n    // Area cost change for day d\n    if (type == 0) { // H[d][idx] changes by delta\n        int r = idx;\n        int old_h = H[d][r];\n        int new_h = old_h + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kr == r) {\n                long long old_area = (long long)old_h * W_vec[d][kc];\n                long long new_area = (long long)new_h * W_vec[d][kc];\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    } else { // W_vec[d][idx] changes by delta\n        int c = idx;\n        int old_w = W_vec[d][c];\n        int new_w = old_w + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kc == c) {\n                long long old_area = (long long)H[d][kr] * old_w;\n                long long new_area = (long long)H[d][kr] * new_w;\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    }\n    \n    // Partition cost change\n    // Affected days: d (with d-1) and d+1 (with d)\n    // If d=0, only d+1. But L_0=0, so partition cost starts from d=1.\n    // Partition cost between d-1 and d depends on cumulative sums at d-1 and d.\n    // Changing H[d][idx] changes cumulative sums for r >= idx on day d.\n    \n    auto update_partition = [&](int day_idx, int type_p, int idx_p, int delta_p) {\n        // day_idx is the day being modified (d)\n        // We need to compare with day_idx-1 and day_idx+1\n        long long cost_change = 0;\n        \n        // Compare with day_idx - 1\n        if (day_idx > 0) {\n            int sum_prev = 0;\n            int sum_curr = 0;\n            // We only need to sum from idx_p to end because before idx_p sums are same\n            // But wait, cumulative sum at r depends on H[0]...H[r].\n            // If H[idx] changes, all cumulative sums Y_r for r > idx change.\n            // Y_idx also changes.\n            // So for all r from idx to R-1, Y_r changes by delta_p.\n            // Cost adds W * |delta_p| for each such line.\n            // Number of lines affected: R - idx_p.\n            // Wait, lines are at Y_1, ..., Y_R.\n            // Y_r = sum(H[0]...H[r-1]).\n            // If H[idx] changes, Y_r changes for r > idx.\n            // So lines Y_{idx+1} ... Y_R change.\n            // Count = R - idx.\n            // But Y_R is at W (fixed sum), so Y_R doesn't change?\n            // We enforce sum H = W. So if H[idx] += delta, some H[other] -= delta.\n            // So Y_R remains W.\n            // So lines affected are those between idx and the 'other' index.\n            // This makes delta calculation complex if we swap.\n            // Let's stick to full cost recalc for partition if needed, or simplify.\n            // Given N is small, full partition cost recalc for affected days is fast.\n            // Affected days: d-1 (boundary d-1|d) and d (boundary d|d+1).\n            // Just recalc partition cost for these two boundaries.\n        }\n        return cost_change;\n    };\n\n    // Simpler approach: Recalculate partition cost for boundaries involving day d.\n    // Boundaries: (d-1, d) and (d, d+1).\n    // Store previous partition cost for these boundaries to subtract.\n    // But implementing this cleanly is verbose.\n    // Given the speed of O(N) area calc, O(R+C) partition calc is also fast.\n    // Let's just calculate the delta for partition explicitly.\n    \n    // Partition cost contribution of day d with d-1:\n    // Sum_r W * |Y_{d,r} - Y_{d-1,r}|\n    // If H[d][idx] changes by delta, Y_{d,r} changes by delta for r > idx.\n    // (Assuming we adjust another H[d][other] to keep sum constant).\n    // If we do swap move (H[idx]+=1, H[other]-=1), then Y_r changes by 1 for r in (min, max].\n    // This is getting complicated for delta.\n    // Given 3 seconds, we can afford O(R+C) per step.\n    // Let's implement a function that recalculates partition cost for day d boundaries.\n    \n    return delta_cost; // Placeholder, will implement full delta in SA loop or use full cost for safety if fast enough\n}\n\n// Function to calculate partition cost between day d1 and d2\nlong long calc_partition_between(int d1, int d2) {\n    long long cost = 0;\n    int y1 = 0, y2 = 0;\n    for (int r = 0; r < R; ++r) {\n        y1 += H[d1][r];\n        y2 += H[d2][r];\n        cost += (long long)W * abs(y1 - y2);\n    }\n    int x1 = 0, x2 = 0;\n    for (int c = 0; c < C; ++c) {\n        x1 += W_vec[d1][c];\n        x2 += W_vec[d2][c];\n        cost += (long long)W * abs(x1 - x2);\n    }\n    return cost;\n}\n\n// Global current cost\nlong long current_cost = 0;\n\nvoid update_cost_after_change(int d, const vector<int>& old_H, const vector<int>& old_W) {\n    // Recompute area cost for day d\n    // Recompute partition cost for (d-1, d) and (d, d+1)\n    // This is O(N + R + C).\n    \n    // We need to subtract old contributions and add new.\n    // To do this cleanly, we need to store per-day costs.\n    // Let's store vector<long long> area_cost(D), partition_cost(D) (cost between d-1 and d)\n    // partition_cost[0] = 0.\n    // Total = sum(area) + sum(partition).\n}\n\n// Let's use a simpler SA structure where we just recompute necessary parts.\n// Since D is small, we can store per-day area cost and per-boundary partition cost.\nvector<long long> day_area_cost;\nvector<long long> boundary_part_cost; // size D, boundary_part_cost[d] is cost between d-1 and d. [0] is 0.\n\nvoid init_costs() {\n    day_area_cost.assign(D, 0);\n    boundary_part_cost.assign(D, 0);\n    \n    for (int d = 0; d < D; ++d) {\n        long long cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                cost += 100LL * (a[d][k] - area);\n            }\n        }\n        day_area_cost[d] = cost;\n    }\n    \n    for (int d = 1; d < D; ++d) {\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n    }\n    \n    current_cost = 0;\n    for (long long c : day_area_cost) current_cost += c;\n    for (long long c : boundary_part_cost) current_cost += c;\n}\n\nvoid apply_move_and_update(int d, int type, int idx, int delta) {\n    // Apply move\n    if (type == 0) {\n        H[d][idx] += delta;\n    } else {\n        W_vec[d][idx] += delta;\n    }\n    \n    // Update day_area_cost[d]\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    // Update boundary_part_cost[d] (between d-1 and d)\n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    // Update boundary_part_cost[d+1] (between d and d+1)\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nvoid revert_move_and_update(int d, int type, int idx, int delta) {\n    // Revert\n    if (type == 0) {\n        H[d][idx] -= delta;\n    } else {\n        W_vec[d][idx] -= delta;\n    }\n    \n    // Recalculate costs (same as apply, effectively undoing the change in values)\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int W_in;\n    if (!(cin >> W_in >> D >> N)) return 0;\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    // Determine R, C\n    // Try to find R that minimizes initial area cost heuristic\n    int best_R = 1;\n    long long min_init_cost = -1;\n    \n    for (int r_try = 1; r_try <= N; ++r_try) {\n        int c_try = (N + r_try - 1) / r_try;\n        // Heuristic cost estimate\n        // Distribute W to rows/cols based on sqrt(area)\n        long long est_cost = 0;\n        // Just pick the one closest to square\n        if (min_init_cost == -1 || abs(r_try - c_try) < abs(best_R - (N + best_R - 1) / best_R)) {\n             best_R = r_try;\n        }\n    }\n    // Prefer square-ish\n    best_R = max(1, (int)round(sqrt(N)));\n    R = best_R;\n    C = (N + R - 1) / R;\n    \n    // Initialize H and W_vec\n    H.assign(D, vector<int>(R));\n    W_vec.assign(D, vector<int>(C));\n    \n    mt19937 rng(12345);\n    \n    for (int d = 0; d < D; ++d) {\n        // Calculate target \"weight\" for each row and col\n        vector<long long> row_weight(R, 0);\n        vector<long long> col_weight(C, 0);\n        \n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            // Use sqrt of area as weight\n            long long w = (long long)sqrt(a[d][k]) + 1;\n            row_weight[r] += w;\n            col_weight[c] += w;\n        }\n        \n        long long sum_rw = accumulate(row_weight.begin(), row_weight.end(), 0LL);\n        long long sum_cw = accumulate(col_weight.begin(), col_weight.end(), 0LL);\n        \n        // Distribute W\n        int rem_h = W;\n        for (int r = 0; r < R; ++r) {\n            int h = (sum_rw == 0) ? W/R : (int)((double)row_weight[r] / sum_rw * W);\n            H[d][r] = h;\n            rem_h -= h;\n        }\n        // Distribute remainder\n        int r_idx = 0;\n        while (rem_h > 0) {\n            H[d][r_idx % R]++;\n            rem_h--;\n            r_idx++;\n        }\n        // Ensure min 1\n        for(int r=0; r<R; ++r) if(H[d][r] < 1) H[d][r] = 1;\n        // Re-normalize sum to W (simple adjust)\n        int sum_h = accumulate(H[d].begin(), H[d].end(), 0);\n        if (sum_h != W) {\n            H[d][0] += (W - sum_h);\n        }\n        \n        int rem_w = W;\n        for (int c = 0; c < C; ++c) {\n            int w = (sum_cw == 0) ? W/C : (int)((double)col_weight[c] / sum_cw * W);\n            W_vec[d][c] = w;\n            rem_w -= w;\n        }\n        int c_idx = 0;\n        while (rem_w > 0) {\n            W_vec[d][c_idx % C]++;\n            rem_w--;\n            c_idx++;\n        }\n        for(int c=0; c<C; ++c) if(W_vec[d][c] < 1) W_vec[d][c] = 1;\n        int sum_w = accumulate(W_vec[d].begin(), W_vec[d].end(), 0);\n        if (sum_w != W) {\n            W_vec[d][0] += (W - sum_w);\n        }\n    }\n    \n    init_costs();\n    \n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double T = 10000.0;\n    double T_end = 1.0;\n    double alpha = 0.99995;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break; // Leave margin\n        \n        // Pick move\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        int type = uniform_int_distribution<int>(0, 1)(rng); // 0: H, 1: W\n        int dim = (type == 0) ? R : C;\n        int idx = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        // Pick another index to swap with to maintain sum\n        int idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        while (idx2 == idx) idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 1)(rng)) delta = -1;\n        \n        // Check validity (must be >= 1)\n        if (type == 0) {\n            if (H[d][idx] + delta < 1 || H[d][idx2] - delta < 1) continue;\n        } else {\n            if (W_vec[d][idx] + delta < 1 || W_vec[d][idx2] - delta < 1) continue;\n        }\n        \n        // Apply first change\n        if (type == 0) H[d][idx] += delta;\n        else W_vec[d][idx] += delta;\n        \n        // Calculate cost delta roughly? \n        // No, let's just apply both and calc cost.\n        if (type == 0) H[d][idx2] -= delta;\n        else W_vec[d][idx2] -= delta;\n        \n        // We need to calculate new cost efficiently.\n        // Since we changed two indices, we can just recompute day_area_cost[d] and boundaries.\n        // Store old values to revert if rejected.\n        int old_val1 = (type == 0) ? H[d][idx] - delta : W_vec[d][idx] - delta;\n        int old_val2 = (type == 0) ? H[d][idx2] + delta : W_vec[d][idx2] + delta;\n        \n        long long old_day_cost = day_area_cost[d];\n        long long old_bound1 = (d > 0) ? boundary_part_cost[d] : 0;\n        long long old_bound2 = (d < D-1) ? boundary_part_cost[d+1] : 0;\n        \n        // Recompute area cost\n        long long new_area_cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                new_area_cost += 100LL * (a[d][k] - area);\n            }\n        }\n        \n        long long new_bound1 = 0, new_bound2 = 0;\n        if (d > 0) new_bound1 = calc_partition_between(d-1, d);\n        if (d < D-1) new_bound2 = calc_partition_between(d, d+1);\n        \n        long long delta_E = (new_area_cost - old_day_cost) + (new_bound1 - old_bound1) + (new_bound2 - old_bound2);\n        \n        bool accept = false;\n        if (delta_E <= 0) accept = true;\n        else {\n            double p = exp(-delta_E / T);\n            if (uniform_real_distribution<double>(0, 1)(rng) < p) accept = true;\n        }\n        \n        if (accept) {\n            current_cost += delta_E;\n            day_area_cost[d] = new_area_cost;\n            if (d > 0) boundary_part_cost[d] = new_bound1;\n            if (d < D-1) boundary_part_cost[d+1] = new_bound2;\n        } else {\n            // Revert\n            if (type == 0) {\n                H[d][idx] = old_val1;\n                H[d][idx2] = old_val2;\n            } else {\n                W_vec[d][idx] = old_val1;\n                W_vec[d][idx2] = old_val2;\n            }\n        }\n        \n        T *= alpha;\n        iter++;\n    }\n    \n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            int i_start = 0;\n            for (int i = 0; i < r; ++i) i_start += H[d][i];\n            int i_end = i_start + H[d][r];\n            \n            int j_start = 0;\n            for (int j = 0; j < c; ++j) j_start += W_vec[d][j];\n            int j_end = j_start + W_vec[d][c];\n            \n            cout << i_start << \" \" << j_start << \" \" << i_end << \" \" << j_end << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\nusing ll = long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int STAMP_SIZE = 3;\nconst int POS_LIMIT = N - STAMP_SIZE + 1; // 7\n\nll A[N][N];\nll S[M][STAMP_SIZE][STAMP_SIZE];\nll Grid[N][N];\nll CurrentScore = 0;\n\nstruct Op {\n    int m, p, q;\n};\nvector<Op> ops;\n\n// Fast random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nll get_rem(ll v) {\n    ll r = v % MOD;\n    if (r < 0) r += MOD;\n    return r;\n}\n\n// Calculate score delta if we add stamp m at (p, q) with multiplier 'delta' (+1 or -1)\n// Does not modify global state, just returns the change in score\nll calc_delta(int m, int p, int q, int delta) {\n    ll score_change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i;\n            int c = q + j;\n            ll old_val = Grid[r][c];\n            ll new_val = old_val + delta * S[m][i][j];\n            \n            // We assume Grid values are always non-negative in valid states\n            // But during calculation new_val could theoretically be negative if we remove \n            // more than added, but we only remove existing ops, so new_val >= A[r][c] >= 0.\n            \n            score_change += get_rem(new_val) - get_rem(old_val);\n        }\n    }\n    return score_change;\n}\n\n// Apply operation to Grid and update CurrentScore\nvoid apply_op(int m, int p, int q, int delta) {\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i;\n            int c = q + j;\n            ll old_val = Grid[r][c];\n            Grid[r][c] += delta * S[m][i][j];\n            ll new_val = Grid[r][c];\n            CurrentScore += get_rem(new_val) - get_rem(old_val);\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, m_in, k_in;\n    if (!(cin >> n_in >> m_in >> k_in)) return 0;\n    // n_in, m_in, k_in should match constants N, M, K but we use constants for array sizing.\n    // The problem guarantees N=9, M=20, K=81.\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n            Grid[i][j] = A[i][j];\n        }\n    }\n\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < STAMP_SIZE; ++i) {\n            for (int j = 0; j < STAMP_SIZE; ++j) {\n                cin >> S[m][i][j];\n            }\n        }\n    }\n\n    // Calculate Initial Score\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            CurrentScore += get_rem(Grid[i][j]);\n        }\n    }\n\n    // Uniform distributions\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, POS_LIMIT - 1);\n    uniform_int_distribution<int> dist_q(0, POS_LIMIT - 1);\n    uniform_int_distribution<int> dist_ops(0, 100); // For move type selection\n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n\n    // Greedy Initialization\n    // Try to add K operations greedily\n    // To speed up, we don't scan all 980 options every time if not needed, \n    // but 980 is small enough.\n    for (int step = 0; step < K; ++step) {\n        ll best_delta = -1e18; // Can be negative\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        // Sample a subset of moves to save time? \n        // 980 * 9 ops is ~9000 ops. K=81 -> 700,000 ops. Very fast.\n        // Let's do full scan for Greedy.\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < POS_LIMIT; ++p) {\n                for (int q = 0; q < POS_LIMIT; ++q) {\n                    ll d = calc_delta(m, p, q, 1);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_delta <= 0) {\n            // No improvement possible by adding more stamps\n            break;\n        }\n\n        ops.push_back({best_m, best_p, best_q});\n        apply_op(best_m, best_p, best_q, 1);\n    }\n\n    ll best_score = CurrentScore;\n    vector<Op> best_ops = ops;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    ll T_start = 1000000000LL; // 1e9\n    double time_limit = 1.900; // seconds\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= time_limit) break;\n\n        double progress = elapsed / time_limit;\n        // Linear cooling\n        ll T = (ll)(T_start * (1.0 - progress));\n        if (T < 1) T = 1;\n\n        // Decide move type\n        int move_type = dist_ops(rng);\n        bool accepted = false;\n        \n        // We need to store state to revert if rejected\n        // But since we calculate delta first, we only apply if accepted.\n        \n        if (ops.empty()) {\n            // Must Add\n            move_type = 200; // Force Add\n        } else if (ops.size() >= K) {\n            // Cannot Add\n            if (move_type < 70) move_type = 0; // Change\n            else move_type = 100; // Remove\n        }\n\n        if (move_type < 70) {\n            // Change an existing operation\n            int idx = uniform_int_distribution<int>(0, ops.size() - 1)(rng);\n            Op old_op = ops[idx];\n            \n            // Propose new op\n            int new_m = dist_m(rng);\n            int new_p = dist_p(rng);\n            int new_q = dist_q(rng);\n            \n            // Avoid null move\n            if (new_m == old_op.m && new_p == old_op.p && new_q == old_op.q) {\n                continue; \n            }\n\n            ll delta = calc_delta(new_m, new_p, new_q, 1);\n            delta += calc_delta(old_op.m, old_op.p, old_op.q, -1);\n\n            if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                // Accept\n                apply_op(old_op.m, old_op.p, old_op.q, -1);\n                apply_op(new_m, new_p, new_q, 1);\n                ops[idx] = {new_m, new_p, new_q};\n                accepted = true;\n            }\n        } else if (move_type < 85) {\n            // Add operation\n            if (ops.size() < K) {\n                int new_m = dist_m(rng);\n                int new_p = dist_p(rng);\n                int new_q = dist_q(rng);\n                \n                ll delta = calc_delta(new_m, new_p, new_q, 1);\n                if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                    apply_op(new_m, new_p, new_q, 1);\n                    ops.push_back({new_m, new_p, new_q});\n                    accepted = true;\n                }\n            }\n        } else {\n            // Remove operation\n            if (!ops.empty()) {\n                int idx = uniform_int_distribution<int>(0, ops.size() - 1)(rng);\n                Op old_op = ops[idx];\n                \n                ll delta = calc_delta(old_op.m, old_op.p, old_op.q, -1);\n                if (delta > 0 || dist_01(rng) < exp((double)delta / T)) {\n                    apply_op(old_op.m, old_op.p, old_op.q, -1);\n                    // Remove from vector efficiently (swap with back and pop)\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                    accepted = true;\n                }\n            }\n        }\n\n        if (CurrentScore > best_score) {\n            best_score = CurrentScore;\n            best_ops = ops;\n        }\n        \n        iter++;\n    }\n\n    // Output\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 <cmath>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction helpers\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar dchar[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int id;\n    int r, c;\n    int holding; // -1 if empty, else container ID\n    bool is_large;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    Crane cranes[N];\n    vector<int> inputs[N]; // Queues of containers to arrive at each row\n    int input_idx[N]; // Next index to arrive\n    int next_dispatch[N]; // Next expected container ID for each dispatch gate\n    int total_dispatched;\n    int total_containers;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = -1;\n            cranes[i].id = i;\n            cranes[i].r = i;\n            cranes[i].c = 0;\n            cranes[i].holding = -1;\n            cranes[i].is_large = (i == 0);\n            input_idx[i] = 0;\n            next_dispatch[i] = i * N;\n            total_dispatched = 0;\n            total_containers = N * N;\n        }\n    }\n};\n\nclass Solver {\n    State state;\n    vector<string> ans;\n    int turn;\n\npublic:\n    Solver(const vector<vector<int>>& A) {\n        ans.resize(N);\n        turn = 0;\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                state.inputs[i].push_back(A[i][j]);\n            }\n        }\n    }\n\n    void receive_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.input_idx[i] < N) {\n                bool has_container = (state.grid[i][0] != -1);\n                bool crane_holding = false;\n                int crane_at_sq = -1;\n                for(int k=0; k<N; ++k) {\n                    if(state.cranes[k].r == i && state.cranes[k].c == 0) {\n                        crane_at_sq = k;\n                        break;\n                    }\n                }\n                if(crane_at_sq != -1 && state.cranes[crane_at_sq].holding != -1) {\n                    crane_holding = true;\n                }\n\n                if(!has_container && !crane_holding) {\n                    state.grid[i][0] = state.inputs[i][state.input_idx[i]];\n                    state.input_idx[i]++;\n                }\n            }\n        }\n    }\n\n    void dispatch_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.grid[i][N-1] != -1) {\n                int cid = state.grid[i][N-1];\n                state.grid[i][N-1] = -1;\n                state.total_dispatched++;\n                if(cid == state.next_dispatch[i]) {\n                    state.next_dispatch[i]++;\n                }\n            }\n        }\n    }\n\n    bool is_valid_move(int crane_idx, int nr, int nc, const vector<pair<int,int>>& planned_next) {\n        if(nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n        \n        // Check collision with other cranes' next positions (already planned)\n        for(int k=0; k<crane_idx; ++k) {\n            if(planned_next[k].first == nr && planned_next[k].second == nc) return false; // Vertex collision\n            // Swap collision\n            if(planned_next[k].first == state.cranes[crane_idx].r && planned_next[k].second == state.cranes[crane_idx].c) {\n                if(nr == state.cranes[k].r && nc == state.cranes[k].c) return false;\n            }\n        }\n        // Check collision with future cranes' current positions (treat as static obstacles)\n        for(int k=crane_idx+1; k<N; ++k) {\n            if(state.cranes[k].r == nr && state.cranes[k].c == nc) return false;\n        }\n        \n        return true;\n    }\n\n    bool is_valid_cell_for_carrying(int crane_idx, int r, int c) {\n        if(state.cranes[crane_idx].holding == -1) return true;\n        if(state.cranes[crane_idx].is_large) return true;\n        // Small crane carrying\n        if(state.grid[r][c] != -1) return false;\n        return true;\n    }\n\n    void solve() {\n        while(turn < MAX_TURNS && state.total_dispatched < state.total_containers) {\n            turn++;\n            receive_containers();\n            \n            vector<char> moves(N, '.');\n            vector<pair<int,int>> planned_next(N);\n            for(int i=0; i<N; ++i) planned_next[i] = {state.cranes[i].r, state.cranes[i].c};\n\n            for(int i=0; i<N; ++i) {\n                Crane &cr = state.cranes[i];\n                long long best_score = -1e18;\n                int nr = cr.r, nc = cr.c;\n                char move_char = '.';\n\n                auto try_move = [&](int tr, int tc, char ch) {\n                    if(!is_valid_move(i, tr, tc, planned_next)) return;\n                    if(!is_valid_cell_for_carrying(i, tr, tc)) return;\n                    \n                    long long score = 0;\n                    \n                    if(cr.holding != -1) {\n                        int target_row = cr.holding / N;\n                        int target_col = N - 1;\n                        \n                        // Distance to target gate\n                        int dist = abs(tr - target_row) + abs(tc - target_col);\n                        score -= dist;\n                        \n                        // Priority for correct next dispatch\n                        if(cr.holding == state.next_dispatch[target_row]) {\n                            score += 5000;\n                        }\n\n                        // Discourage entering Dispatch Column (N-1) unless at target row\n                        // This prevents congestion on the right edge\n                        if(tc == N-1 && tr != target_row) {\n                            score -= 1000; \n                        }\n                        \n                        // Action Q (Place)\n                        if(ch == 'Q') { // 'Q' is handled separately in logic flow usually, but here we simulate outcome\n                             // If we are effectively placing (logic handled outside), but here we evaluate move to (tr,tc)\n                             // Actually, Q happens at current pos.\n                        }\n                    } else {\n                        // Empty\n                        // Priority: Pick up next_dispatch container\n                        int min_dist_input = 10000;\n                        for(int r=0; r<N; ++r) {\n                            if(state.input_idx[r] < N && state.grid[r][0] != -1) {\n                                int cid = state.grid[r][0];\n                                int d = abs(tr - r) + abs(tc - 0);\n                                // Bonus if this container is needed next\n                                if(cid == state.next_dispatch[r]) d -= 50; \n                                if(d < min_dist_input) min_dist_input = d;\n                            }\n                        }\n                        score -= min_dist_input;\n                        \n                        // Priority: Move towards buffers with containers needing transport\n                        if(cr.is_large) {\n                            for(int r=0; r<N; ++r) {\n                                for(int c=1; c<N-1; ++c) {\n                                    if(state.grid[r][c] != -1) {\n                                        int cid = state.grid[r][c];\n                                        if(cid == state.next_dispatch[r/N]) { // Wait, cid/N is target row\n                                            int d = abs(tr - r) + abs(tc - c);\n                                            score -= d; // Attract\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    // Evaluate Action P (Pick up)\n                    if(ch == '.') {\n                        if(cr.holding == -1 && state.grid[cr.r][cr.c] != -1) {\n                            int cid = state.grid[cr.r][cr.c];\n                            int t_row = cid / N;\n                            long long pick_score = score;\n                            if(cid == state.next_dispatch[t_row]) pick_score += 10000;\n                            else pick_score += 1000;\n                            \n                            if(pick_score > best_score) {\n                                best_score = pick_score;\n                                nr = cr.r; nc = cr.c;\n                                move_char = 'P';\n                            }\n                        }\n                        // Evaluate Action Q (Place)\n                        if(cr.holding != -1 && state.grid[cr.r][cr.c] == -1) {\n                            int t_row = cr.holding / N;\n                            long long place_score = score;\n                            \n                            if(cr.r == t_row && cr.c == N-1) {\n                                // Correct Gate\n                                if(cr.holding == state.next_dispatch[t_row]) place_score += 20000;\n                                else place_score += 5000; // Wrong order but correct gate\n                            } else if(cr.c == N-1) {\n                                // Wrong Gate\n                                // M2 penalty is 10^4, M3 is 10^6. Dispatching is better than holding forever.\n                                place_score += 2000; \n                            } else {\n                                // Buffer\n                                place_score -= 500;\n                            }\n                            \n                            if(place_score > best_score) {\n                                best_score = place_score;\n                                nr = cr.r; nc = cr.c;\n                                move_char = 'Q';\n                            }\n                        }\n                    }\n                    \n                    // Evaluate Move\n                    // Only if move_char is still '.' or score is better than current best (which might be P/Q)\n                    // Note: P/Q keeps crane at (cr.r, cr.c). Move changes to (tr, tc).\n                    // We need to compare Move score vs P/Q score.\n                    // But P/Q score was added to `score` (which included movement penalty to tr,tc? No).\n                    // Wait, `score` calculation above assumed moving to (tr, tc).\n                    // P/Q happens at (cr.r, cr.c).\n                    // So we should recalculate base score for stay (cr.r, cr.c) for P/Q comparison.\n                    // To simplify:\n                    // 1. Calculate best Move score.\n                    // 2. Calculate P/Q score at current pos.\n                    // 3. Compare.\n                    \n                    // Let's refactor slightly inside the loop to separate Move vs Action\n                };\n                \n                // Reset for proper logic separation\n                best_score = -1e18;\n                move_char = '.';\n                nr = cr.r; nc = cr.c;\n\n                // 1. Evaluate Actions at Current Position (P, Q, .)\n                // Base score for staying\n                long long base_score = 0;\n                if(cr.holding != -1) {\n                    int t_row = cr.holding / N;\n                    base_score -= (abs(cr.r - t_row) + abs(cr.c - (N-1)));\n                    if(cr.holding == state.next_dispatch[t_row]) base_score += 5000;\n                } else {\n                    // Empty logic roughly\n                }\n\n                // Check P\n                if(cr.holding == -1 && state.grid[cr.r][cr.c] != -1) {\n                    int cid = state.grid[cr.r][cr.c];\n                    int t_row = cid / N;\n                    long long s = base_score;\n                    if(cid == state.next_dispatch[t_row]) s += 10000;\n                    else s += 2000;\n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = 'P';\n                    }\n                }\n                // Check Q\n                if(cr.holding != -1 && state.grid[cr.r][cr.c] == -1) {\n                    int t_row = cr.holding / N;\n                    long long s = base_score;\n                    if(cr.r == t_row && cr.c == N-1) {\n                        if(cr.holding == state.next_dispatch[t_row]) s += 20000;\n                        else s += 5000;\n                    } else if(cr.c == N-1) {\n                        s += 3000; // Dispatch wrong gate is okay\n                    } else {\n                        s -= 1000; // Buffer\n                    }\n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = 'Q';\n                    }\n                }\n                \n                // 2. Evaluate Moves (U, D, L, R)\n                for(int d=0; d<4; ++d) {\n                    int tr = cr.r + dr[d];\n                    int tc = cr.c + dc[d];\n                    if(!is_valid_move(i, tr, tc, planned_next)) continue;\n                    if(!is_valid_cell_for_carrying(i, tr, tc)) continue;\n                    \n                    long long s = 0;\n                    if(cr.holding != -1) {\n                        int t_row = cr.holding / N;\n                        int dist = abs(tr - t_row) + abs(tc - (N-1));\n                        s -= dist;\n                        if(cr.holding == state.next_dispatch[t_row]) s += 5000;\n                        if(tc == N-1 && tr != t_row) s -= 2000; // Strongly discourage entering dispatch lane early\n                    } else {\n                        // Empty: go to inputs\n                        int min_d = 1000;\n                        for(int r=0; r<N; ++r) {\n                            if(state.input_idx[r] < N && state.grid[r][0] != -1) {\n                                int d_val = abs(tr - r) + abs(tc - 0);\n                                if(state.grid[r][0] == state.next_dispatch[r]) d_val -= 50;\n                                if(d_val < min_d) min_d = d_val;\n                            }\n                        }\n                        s -= min_d;\n                    }\n                    \n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = dchar[d];\n                        nr = tr; nc = tc;\n                    }\n                }\n                \n                // Apply\n                moves[i] = move_char;\n                if(move_char == 'P' || move_char == 'Q' || move_char == '.') {\n                    planned_next[i] = {cr.r, cr.c};\n                } else {\n                    planned_next[i] = {nr, nc};\n                }\n            }\n\n            // Execute\n            for(int i=0; i<N; ++i) {\n                ans[i] += moves[i];\n                Crane &cr = state.cranes[i];\n                char m = moves[i];\n                if(m == 'P') {\n                    cr.holding = state.grid[cr.r][cr.c];\n                    state.grid[cr.r][cr.c] = -1;\n                } else if(m == 'Q') {\n                    state.grid[cr.r][cr.c] = cr.holding;\n                    cr.holding = -1;\n                } else if(m == 'U') cr.r--;\n                else if(m == 'D') cr.r++;\n                else if(m == 'L') cr.c--;\n                else if(m == 'R') cr.c++;\n            }\n\n            dispatch_containers();\n        }\n        \n        // Pad\n        size_t max_len = 0;\n        for(const auto& s : ans) max_len = max(max_len, s.size());\n        if(max_len == 0) max_len = 1;\n        for(int i=0; i<N; ++i) {\n            while(ans[i].size() < max_len) ans[i] += '.';\n        }\n    }\n\n    void print_ans() {\n        for(int i=0; i<N; ++i) {\n            cout << ans[i] << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.print_ans();\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <string>\n#include <cstdlib>\n\nusing namespace std;\n\n// Structure to represent grid coordinates\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Coord& o) const { return !(*this == o); }\n};\n\n// Manhattan distance between two coordinates\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint N;\nint h[25][25];\nvector<Coord> sources;\nvector<Coord> sinks;\n\n// Flow targets for each source cell: list of {sink_coord, amount}\nstruct FlowTarget {\n    Coord sink;\n    int amount;\n};\nvector<FlowTarget> source_flows[25][25];\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\n    // Read input and identify sources (h > 0) and sinks (h < 0)\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    // Working copy of heights to track remaining supply/demand\n    int cur_h[25][25];\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            cur_h[i][j] = h[i][j];\n    \n    // Indices of active sources and sinks\n    vector<int> src_idx(sources.size());\n    iota(src_idx.begin(), src_idx.end(), 0);\n    vector<int> snk_idx(sinks.size());\n    iota(snk_idx.begin(), snk_idx.end(), 0);\n\n    // Greedy Flow Calculation\n    // Repeatedly pick the pair (source, sink) with minimum distance and transfer soil.\n    // This approximates the Minimum Cost Flow / Earth Mover's Distance.\n    while (!src_idx.empty() && !snk_idx.empty()) {\n        int s_choice = -1;\n        int k_choice = -1;\n        int min_d = 1e9;\n\n        // Find the pair with minimum Manhattan distance\n        for (int s : src_idx) {\n            for (int k : snk_idx) {\n                int d = dist(sources[s], sinks[k]);\n                if (d < min_d) {\n                    min_d = d;\n                    s_choice = s;\n                    k_choice = k;\n                }\n            }\n        }\n        \n        if (s_choice == -1) break;\n\n        Coord u = sources[s_choice];\n        Coord v = sinks[k_choice];\n        // Transfer as much as possible\n        int amount = min(cur_h[u.r][u.c], -cur_h[v.r][v.c]);\n        \n        source_flows[u.r][u.c].push_back({v, amount});\n        \n        cur_h[u.r][u.c] -= amount;\n        cur_h[v.r][v.c] += amount;\n        \n        // Remove exhausted source or sink from active lists\n        if (cur_h[u.r][u.c] == 0) {\n            for(int i=0; i<src_idx.size(); ++i) {\n                if(src_idx[i] == s_choice) {\n                    src_idx[i] = src_idx.back();\n                    src_idx.pop_back();\n                    break;\n                }\n            }\n        }\n        if (cur_h[v.r][v.c] == 0) {\n            for(int i=0; i<snk_idx.size(); ++i) {\n                if(snk_idx[i] == k_choice) {\n                    snk_idx[i] = snk_idx.back();\n                    snk_idx.pop_back();\n                    break;\n                }\n            }\n        }\n    }\n\n    vector<string> ops;\n    Coord cur = {0, 0}; // Truck starts at (0,0)\n\n    // List of sources that have soil to transport\n    vector<Coord> active_sources;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!source_flows[i][j].empty()) {\n                active_sources.push_back({i, j});\n            }\n        }\n    }\n\n    // Order sources using Nearest Neighbor heuristic to minimize empty travel\n    vector<bool> visited_source(active_sources.size(), false);\n    int sources_remaining = active_sources.size();\n\n    while (sources_remaining > 0) {\n        int best_idx = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < active_sources.size(); ++i) {\n            if (!visited_source[i]) {\n                int d = dist(cur, active_sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n        }\n\n        if (best_idx == -1) break;\n\n        Coord u = active_sources[best_idx];\n        visited_source[best_idx] = true;\n        sources_remaining--;\n\n        // Move truck to source u\n        while (cur != u) {\n            if (cur.r < u.r) { cur.r++; ops.push_back(\"D\"); }\n            else if (cur.r > u.r) { cur.r--; ops.push_back(\"U\"); }\n            else if (cur.c < u.c) { cur.c++; ops.push_back(\"R\"); }\n            else if (cur.c > u.c) { cur.c--; ops.push_back(\"L\"); }\n        }\n\n        // Calculate total load to pick up at u\n        int total_load = 0;\n        for (auto& flow : source_flows[u.r][u.c]) {\n            total_load += flow.amount;\n        }\n\n        // Load soil\n        ops.push_back(\"+\" + to_string(total_load));\n\n        // Visit assigned sinks for this source\n        // Order sinks using Nearest Neighbor to minimize loaded travel\n        vector<FlowTarget> targets = source_flows[u.r][u.c];\n        vector<bool> visited_target(targets.size(), false);\n        int targets_remaining = targets.size();\n\n        while (targets_remaining > 0) {\n            int best_t = -1;\n            int min_td = 1e9;\n            for (int i = 0; i < targets.size(); ++i) {\n                if (!visited_target[i]) {\n                    int d = dist(cur, targets[i].sink);\n                    if (d < min_td) {\n                        min_td = d;\n                        best_t = i;\n                    }\n                }\n            }\n            \n            Coord v = targets[best_t].sink;\n            // Move truck to sink v\n            while (cur != v) {\n                if (cur.r < v.r) { cur.r++; ops.push_back(\"D\"); }\n                else if (cur.r > v.r) { cur.r--; ops.push_back(\"U\"); }\n                else if (cur.c < v.c) { cur.c++; ops.push_back(\"R\"); }\n                else if (cur.c > v.c) { cur.c--; ops.push_back(\"L\"); }\n            }\n\n            // Unload soil\n            int amt = targets[best_t].amount;\n            ops.push_back(\"-\" + to_string(amt));\n            \n            visited_target[best_t] = true;\n            targets_remaining--;\n        }\n    }\n\n    // Output the sequence of operations\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 <cmath>\n#include <random>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n    \n    int seed_count = 2 * N * (N - 1); // 60 seeds\n    int grid_size = N * N; // 36 squares\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    \n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n    \n    mt19937 rng(12345);\n    \n    // Track global max for each dimension (for scoring)\n    vector<int> global_max(M, 0);\n    for (int d = 0; d < M; d++) {\n        for (int i = 0; i < seed_count; i++) {\n            global_max[d] = max(global_max[d], X[i][d]);\n        }\n    }\n    \n    for (int turn = 0; turn < T; turn++) {\n        // Calculate statistics for each dimension\n        vector<int> dim_max(M, 0);\n        vector<int> dim_sum(M, 0);\n        vector<int> dim_count_above(M, 0);\n        \n        for (int d = 0; d < M; d++) {\n            for (int i = 0; i < seed_count; i++) {\n                dim_max[d] = max(dim_max[d], X[i][d]);\n                dim_sum[d] += X[i][d];\n                if (X[i][d] >= dim_max[d] * 0.8) {\n                    dim_count_above[d]++;\n                }\n            }\n        }\n        \n        // Calculate seed scores with multiple factors\n        vector<double> seed_score(seed_count, 0);\n        for (int i = 0; i < seed_count; i++) {\n            double score = 0;\n            \n            // Factor 1: Total value\n            int total = 0;\n            for (int d = 0; d < M; d++) {\n                total += X[i][d];\n                // Factor 2: Dimensional excellence with rarity bonus\n                if (dim_max[d] > 0) {\n                    double ratio = (double)X[i][d] / dim_max[d];\n                    // Bonus for being close to max, penalized if many seeds have similar values\n                    score += ratio * ratio * (1.0 / dim_count_above[d]);\n                }\n            }\n            score += total * 0.01;\n            \n            // Factor 3: Unique high values\n            for (int d = 0; d < M; d++) {\n                if (X[i][d] >= dim_max[d] * 0.9) {\n                    score += 5.0; // Significant bonus for near-max values\n                }\n            }\n            \n            seed_score[i] = score;\n        }\n        \n        // Turn-dependent strategy\n        double diversity_weight = 1.0 - (double)turn / T;\n        double elite_weight = (double)turn / T;\n        \n        // Select seeds with balance of diversity and elite performance\n        vector<pair<double, int>> scored_seeds;\n        for (int i = 0; i < seed_count; i++) {\n            scored_seeds.push_back({seed_score[i], i});\n        }\n        \n        // Greedy selection with diversity consideration\n        vector<int> selected;\n        vector<bool> selected_flag(seed_count, false);\n        vector<int> dim_coverage(M, 0); // How many selected seeds are good in each dimension\n        \n        // First pass: ensure dimensional coverage\n        for (int d = 0; d < M; d++) {\n            int best_seed = -1;\n            double best_score = -1;\n            for (int i = 0; i < seed_count; i++) {\n                if (!selected_flag[i] && X[i][d] >= dim_max[d] * 0.85) {\n                    if (seed_score[i] > best_score) {\n                        best_score = seed_score[i];\n                        best_seed = i;\n                    }\n                }\n            }\n            if (best_seed >= 0 && selected.size() < grid_size) {\n                selected.push_back(best_seed);\n                selected_flag[best_seed] = true;\n                for (int dd = 0; dd < M; dd++) {\n                    if (X[best_seed][dd] >= dim_max[dd] * 0.85) {\n                        dim_coverage[dd]++;\n                    }\n                }\n            }\n        }\n        \n        // Second pass: fill with highest scored seeds\n        sort(scored_seeds.begin(), scored_seeds.end(), greater<pair<double,int>>());\n        for (auto& p : scored_seeds) {\n            if (selected.size() >= grid_size) break;\n            if (!selected_flag[p.second]) {\n                selected.push_back(p.second);\n                selected_flag[p.second] = true;\n            }\n        }\n        \n        // Calculate compatibility between seeds (how complementary they are)\n        vector<vector<double>> compatibility(seed_count, vector<double>(seed_count, 0));\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = i + 1; j < seed_count; j++) {\n                double comp = 0;\n                for (int d = 0; d < M; d++) {\n                    // Reward when one is high and other is also decent\n                    double v1 = (double)X[i][d] / max(1, dim_max[d]);\n                    double v2 = (double)X[j][d] / max(1, dim_max[d]);\n                    // Want both to be high for this dimension\n                    comp += min(v1, v2);\n                }\n                comp /= M;\n                // Also consider total values\n                int sum1 = 0, sum2 = 0;\n                for (int d = 0; d < M; d++) {\n                    sum1 += X[i][d];\n                    sum2 += X[j][d];\n                }\n                comp += (sum1 + sum2) * 0.001;\n                compatibility[i][j] = compatibility[j][i] = comp;\n            }\n        }\n        \n        // Place seeds in grid using greedy optimization\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        vector<bool> placed(selected.size(), false);\n        \n        // Find best pair to start with (center of grid)\n        int best_i = 0, best_j = 1;\n        double best_comp = -1;\n        for (int i = 0; i < selected.size(); i++) {\n            for (int j = i + 1; j < selected.size(); j++) {\n                if (compatibility[selected[i]][selected[j]] > best_comp) {\n                    best_comp = compatibility[selected[i]][selected[j]];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        // Place in center\n        A[N/2][N/2] = selected[best_i];\n        placed[best_i] = true;\n        \n        if (N > 1 && !placed[best_j]) {\n            A[N/2][N/2 + 1] = selected[best_j];\n            placed[best_j] = true;\n        }\n        \n        // Greedily place remaining seeds adjacent to placed ones\n        for (int count = 2; count < grid_size; count++) {\n            int best_seed_idx = -1;\n            int best_pos_i = -1, best_pos_j = -1;\n            double best_adj_score = -1;\n            \n            // Find best unplaced seed and position\n            for (int si = 0; si < selected.size(); si++) {\n                if (placed[si]) continue;\n                int seed_id = selected[si];\n                \n                // Try each empty position\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] != -1) continue;\n                        \n                        // Check if adjacent to any placed seed\n                        bool has_neighbor = false;\n                        double adj_score = 0;\n                        int neighbor_count = 0;\n                        \n                        const int di[] = {-1, 1, 0, 0};\n                        const int dj[] = {0, 0, -1, 1};\n                        \n                        for (int dir = 0; dir < 4; dir++) {\n                            int ni = i + di[dir];\n                            int nj = j + dj[dir];\n                            if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1) {\n                                has_neighbor = true;\n                                adj_score += compatibility[seed_id][A[ni][nj]];\n                                neighbor_count++;\n                            }\n                        }\n                        \n                        if (has_neighbor) {\n                            adj_score /= neighbor_count;\n                            // Prefer positions with more neighbors (center positions)\n                            int neighbors_total = 0;\n                            for (int dir = 0; dir < 4; dir++) {\n                                int ni = i + di[dir];\n                                int nj = j + dj[dir];\n                                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                                    neighbors_total++;\n                                }\n                            }\n                            adj_score += neighbors_total * 0.1;\n                            \n                            if (adj_score > best_adj_score) {\n                                best_adj_score = adj_score;\n                                best_seed_idx = si;\n                                best_pos_i = i;\n                                best_pos_j = j;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (best_seed_idx >= 0) {\n                A[best_pos_i][best_pos_j] = selected[best_seed_idx];\n                placed[best_seed_idx] = true;\n            } else {\n                // Fill any remaining empty spots\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] == -1) {\n                            for (int si = 0; si < selected.size(); si++) {\n                                if (!placed[si]) {\n                                    A[i][j] = selected[si];\n                                    placed[si] = true;\n                                    goto filled;\n                                }\n                            }\n                        }\n                    }\n                }\n                filled:;\n            }\n        }\n        \n        // Output the grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds and update global max\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                global_max[j] = max(global_max[j], X[i][j]);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n    bool operator<(const Point& o) const {\n        if (x != o.x) return x < o.x;\n        return y < o.y;\n    }\n};\n\nint dist(Point a, Point b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> S(N), T(N);\n    for (int i = 0; i < N; i++) cin >> S[i];\n    for (int i = 0; i < N; i++) cin >> T[i];\n    \n    vector<Point> sources, targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (S[i][j] == '1') sources.push_back({i, j});\n            if (T[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n    \n    // Design arm: star topology with varying edge lengths\n    int V_prime = min(V, (int)sources.size() + 1);\n    if (V_prime < 2) V_prime = 2;\n    int num_fingertips = V_prime - 1;\n    \n    cout << V_prime << \"\\n\";\n    vector<int> edge_len(V_prime, 0);\n    for (int i = 1; i < V_prime; i++) {\n        edge_len[i] = (i - 1) % (N - 1) + 1;\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Find good initial root position (center of sources)\n    int sum_x = 0, sum_y = 0;\n    for (auto& p : sources) {\n        sum_x += p.x;\n        sum_y += p.y;\n    }\n    int root_x = sum_x / M;\n    int root_y = sum_y / M;\n    root_x = max(0, min(N - 1, root_x));\n    root_y = max(0, min(N - 1, root_y));\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Grid state tracking\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = (S[i][j] == '1' ? 1 : 0);\n        }\n    }\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            is_target[i][j] = (T[i][j] == '1' ? 1 : 0);\n        }\n    }\n    \n    // Fingertip state\n    vector<int> fp_dir(num_fingertips, 0);  // 0:R, 1:D, 2:L, 3:U\n    vector<bool> fp_holding(num_fingertips, false);\n    \n    auto get_fp_pos = [&](int fp_idx) -> Point {\n        int d = fp_dir[fp_idx];\n        return {root_x + DX[d] * edge_len[fp_idx + 1], \n                root_y + DY[d] * edge_len[fp_idx + 1]};\n    };\n    \n    auto in_bounds = [&](Point p) -> bool {\n        return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n    };\n    \n    auto can_pick = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 1;\n    };\n    \n    auto can_place = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 0;\n    };\n    \n    vector<string> commands;\n    int turns = 0;\n    int delivered = 0;\n    \n    // Create source-target matching (greedy by distance)\n    vector<bool> src_used(sources.size(), false);\n    vector<bool> tgt_used(targets.size(), false);\n    vector<pair<int, int>> pairs;\n    \n    for (int iter = 0; iter < M; iter++) {\n        int best_si = -1, best_ti = -1, best_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); i++) {\n            if (src_used[i]) continue;\n            for (int j = 0; j < (int)targets.size(); j++) {\n                if (tgt_used[j]) continue;\n                int d = dist(sources[i], targets[j]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_si = i;\n                    best_ti = j;\n                }\n            }\n        }\n        if (best_si >= 0) {\n            src_used[best_si] = true;\n            tgt_used[best_ti] = true;\n            pairs.push_back({best_si, best_ti});\n        }\n    }\n    \n    // Process pairs using multiple fingertips in parallel\n    int pair_idx = 0;\n    vector<int> fp_task(num_fingertips, -1);  // Which pair each fingertip is handling\n    \n    while ((pair_idx < (int)pairs.size() || \n           count(fp_task.begin(), fp_task.end(), -1) < num_fingertips) && \n           turns < 99000) {\n        \n        string cmd(V_prime * 2, '.');\n        bool action_taken = false;\n        \n        // Assign new tasks to idle fingertips\n        for (int fp = 0; fp < num_fingertips && pair_idx < (int)pairs.size(); fp++) {\n            if (fp_task[fp] == -1 && !fp_holding[fp]) {\n                fp_task[fp] = pair_idx++;\n            }\n        }\n        \n        // Process each fingertip\n        for (int fp = 0; fp < num_fingertips; fp++) {\n            if (fp_task[fp] == -1) continue;\n            \n            int si = pairs[fp_task[fp]].first;\n            int ti = pairs[fp_task[fp]].second;\n            Point src = sources[si];\n            Point tgt = targets[ti];\n            \n            if (!fp_holding[fp]) {\n                // Need to pick up from source\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == src && can_pick(src)) {\n                    // Pick up\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = true;\n                    grid[src.x][src.y] = 0;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach source\n                    int target_rx = src.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = src.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == src.x && ty == src.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            } else {\n                // Need to deliver to target\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == tgt && can_place(tgt) && is_target[tgt.x][tgt.y]) {\n                    // Place\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = false;\n                    grid[tgt.x][tgt.y] = 1;\n                    fp_task[fp] = -1;\n                    delivered++;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach target\n                    int target_rx = tgt.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = tgt.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == tgt.x && ty == tgt.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            }\n        }\n        \n        // If no fingertips active, try to activate more\n        if (!action_taken) {\n            bool found = false;\n            for (int fp = 0; fp < num_fingertips && !found; fp++) {\n                if (fp_task[fp] == -1 && pair_idx < (int)pairs.size()) {\n                    fp_task[fp] = pair_idx++;\n                    found = true;\n                }\n            }\n            if (!found) break;\n            continue;\n        }\n        \n        commands.push_back(cmd);\n        turns++;\n    }\n    \n    // Output all commands\n    for (const string& c : commands) {\n        cout << c << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int CELL_SIZE = 500;\nconst int GW = MAX_COORD / CELL_SIZE + 1; // 201\nconst int GH = MAX_COORD / CELL_SIZE + 1; // 201\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct GridCell {\n    int m; // mackerels\n    int s; // sardines\n    int score() const { return m - s; }\n};\n\nGridCell grid[GH][GW];\nbool selected[GH][GW];\n\n// Directions: Up, Right, Down, Left (clockwise)\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {-1, 0, 1, 0};\n\n// Priority Queue Element for Growth\nstruct PQElement {\n    int r, c;\n    int score;\n    bool operator<(const PQElement& other) const {\n        return score < other.score; // Max heap\n    }\n};\n\n// Function to check if a point is inside the polygon\n// Ray casting algorithm for orthogonal polygons\nbool isInside(const vector<Point>& poly, int px, int py) {\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        \n        // Check if point is on the edge\n        if (xi == xj && px == xi && py >= min(yi, yj) && py <= max(yi, yj)) return true;\n        if (yi == yj && py == yi && px >= min(xi, xj) && px <= max(xi, xj)) return true;\n\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score\nlong long calculateScore(const vector<Point>& poly, const vector<Point>& mackerels, const vector<Point>& sardines) {\n    long long a = 0;\n    long long b = 0;\n    for (const auto& p : mackerels) {\n        if (isInside(poly, p.x, p.y)) a++;\n    }\n    for (const auto& p : sardines) {\n        if (isInside(poly, p.x, p.y)) b++;\n    }\n    return a - b + 1;\n}\n\n// Extract polygon from selected grid cells by tracing the boundary\nvector<Point> extractPolygon() {\n    // Find a starting point on the boundary\n    int start_r = -1, start_c = -1;\n    for (int r = 0; r < GH && start_r == -1; ++r) {\n        for (int c = 0; c < GW && start_r == -1; ++c) {\n            if (selected[r][c]) {\n                // Check if this cell is on the boundary\n                bool on_boundary = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + DY[d];\n                    int nc = c + DX[d];\n                    if (nr < 0 || nr >= GH || nc < 0 || nc >= GW || !selected[nr][nc]) {\n                        on_boundary = true;\n                        break;\n                    }\n                }\n                if (on_boundary) {\n                    start_r = r;\n                    start_c = c;\n                }\n            }\n        }\n    }\n    \n    if (start_r == -1) return {};\n    \n    // Trace the boundary using wall-following algorithm\n    vector<Point> poly;\n    \n    // Start from the top-left corner of the starting cell\n    int x = start_c * CELL_SIZE;\n    int y = start_r * CELL_SIZE;\n    \n    // Current direction: 0=Up, 1=Right, 2=Down, 3=Left\n    // We'll trace clockwise around the selected region\n    int dir = 1; // Start moving right\n    \n    int start_x = x, start_y = y;\n    int prev_x = -1, prev_y = -1;\n    \n    // Maximum iterations to prevent infinite loop\n    int max_iter = 4 * GW * GH;\n    int iter = 0;\n    \n    while (iter < max_iter) {\n        // Add current vertex if it's different from previous\n        if (poly.empty() || !(poly.back().x == x && poly.back().y == y)) {\n            poly.push_back({x, y});\n        }\n        \n        // Check if we've returned to start\n        if (!poly.empty() && poly.size() > 3 && x == start_x && y == start_y) {\n            break;\n        }\n        \n        // Try to turn left (counter-clockwise relative to current direction)\n        // For clockwise tracing, we want to keep the selected cells on our right\n        int new_dir = (dir + 3) % 4; // Turn left\n        \n        // Calculate next position based on direction\n        int nx = x + DX[new_dir] * CELL_SIZE;\n        int ny = y + DY[new_dir] * CELL_SIZE;\n        \n        // Check if we can move in this direction (keep selected cells on right)\n        // For direction dir, the cell to our right is:\n        // dir=0 (Up): cell to right is (r, c+1)\n        // dir=1 (Right): cell to right is (r+1, c)\n        // dir=2 (Down): cell to right is (r, c-1)\n        // dir=3 (Left): cell to right is (r-1, c)\n        \n        bool can_turn = false;\n        for (int try_dir = 0; try_dir < 4; ++try_dir) {\n            int test_dir = (dir + 3 + try_dir) % 4; // Try turning left, then straight, then right, then back\n            \n            int tx = x + DX[test_dir] * CELL_SIZE;\n            int ty = y + DY[test_dir] * CELL_SIZE;\n            \n            // Determine which cell would be on our right if we move in test_dir\n            int right_r, right_c;\n            // Current vertex (x, y) corresponds to grid corner\n            // Cell to the right depends on direction\n            if (test_dir == 0) { // Moving up, right is east\n                right_c = x / CELL_SIZE;\n                right_r = (y - 1) / CELL_SIZE;\n            } else if (test_dir == 1) { // Moving right, right is south\n                right_c = (x + CELL_SIZE - 1) / CELL_SIZE;\n                right_r = y / CELL_SIZE;\n            } else if (test_dir == 2) { // Moving down, right is west\n                right_c = (x - 1) / CELL_SIZE;\n                right_r = y / CELL_SIZE;\n            } else { // Moving left, right is north\n                right_c = x / CELL_SIZE;\n                right_r = (y + CELL_SIZE - 1) / CELL_SIZE;\n            }\n            \n            bool cell_on_right = (right_r >= 0 && right_r < GH && right_c >= 0 && right_c < GW && selected[right_r][right_c]);\n            \n            if (cell_on_right) {\n                // Can move in this direction\n                x = tx;\n                y = ty;\n                dir = test_dir;\n                can_turn = true;\n                break;\n            }\n        }\n        \n        prev_x = x;\n        prev_y = y;\n        iter++;\n        \n        if (!can_turn) {\n            // Should not happen for valid selected region\n            break;\n        }\n    }\n    \n    // Remove duplicate last point if it equals first\n    if (poly.size() > 1 && poly.front().x == poly.back().x && poly.front().y == poly.back().y) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Simpler polygon extraction: collect all boundary edges and trace\nvector<Point> extractPolygonSimple() {\n    vector<Point> poly;\n    \n    // Find all boundary vertices\n    set<pair<int, int>> vertices;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                // Check 4 corners of this cell\n                int corners[4][2] = {\n                    {c * CELL_SIZE, r * CELL_SIZE},\n                    {(c + 1) * CELL_SIZE, r * CELL_SIZE},\n                    {(c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE},\n                    {c * CELL_SIZE, (r + 1) * CELL_SIZE}\n                };\n                \n                for (int i = 0; i < 4; ++i) {\n                    int vx = corners[i][0];\n                    int vy = corners[i][1];\n                    \n                    // Check if this vertex is on the boundary\n                    // A vertex is on boundary if not all 4 cells around it are selected\n                    bool on_boundary = false;\n                    \n                    // Check 4 cells around this vertex\n                    // Cell (r-1, c-1), (r-1, c), (r, c-1), (r, c)\n                    int cells_around[4][2] = {\n                        {r - 1, c - 1},\n                        {r - 1, c},\n                        {r, c - 1},\n                        {r, c}\n                    };\n                    \n                    int selected_count = 0;\n                    for (int j = 0; j < 4; ++j) {\n                        int cr = cells_around[j][0];\n                        int cc = cells_around[j][1];\n                        if (cr >= 0 && cr < GH && cc >= 0 && cc < GW && selected[cr][cc]) {\n                            selected_count++;\n                        }\n                    }\n                    \n                    if (selected_count > 0 && selected_count < 4) {\n                        on_boundary = true;\n                    }\n                    \n                    if (on_boundary) {\n                        vertices.insert({vx, vy});\n                    }\n                }\n            }\n        }\n    }\n    \n    if (vertices.empty()) return {};\n    \n    // Convert to vector and sort to find a starting point\n    vector<Point> verts;\n    for (const auto& v : vertices) {\n        verts.push_back({v.first, v.second});\n    }\n    \n    // Find the vertex with minimum (y, x) as starting point\n    sort(verts.begin(), verts.end(), [](const Point& a, const Point& b) {\n        if (a.y != b.y) return a.y < b.y;\n        return a.x < b.x;\n    });\n    \n    // Now trace the perimeter\n    // Start from the leftmost-topmost vertex\n    Point start = verts[0];\n    poly.push_back(start);\n    \n    Point current = start;\n    Point prev = {-1, -1};\n    \n    // Direction to move: we'll go clockwise\n    // From top-left, we should go right first\n    int dir = 1; // Right\n    \n    int max_iter = verts.size() * 4 + 100;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        // Try to find next vertex\n        Point next = {-1, -1};\n        int next_dir = -1;\n        \n        // Try directions in order: right, down, left, up (clockwise)\n        // But prefer to turn left relative to current direction\n        for (int d = 0; d < 4; ++d) {\n            int test_dir = (dir + 3 + d) % 4; // Turn left first\n            \n            int nx = current.x + DX[test_dir];\n            int ny = current.y + DY[test_dir];\n            \n            // Check if there's a vertex in this direction\n            // We need to find the farthest vertex in this direction that's connected\n            bool found = false;\n            int fx = current.x, fy = current.y;\n            \n            // Walk in this direction until we hit another vertex or boundary\n            for (int step = 1; step <= MAX_COORD; ++step) {\n                int cx = current.x + DX[test_dir] * step;\n                int cy = current.y + DY[test_dir] * step;\n                \n                // Check bounds\n                if (cx < 0 || cx > MAX_COORD || cy < 0 || cy > MAX_COORD) break;\n                \n                // Check if this is a vertex\n                if (vertices.count({cx, cy})) {\n                    fx = cx;\n                    fy = cy;\n                    found = true;\n                }\n            }\n            \n            if (found) {\n                next = {fx, fy};\n                next_dir = test_dir;\n                break;\n            }\n        }\n        \n        if (next.x == -1) break;\n        \n        // Check if we've returned to start\n        if (next.x == start.x && next.y == start.y && poly.size() > 3) {\n            break;\n        }\n        \n        // Check if this creates a valid orthogonal move\n        if (next.x != current.x && next.y != current.y) {\n            // Diagonal move - this shouldn't happen\n            break;\n        }\n        \n        poly.push_back(next);\n        prev = current;\n        current = next;\n        dir = next_dir;\n    }\n    \n    // Remove duplicate last point\n    if (poly.size() > 1 && poly.front().x == poly.back().x && poly.front().y == poly.back().y) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Most reliable: build polygon from cell boundaries directly\nvector<Point> buildPolygonFromCells() {\n    // Collect all boundary edges\n    struct 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    vector<Edge> edges;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                int x1 = c * CELL_SIZE;\n                int y1 = r * CELL_SIZE;\n                int x2 = (c + 1) * CELL_SIZE;\n                int y2 = (r + 1) * CELL_SIZE;\n                \n                // Top edge\n                if (r == 0 || !selected[r-1][c]) {\n                    edges.push_back({x1, y1, x2, y1});\n                }\n                // Bottom edge\n                if (r == GH - 1 || !selected[r+1][c]) {\n                    edges.push_back({x1, y2, x2, y2});\n                }\n                // Left edge\n                if (c == 0 || !selected[r][c-1]) {\n                    edges.push_back({x1, y1, x1, y2});\n                }\n                // Right edge\n                if (c == GW - 1 || !selected[r][c+1]) {\n                    edges.push_back({x2, y1, x2, y2});\n                }\n            }\n        }\n    }\n    \n    if (edges.empty()) return {};\n    \n    // Sort edges to help with linking\n    sort(edges.begin(), edges.end());\n    \n    // Build adjacency map: (x, y) -> list of connected points\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    for (const auto& e : edges) {\n        adj[{e.x1, e.y1}].push_back({e.x2, e.y2});\n        adj[{e.x2, e.y2}].push_back({e.x1, e.y1});\n    }\n    \n    // Start from the leftmost-bottommost vertex\n    Point start = {edges[0].x1, edges[0].y1};\n    for (const auto& e : edges) {\n        Point p1 = {e.x1, e.y1};\n        Point p2 = {e.x2, e.y2};\n        if (p1.y < start.y || (p1.y == start.y && p1.x < start.x)) {\n            start = p1;\n        }\n        if (p2.y < start.y || (p2.y == start.y && p2.x < start.x)) {\n            start = p2;\n        }\n    }\n    \n    // Trace the polygon\n    vector<Point> poly;\n    Point current = start;\n    Point prev = {-1000000, -1000000}; // Invalid point\n    \n    for (int iter = 0; iter < (int)edges.size() * 2 + 10; ++iter) {\n        poly.push_back(current);\n        \n        // Find neighbors\n        auto it = adj.find({current.x, current.y});\n        if (it == adj.end()) break;\n        \n        // Choose next vertex (not the one we came from)\n        Point next = {-1, -1};\n        for (const auto& neighbor : it->second) {\n            Point np = {neighbor.first, neighbor.second};\n            if (!(np.x == prev.x && np.y == prev.y)) {\n                // For orthogonal polygon, prefer to turn consistently\n                if (next.x == -1) {\n                    next = np;\n                } else {\n                    // Choose based on direction (clockwise)\n                    // Calculate cross product to determine turn direction\n                    long long dx1 = current.x - prev.x;\n                    long long dy1 = current.y - prev.y;\n                    long long dx2 = np.x - current.x;\n                    long long dy2 = np.y - current.y;\n                    long long cross = dx1 * dy2 - dy1 * dx2;\n                    \n                    long long cdx1 = current.x - prev.x;\n                    long long cdy1 = current.y - prev.y;\n                    long long cdx2 = next.x - current.x;\n                    long long cdy2 = next.y - current.y;\n                    long long ccross = cdx1 * cdy2 - cdy1 * cdx2;\n                    \n                    // For clockwise, we want negative cross product (right turn)\n                    if (cross < ccross) {\n                        next = np;\n                    }\n                }\n            }\n        }\n        \n        if (next.x == -1) break;\n        \n        // Check if we've returned to start\n        if (next.x == start.x && next.y == start.y && poly.size() > 3) {\n            break;\n        }\n        \n        prev = current;\n        current = next;\n    }\n    \n    // Ensure polygon is closed (don't add start again)\n    // Remove duplicate if last equals first\n    if (poly.size() > 1 && poly.front().x == poly.back().x && poly.front().y == poly.back().y) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Simplify polygon by removing collinear vertices\nvector<Point> simplifyPolygon(const vector<Point>& poly) {\n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> result;\n    result.push_back(poly[0]);\n    \n    for (size_t i = 1; i < poly.size() - 1; ++i) {\n        Point p1 = result.back();\n        Point p2 = poly[i];\n        Point p3 = poly[i + 1];\n        \n        // Check if p1, p2, p3 are collinear (for orthogonal, same x or same y)\n        bool collinear = false;\n        if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n        if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n        \n        if (!collinear) {\n            result.push_back(p2);\n        }\n    }\n    \n    result.push_back(poly.back());\n    \n    // Check wrap-around collinearity\n    if (result.size() > 3) {\n        // Check last, first, second\n        Point p1 = result[result.size() - 2];\n        Point p2 = result.back();\n        Point p3 = result[0];\n        bool collinear = false;\n        if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n        if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n        if (collinear) {\n            // Remove the middle point (result.back())\n            result.pop_back();\n            result[0] = p3; // Actually we need to remove result[0] and shift\n            // Simpler: just leave it, vertex limit is generous\n        }\n    }\n    \n    // Remove consecutive duplicates\n    vector<Point> final_result;\n    for (const auto& p : result) {\n        if (final_result.empty() || !(final_result.back().x == p.x && final_result.back().y == p.y)) {\n            final_result.push_back(p);\n        }\n    }\n    \n    return final_result;\n}\n\n// Validate polygon\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4) {\n        cerr << \"Error: Polygon has less than 4 vertices\" << endl;\n        return false;\n    }\n    \n    if (poly.size() > MAX_VERTICES) {\n        cerr << \"Error: Polygon has more than \" << MAX_VERTICES << \" vertices\" << endl;\n        return false;\n    }\n    \n    // Check all edges are orthogonal\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        \n        if (p1.x != p2.x && p1.y != p2.y) {\n            cerr << \"Error: Edge \" << i << \" is not orthogonal: (\" << p1.x << \", \" << p1.y \n                 << \") - (\" << p2.x << \", \" << p2.y << \")\" << endl;\n            return false;\n        }\n        \n        if (p1.x == p2.x && p1.y == p2.y) {\n            cerr << \"Error: Edge \" << i << \" has zero length\" << endl;\n            return false;\n        }\n    }\n    \n    // Check perimeter\n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    \n    if (perim > MAX_PERIMETER) {\n        cerr << \"Error: Perimeter \" << perim << \" exceeds limit \" << MAX_PERIMETER << endl;\n        return false;\n    }\n    \n    // Check coordinates in bounds\n    for (const auto& p : poly) {\n        if (p.x < 0 || p.x > MAX_COORD || p.y < 0 || p.y > MAX_COORD) {\n            cerr << \"Error: Vertex (\" << p.x << \", \" << p.y << \") out of bounds\" << endl;\n            return false;\n        }\n    }\n    \n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<Point> mackerels(N);\n    vector<Point> sardines(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    // Initialize grid\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            grid[r][c] = {0, 0};\n            selected[r][c] = false;\n        }\n    }\n\n    // Populate grid\n    for (const auto& p : mackerels) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].m++;\n        }\n    }\n    for (const auto& p : sardines) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].s++;\n        }\n    }\n\n    // Find best starting cell\n    int best_r = 0, best_c = 0;\n    int best_score = -1e9;\n    \n    bool found_positive = false;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            int sc = grid[r][c].score();\n            if (sc > best_score) {\n                best_score = sc;\n                best_r = r;\n                best_c = c;\n            }\n            if (sc > 0) found_positive = true;\n        }\n    }\n\n    if (!found_positive) {\n        best_score = -1e9;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                if (grid[r][c].m > 0) {\n                    int sc = grid[r][c].score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n        }\n    }\n\n    // Grow region\n    priority_queue<PQElement> pq;\n    selected[best_r][best_c] = true;\n    \n    vector<vector<bool>> in_pq(GH, vector<bool>(GW, false));\n    for (int i = 0; i < 4; ++i) {\n        int nr = best_r + DY[i];\n        int nc = best_c + DX[i];\n        if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc]) {\n            in_pq[nr][nc] = true;\n            pq.push({nr, nc, grid[nr][nc].score()});\n        }\n    }\n\n    long long current_perimeter = 4LL * CELL_SIZE;\n\n    while (!pq.empty()) {\n        PQElement top = pq.top();\n        pq.pop();\n\n        int r = top.r;\n        int c = top.c;\n\n        if (selected[r][c]) continue;\n\n        int shared = 0;\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                shared++;\n            }\n        }\n        long long new_perimeter = current_perimeter + 4LL * CELL_SIZE - 2LL * shared * CELL_SIZE;\n\n        if (new_perimeter > MAX_PERIMETER - 1000) {\n            continue;\n        }\n\n        selected[r][c] = true;\n        current_perimeter = new_perimeter;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc] && !in_pq[nr][nc]) {\n                in_pq[nr][nc] = true;\n                pq.push({nr, nc, grid[nr][nc].score()});\n            }\n        }\n    }\n\n    // Extract polygon using the most reliable method\n    vector<Point> poly = buildPolygonFromCells();\n    \n    // Simplify\n    poly = simplifyPolygon(poly);\n    \n    // Validate\n    if (!validatePolygon(poly)) {\n        // Fallback to simple rectangle\n        poly = {\n            {best_c * CELL_SIZE, best_r * CELL_SIZE},\n            {(best_c + 1) * CELL_SIZE, best_r * CELL_SIZE},\n            {(best_c + 1) * CELL_SIZE, (best_r + 1) * CELL_SIZE},\n            {best_c * CELL_SIZE, (best_r + 1) * CELL_SIZE}\n        };\n    }\n    \n    // Final validation\n    if (!validatePolygon(poly)) {\n        // Ultimate fallback\n        poly = {\n            {0, 0},\n            {CELL_SIZE, 0},\n            {CELL_SIZE, CELL_SIZE},\n            {0, CELL_SIZE}\n        };\n    }\n\n    // Output\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>\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n};\n\nint N;\nvector<Rectangle> rects;\nvector<Placement> placements;\nvector<pair<int, int>> pos;\nvector<pair<int, int>> dim;\n\nvoid clear_state() {\n    placements.clear();\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n}\n\nvoid add_placement(int rect_id, int rotation, char direction, int base) {\n    placements.push_back({rect_id, rotation, direction, base});\n}\n\npair<int, int> simulate_fast() {\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n    int max_x = 0, max_y = 0;\n    \n    for (size_t idx = 0; idx < placements.size(); idx++) {\n        const auto& p = placements[idx];\n        int w = rects[p.rect_id].w_obs;\n        int h = rects[p.rect_id].h_obs;\n        \n        if (p.rotation == 1) swap(w, h);\n        dim[p.rect_id] = {w, h};\n        \n        int x = 0, y = 0;\n        \n        if (p.direction == 'U') {\n            if (p.base == -1) {\n                x = 0;\n            } else {\n                x = pos[p.base].first + dim[p.base].first;\n            }\n            // Find the lowest y that doesn't overlap\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                // Check horizontal overlap\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else { // 'L'\n            if (p.base == -1) {\n                y = 0;\n            } else {\n                y = pos[p.base].second + dim[p.base].second;\n            }\n            // Find the leftmost x that doesn't overlap\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                // Check vertical overlap\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        pos[p.rect_id] = {x, y};\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto get_elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    rects.resize(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    vector<Placement> best_placements;\n    long long best_score = LLONG_MAX;\n    \n    mt19937 rng(42);\n    \n    // Time budget: leave 0.2 sec for safety\n    const double TIME_LIMIT = 2.8;\n    \n    for (int turn = 0; turn < T; turn++) {\n        // Check time limit\n        if (get_elapsed() > TIME_LIMIT) {\n            break;\n        }\n        \n        clear_state();\n        \n        // Calculate time remaining for this turn\n        double time_remaining = TIME_LIMIT - get_elapsed();\n        double time_per_turn = time_remaining / (T - turn);\n        \n        // Greedy construction with limited search\n        for (int i = 0; i < N; i++) {\n            int best_rot = 0;\n            char best_dir = 'U';\n            int best_base = -1;\n            long long best_local = LLONG_MAX;\n            \n            // Limit base candidates based on time\n            int max_bases = min(i, 5);\n            vector<int> bases;\n            bases.push_back(-1);\n            for (int j = 0; j < max_bases; j++) {\n                bases.push_back(j);\n            }\n            \n            // Try combinations\n            for (int rot = 0; rot < 2; rot++) {\n                for (char dir : {'U', 'L'}) {\n                    for (int base : bases) {\n                        add_placement(i, rot, dir, base);\n                        auto dims = simulate_fast();\n                        long long score = (long long)dims.first + dims.second;\n                        \n                        if (score < best_local) {\n                            best_local = score;\n                            best_rot = rot;\n                            best_dir = dir;\n                            best_base = base;\n                        }\n                        \n                        placements.pop_back();\n                    }\n                }\n            }\n            \n            add_placement(i, best_rot, best_dir, best_base);\n        }\n        \n        // Light local search (only if time permits)\n        if (time_per_turn > 0.01) {\n            int search_iters = min(3, (int)(time_per_turn * 100));\n            \n            for (int iter = 0; iter < search_iters; iter++) {\n                bool improved = false;\n                auto current_dims = simulate_fast();\n                long long current_score = (long long)current_dims.first + current_dims.second;\n                \n                // Try modifying a few random rectangles\n                int num_to_try = min(N, 10);\n                vector<int> indices(N);\n                iota(indices.begin(), indices.end(), 0);\n                shuffle(indices.begin(), indices.end(), rng);\n                \n                for (int k = 0; k < num_to_try && !improved; k++) {\n                    int i = indices[k];\n                    int orig_rot = placements[i].rotation;\n                    char orig_dir = placements[i].direction;\n                    int orig_base = placements[i].base;\n                    \n                    // Try alternative rotation\n                    for (int rot = 0; rot < 2; rot++) {\n                        if (rot == orig_rot) continue;\n                        placements[i].rotation = rot;\n                        auto dims = simulate_fast();\n                        long long score = (long long)dims.first + dims.second;\n                        \n                        if (score < current_score) {\n                            current_score = score;\n                            orig_rot = rot;\n                            improved = true;\n                        }\n                    }\n                    placements[i].rotation = orig_rot;\n                    \n                    // Try alternative direction\n                    for (char dir : {'U', 'L'}) {\n                        if (dir == orig_dir) continue;\n                        placements[i].direction = dir;\n                        auto dims = simulate_fast();\n                        long long score = (long long)dims.first + dims.second;\n                        \n                        if (score < current_score) {\n                            current_score = score;\n                            orig_dir = dir;\n                            improved = true;\n                        }\n                    }\n                    placements[i].direction = orig_dir;\n                }\n                \n                if (!improved) break;\n            }\n        }\n        \n        auto final_dims = simulate_fast();\n        long long estimated_score = (long long)final_dims.first + final_dims.second;\n        \n        // Output placements\n        cout << \"# Turn \" << turn << \" est: \" << final_dims.first << \"+\" << final_dims.second << \"=\" << estimated_score << \"\\n\";\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read feedback\n        int W_meas, H_meas;\n        cin >> W_meas >> H_meas;\n        long long measured_score = (long long)W_meas + H_meas;\n        \n        // Update best\n        if (measured_score < best_score) {\n            best_score = measured_score;\n            best_placements = placements;\n            cout << \"# Best: \" << measured_score << \" at turn \" << turn << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\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\n    // Skip coordinates as they are not needed for the graph structure logic\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // State: is_root[v] indicates if vertex v is a root of a tree\n    // We start with all vertices as roots, which is a valid state (height 0 for all)\n    vector<bool> is_root(N, true); \n    \n    // Buffer for distance calculation\n    vector<int> dist(N);\n\n    // Function to calculate score and check validity (max height <= H)\n    // Returns -1 if invalid\n    auto get_score_and_validity = [&](const vector<bool>& roots, vector<int>& d) -> long long {\n        fill(d.begin(), d.end(), -1);\n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (roots[i]) {\n                d[i] = 0;\n                q.push(i);\n            }\n        }\n\n        if (q.empty()) return -1; // Must have at least one root\n\n        int max_d = 0;\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (d[u] > max_d) max_d = d[u];\n            if (max_d > H) return -1; // Exceeds height limit\n\n            for (int v : adj[u]) {\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        \n        long long score = 0;\n        for (int i = 0; i < N; ++i) {\n            score += (long long)(d[i] + 1) * A[i];\n        }\n        return score;\n    };\n\n    vector<int> current_dist(N);\n    long long current_score = get_score_and_validity(is_root, current_dist);\n    \n    vector<int> nodes(N);\n    iota(nodes.begin(), nodes.end(), 0);\n    \n    // Random number generator seeded with time\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Greedy removal phase: Try to remove roots to increase depth (and score)\n    // while maintaining validity.\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        shuffle(nodes.begin(), nodes.end(), rng);\n        for (int u : nodes) {\n            if (is_root[u]) {\n                is_root[u] = false;\n                long long new_score = get_score_and_validity(is_root, current_dist);\n                if (new_score == -1) {\n                    is_root[u] = true; // Revert if invalid\n                } else {\n                    current_score = new_score;\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    // Simulated Annealing phase to explore the solution space\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // Leave margin for output\n\n    double T = 100.0;\n    double cooling_rate = 0.9995; \n    \n    vector<bool> best_roots = is_root;\n    long long best_score = current_score;\n    vector<int> best_dist = current_dist;\n\n    vector<int> next_dist(N);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // Propose a move: either remove a root or swap a root with a non-root\n        int move_type = rng() % 2;\n        bool accepted = false;\n\n        if (move_type == 0) {\n            // Try remove\n            vector<int> roots_list;\n            for(int i=0; i<N; ++i) if(is_root[i]) roots_list.push_back(i);\n            \n            if (!roots_list.empty()) {\n                int idx = rng() % roots_list.size();\n                int u = roots_list[idx];\n                \n                is_root[u] = false;\n                long long new_score = get_score_and_validity(is_root, next_dist);\n                \n                if (new_score != -1) {\n                    double delta = (double)(new_score - current_score);\n                    // Accept if better, or with probability based on temperature\n                    if (delta > 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        current_dist = next_dist;\n                        accepted = true;\n                    } else {\n                        is_root[u] = true; // Revert\n                    }\n                } else {\n                    is_root[u] = true; // Revert\n                }\n            }\n        } else {\n            // Try swap\n            vector<int> roots_list, non_roots_list;\n            for(int i=0; i<N; ++i) {\n                if(is_root[i]) roots_list.push_back(i);\n                else non_roots_list.push_back(i);\n            }\n            \n            if (!roots_list.empty() && !non_roots_list.empty()) {\n                int i1 = rng() % roots_list.size();\n                int i2 = rng() % non_roots_list.size();\n                int u = roots_list[i1];\n                int w = non_roots_list[i2];\n                \n                is_root[u] = false;\n                is_root[w] = true;\n                \n                long long new_score = get_score_and_validity(is_root, next_dist);\n                \n                if (new_score != -1) {\n                    double delta = (double)(new_score - current_score);\n                    if (delta > 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        current_dist = next_dist;\n                        accepted = true;\n                    } else {\n                        is_root[u] = true;\n                        is_root[w] = false; // Revert\n                    }\n                } else {\n                    is_root[u] = true;\n                    is_root[w] = false; // Revert\n                }\n            }\n        }\n\n        // Update best solution found so far\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_roots = is_root;\n            best_dist = current_dist;\n        }\n\n        T *= cooling_rate;\n    }\n\n    // Reconstruct parent pointers based on best_dist\n    // If v is root, p_v = -1. Else p_v is a neighbor with dist = dist[v] - 1.\n    vector<int> P(N);\n    for (int v = 0; v < N; ++v) {\n        if (best_roots[v]) {\n            P[v] = -1;\n        } else {\n            int d = best_dist[v];\n            int parent = -1;\n            for (int u : adj[v]) {\n                if (best_dist[u] == d - 1) {\n                    parent = u;\n                    break; // Pick the first valid parent\n                }\n            }\n            P[v] = parent;\n        }\n    }\n\n    // Output result\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cassert>\n\nusing namespace std;\n\nstruct Piece {\n    int r, c;\n    char type; // 'x' = Oni, 'o' = Fukunokami, '.' = empty\n};\n\nstruct Operation {\n    char dir;\n    int idx;\n};\n\nint N = 20;\nvector<string> board;\nvector<pair<int, int>> oni_positions;\nvector<pair<int, int>> fuku_positions;\n\n// Check if direction is safe for removing Oni at (r, c)\n// dir: 0=up, 1=down, 2=left, 3=right\nbool is_safe_direction(int r, int c, int dir, const vector<string>& bd) {\n    if (dir == 0) { // up\n        for (int i = 0; i < r; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 1) { // down\n        for (int i = r + 1; i < N; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 2) { // left\n        for (int j = 0; j < c; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    } else { // right\n        for (int j = c + 1; j < N; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    }\n}\n\n// Calculate cost to remove Oni at (r, c) in given direction\nint get_cost(int r, int c, int dir) {\n    if (dir == 0) return 2 * (r + 1); // up then down\n    if (dir == 1) return 2 * (N - r); // down then up\n    if (dir == 2) return 2 * (c + 1); // left then right\n    return 2 * (N - c); // right then left\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n    }\n    \n    // Find all Oni and Fukunokami positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == 'x') {\n                oni_positions.push_back({i, j});\n            } else if (board[i][j] == 'o') {\n                fuku_positions.push_back({i, j});\n            }\n        }\n    }\n    \n    vector<Operation> ops;\n    vector<string> current_board = board;\n    \n    // Process each Oni\n    // Sort by minimum cost to remove (greedy approach)\n    struct OniInfo {\n        int r, c, best_dir, cost;\n    };\n    \n    vector<OniInfo> oni_list;\n    for (auto& p : oni_positions) {\n        int best_dir = -1;\n        int min_cost = 1e9;\n        for (int dir = 0; dir < 4; dir++) {\n            if (is_safe_direction(p.first, p.second, dir, current_board)) {\n                int cost = get_cost(p.first, p.second, dir);\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_dir = dir;\n                }\n            }\n        }\n        oni_list.push_back({p.first, p.second, best_dir, min_cost});\n    }\n    \n    // Sort by cost (remove cheapest first)\n    sort(oni_list.begin(), oni_list.end(), [](const OniInfo& a, const OniInfo& b) {\n        return a.cost < b.cost;\n    });\n    \n    // Remove each Oni\n    for (auto& oni : oni_list) {\n        int r = oni.r, c = oni.c;\n        int dir = oni.best_dir;\n        \n        if (dir == 0) { // up\n            // Shift column c upward (r+1) times\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'U', c});\n                // Update board\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n            // Shift column c downward (r+1) times to restore\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'D', c});\n                // Update board\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n        } else if (dir == 1) { // down\n            // Shift column c downward (N-r) times\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'D', c});\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n            // Shift column c upward (N-r) times to restore\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'U', c});\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n        } else if (dir == 2) { // left\n            // Shift row r leftward (c+1) times\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n            // Shift row r rightward (c+1) times to restore\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n        } else { // right\n            // Shift row r rightward (N-c) times\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n            // Shift row r leftward (N-c) times to restore\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n        }\n    }\n    \n    // Output operations\n    for (auto& op : ops) {\n        cout << op.dir << \" \" << op.idx << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    long long L;\n    cin >> N >> L;\n    \n    vector<long long> T(N);\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n    \n    // Use fixed seed for reproducibility, or time-based for variety\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Create weighted candidate distribution based on target frequencies\n    vector<int> weighted_candidates;\n    for (int i = 0; i < N; i++) {\n        // Higher target = more likely to be chosen as next cleaner\n        int weight = max(1, (int)(T[i] / 500 + 1));\n        for (int j = 0; j < weight; j++) {\n            weighted_candidates.push_back(i);\n        }\n    }\n    \n    // Initialize a and b arrays\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; i++) {\n        a[i] = weighted_candidates[rng() % weighted_candidates.size()];\n        b[i] = weighted_candidates[rng() % weighted_candidates.size()];\n    }\n    \n    // Simulation function\n    auto simulate = [&]() -> vector<long long> {\n        vector<long long> count(N, 0);\n        int current = 0;\n        \n        for (long long week = 0; week < L; week++) {\n            count[current]++;\n            // t = count[current] is the number of times current has cleaned\n            // If t is odd (1st, 3rd, 5th...), use a[current]\n            // If t is even (2nd, 4th, 6th...), use b[current]\n            if (count[current] % 2 == 1) {\n                current = a[current];\n            } else {\n                current = b[current];\n            }\n        }\n        \n        return count;\n    };\n    \n    // Error calculation\n    auto calcError = [&](const vector<long long>& actual) -> long long {\n        long long error = 0;\n        for (int i = 0; i < N; i++) {\n            error += abs(actual[i] - T[i]);\n        }\n        return error;\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_error = 1e18;\n    vector<int> best_a = a, best_b = b;\n    \n    // Main optimization loop\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Stop with buffer time for output\n        if (elapsed > 1950) break;\n        \n        // Evaluate current solution\n        vector<long long> actual = simulate();\n        long long error = calcError(actual);\n        \n        // Track best solution\n        if (error < best_error) {\n            best_error = error;\n            best_a = a;\n            best_b = b;\n        }\n        \n        // Local search: modify one parameter\n        int i = rng() % N;\n        int choice = rng() % 2;  // 0 = modify a[i], 1 = modify b[i]\n        int old_val = (choice == 0) ? a[i] : b[i];\n        \n        // Try new value from weighted candidates\n        int new_val = weighted_candidates[rng() % weighted_candidates.size()];\n        \n        if (choice == 0) {\n            a[i] = new_val;\n        } else {\n            b[i] = new_val;\n        }\n        \n        // Evaluate new solution\n        vector<long long> new_actual = simulate();\n        long long new_error = calcError(new_actual);\n        \n        // Simulated annealing acceptance criterion\n        if (new_error < error) {\n            // Always accept improvements\n        } else {\n            // Accept worse solutions with decreasing probability over time\n            double progress = (double)elapsed / 2000.0;\n            double temperature = 1000.0 * (1.0 - progress);\n            temperature = max(1.0, temperature);\n            \n            double acceptance_prob = exp(-(double)(new_error - error) / temperature);\n            \n            if ((double)rng() / rng.max() > acceptance_prob) {\n                // Revert change\n                if (choice == 0) {\n                    a[i] = old_val;\n                } else {\n                    b[i] = old_val;\n                }\n            }\n        }\n    }\n    \n    // Output best solution found\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 <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <chrono>\n#include <random>\n#include <iomanip>\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 weight;\n    double confidence; // 1.0 for query edges, <1.0 for estimated\n    bool fromQuery;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(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        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\n// Hilbert curve distance for better spatial locality\nint hilbertDist(int x, int y, int order = 14) {\n    int d = 0;\n    for (int s = 1 << (order - 1); s > 0; s >>= 1) {\n        int rx = (x & s) > 0;\n        int ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (rx == 0) {\n            if (ry == 1) {\n                x = (1 << order) - 1 - x;\n                y = (1 << order) - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// Minimum possible distance between two rectangles\nint minRectDist(const City& a, const City& b) {\n    int dx = 0, dy = 0;\n    if (a.rx < b.lx) dx = b.lx - a.rx;\n    else if (b.rx < a.lx) dx = a.lx - b.rx;\n    \n    if (a.ry < b.ly) dy = b.ly - a.ry;\n    else if (b.ry < a.ly) dy = a.ly - b.ry;\n    \n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Estimated distance using centers (more optimistic)\nint centerDist(const City& a, const City& b) {\n    double dx = a.cx - b.cx;\n    double dy = a.cy - b.cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\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, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    \n    vector<int> G(M);\n    for (int i = 0; i < M; i++) {\n        cin >> G[i];\n    }\n    \n    vector<City> cities(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 Hilbert curve distance for better spatial locality\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int ha = hilbertDist((int)cities[a].cx, (int)cities[a].cy);\n        int hb = hilbertDist((int)cities[b].cx, (int)cities[b].cy);\n        return ha < hb;\n    });\n    \n    // Assign cities to groups based on spatial ordering\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n    \n    // Track all known edges globally\n    map<pair<int,int>, Edge> knownEdges;\n    vector<vector<pair<int,int>>> groupEdges(M);\n    \n    int queriesUsed = 0;\n    \n    // Calculate query priority for each group\n    // Larger groups and groups with higher uncertainty get more queries\n    vector<pair<double, int>> groupPriority(M);\n    for (int i = 0; i < M; i++) {\n        int size = groups[i].size();\n        if (size < 2) {\n            groupPriority[i] = {0.0, i};\n            continue;\n        }\n        // Priority based on: number of edges needed * uncertainty\n        double uncertainty = 0;\n        for (int j = 0; j < size && j < 10; j++) {\n            for (int k = j + 1; k < size && k < 10; k++) {\n                int minD = minRectDist(cities[groups[i][j]], cities[groups[i][k]]);\n                int cenD = centerDist(cities[groups[i][j]], cities[groups[i][k]]);\n                uncertainty += (cenD - minD + 1);\n            }\n        }\n        // More edges needed = higher priority\n        groupPriority[i] = {(size - 1) * (1.0 + uncertainty / 100.0), i};\n    }\n    sort(groupPriority.begin(), groupPriority.end(), greater<pair<double,int>>());\n    \n    // Query each group strategically\n    for (auto& [priority, gi] : groupPriority) {\n        // Time check - leave margin for output\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        if (elapsed > 1850 || queriesUsed >= Q) break;\n        \n        int groupSize = groups[gi].size();\n        if (groupSize < 2) continue;\n        \n        // Calculate how many queries we can use for this group\n        int edgesNeeded = groupSize - 1;\n        int maxQueriesForGroup = min((Q - queriesUsed), (edgesNeeded + L - 2) / (L - 1));\n        \n        // Ensure we cover all cities in the group\n        vector<bool> covered(groupSize, false);\n        int queriesForThisGroup = 0;\n        \n        // First pass: ensure all cities are covered\n        for (int start = 0; start < groupSize && queriesForThisGroup < maxQueriesForGroup && queriesUsed < Q; ) {\n            int remaining = groupSize - start;\n            int chunkSize = min(L, remaining);\n            \n            if (chunkSize < 2) {\n                // Connect remaining city to previous\n                if (start > 0 && start < groupSize) {\n                    int u = groups[gi][start - 1];\n                    int v = groups[gi][start];\n                    if (u > v) swap(u, v);\n                    if (knownEdges.find({u, v}) == knownEdges.end()) {\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 0.5, false};\n                    }\n                }\n                break;\n            }\n            \n            // Make query\n            cout << \"?\" << \" \" << chunkSize;\n            for (int i = 0; i < chunkSize; i++) {\n                cout << \" \" << groups[gi][start + i];\n                covered[start + i] = true;\n            }\n            cout << endl;\n            cout.flush();\n            \n            queriesUsed++;\n            queriesForThisGroup++;\n            \n            // Read MST edges from response\n            for (int i = 0; i < chunkSize - 1; i++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                \n                // Mark as high confidence query edge\n                knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n            }\n            \n            // Move forward, overlap by 1 to ensure connectivity\n            start += chunkSize - 1;\n        }\n        \n        // Second pass: cover any missed cities with small queries\n        for (int i = 0; i < groupSize && queriesUsed < Q; i++) {\n            if (!covered[i]) {\n                // Find nearest covered city to query with\n                int bestJ = -1;\n                int bestDist = 1e9;\n                for (int j = 0; j < groupSize; j++) {\n                    if (covered[j] && j != i) {\n                        int d = centerDist(cities[groups[gi][i]], cities[groups[gi][j]]);\n                        if (d < bestDist) {\n                            bestDist = d;\n                            bestJ = j;\n                        }\n                    }\n                }\n                \n                if (bestJ >= 0) {\n                    int chunkSize = 2;\n                    if (queriesUsed < Q - 1) {\n                        // Try to add one more city if possible\n                        for (int k = 0; k < groupSize && chunkSize < L; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                chunkSize++;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    cout << \"?\" << \" \" << chunkSize << \" \" << groups[gi][i];\n                    int count = 1;\n                    if (count < chunkSize) {\n                        cout << \" \" << groups[gi][bestJ];\n                        count++;\n                        for (int k = 0; k < groupSize && count < chunkSize; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                cout << \" \" << groups[gi][k];\n                                count++;\n                            }\n                        }\n                    }\n                    cout << endl;\n                    cout.flush();\n                    \n                    queriesUsed++;\n                    \n                    for (int e = 0; e < chunkSize - 1; e++) {\n                        int u, v;\n                        cin >> u >> v;\n                        if (u > v) swap(u, v);\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n                    }\n                    covered[i] = true;\n                }\n            }\n        }\n    }\n    \n    // Build complete MST for each group using all available edges\n    for (int g = 0; g < M; g++) {\n        int groupSize = groups[g].size();\n        if (groupSize < 2) continue;\n        \n        vector<Edge> allEdges;\n        set<pair<int,int>> added;\n        \n        // Add all known edges for cities in this group\n        for (auto& [key, edge] : knownEdges) {\n            bool inGroup = false;\n            for (int city : groups[g]) {\n                if (city == edge.u || city == edge.v) {\n                    inGroup = true;\n                    break;\n                }\n            }\n            if (!inGroup) continue;\n            \n            // Check both endpoints are in this group\n            bool uIn = false, vIn = false;\n            for (int city : groups[g]) {\n                if (city == edge.u) uIn = true;\n                if (city == edge.v) vIn = true;\n            }\n            if (!uIn || !vIn) continue;\n            \n            if (added.find({edge.u, edge.v}) == added.end()) {\n                allEdges.push_back(edge);\n                added.insert({edge.u, edge.v});\n            }\n        }\n        \n        // Add estimated edges for missing connections\n        for (int i = 0; i < groupSize; i++) {\n            for (int j = i + 1; j < groupSize; j++) {\n                int u = groups[g][i];\n                int v = groups[g][j];\n                if (u > v) swap(u, v);\n                \n                if (added.find({u, v}) == added.end()) {\n                    int minD = minRectDist(cities[u], cities[v]);\n                    int cenD = centerDist(cities[u], cities[v]);\n                    // Use weighted average of min and center distance\n                    int estD = (minD + cenD) / 2;\n                    allEdges.push_back({u, v, estD, 0.3, false});\n                    added.insert({u, v});\n                }\n            }\n        }\n        \n        // Build MST - prefer query edges (high confidence), then by weight\n        sort(allEdges.begin(), allEdges.end(), [&](const Edge& a, const Edge& b) {\n            if (a.fromQuery != b.fromQuery) return a.fromQuery > b.fromQuery;\n            if (abs(a.confidence - b.confidence) > 0.1) return a.confidence > b.confidence;\n            return a.weight < b.weight;\n        });\n        \n        vector<pair<int,int>> mstEdges;\n        DSU dsu(N);\n        \n        for (auto& e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                mstEdges.push_back({e.u, e.v});\n                if ((int)mstEdges.size() == groupSize - 1) break;\n            }\n        }\n        \n        // Fallback: if MST is incomplete, add any remaining edges\n        if ((int)mstEdges.size() < groupSize - 1) {\n            DSU dsu2(N);\n            for (auto& e : mstEdges) {\n                dsu2.unite(e.first, e.second);\n            }\n            for (auto& e : allEdges) {\n                if (dsu2.unite(e.u, e.v)) {\n                    mstEdges.push_back({e.u, e.v});\n                    if ((int)mstEdges.size() == groupSize - 1) break;\n                }\n            }\n        }\n        \n        groupEdges[g] = mstEdges;\n    }\n    \n    // Output final answer\n    cout << \"!\" << endl;\n    cout.flush();\n    \n    for (int g = 0; g < M; g++) {\n        // Output cities in group\n        for (int i = 0; i < (int)groups[g].size(); i++) {\n            if (i > 0) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : groupEdges[g]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint cur_i, cur_j;\nvector<pair<int, int>> targets;\nset<pair<int, int>> blocks;\n\n// Direction arrays at global scope\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && blocks.find({i, j}) == blocks.end();\n}\n\npair<int, int> getSlideEnd(int i, int j, int di, int dj) {\n    while (true) {\n        int ni = i + di, nj = j + dj;\n        if (!isValid(ni, nj)) break;\n        i = ni;\n        j = nj;\n    }\n    return {i, j};\n}\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nvoid solve() {\n    cin >> N >> M;\n    cin >> cur_i >> cur_j;\n    for (int k = 0; k < M; k++) {\n        int i, j;\n        cin >> i >> j;\n        targets.push_back({i, j});\n    }\n    \n    vector<pair<char, char>> allActions;\n    \n    for (int t = 0; t < M; t++) {\n        int ti = targets[t].first;\n        int tj = targets[t].second;\n        vector<pair<char, char>> targetActions;\n        \n        // Simple BFS to find path to target\n        queue<tuple<int, int, vector<pair<char, char>>>> q;\n        vector<pair<char, char>> emptyPath;\n        q.push({cur_i, cur_j, emptyPath});\n        \n        set<pair<int, int>> visited;\n        visited.insert({cur_i, cur_j});\n        bool found = false;\n        \n        int maxDepth = 200;\n        \n        while (!q.empty() && !found) {\n            auto [pi, pj, path] = q.front();\n            q.pop();\n            \n            if ((int)path.size() > maxDepth) continue;\n            \n            if (pi == ti && pj == tj) {\n                targetActions = path;\n                found = true;\n                break;\n            }\n            \n            // Try moves\n            for (int d = 0; d < 4; d++) {\n                int ni = pi + DI[d], nj = pj + DJ[d];\n                \n                if (isValid(ni, nj) && !visited.count({ni, nj})) {\n                    visited.insert({ni, nj});\n                    auto newPath = path;\n                    newPath.emplace_back('M', DIR_CHAR[d]);\n                    q.push({ni, nj, newPath});\n                }\n                \n                // Try slides\n                auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                if ((si != pi || sj != pj) && !visited.count({si, sj})) {\n                    visited.insert({si, sj});\n                    auto newPath = path;\n                    newPath.emplace_back('S', DIR_CHAR[d]);\n                    q.push({si, sj, newPath});\n                }\n            }\n        }\n        \n        // Fallback: greedy approach if BFS fails\n        if (!found) {\n            int pi = cur_i, pj = cur_j;\n            \n            while (pi != ti || pj != tj) {\n                bool moved = false;\n                \n                // Try slides first\n                for (int d = 0; d < 4; d++) {\n                    auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                    \n                    if (si == ti && sj == tj) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                    \n                    int oldDist = manhattan(pi, pj, ti, tj);\n                    int newDist = manhattan(si, sj, ti, tj);\n                    \n                    if (newDist < oldDist && (si != pi || sj != pj)) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                }\n                \n                if (!moved) {\n                    // Use move\n                    if (pi < ti) {\n                        targetActions.emplace_back('M', 'D');\n                        pi++;\n                    } else if (pi > ti) {\n                        targetActions.emplace_back('M', 'U');\n                        pi--;\n                    } else if (pj < tj) {\n                        targetActions.emplace_back('M', 'R');\n                        pj++;\n                    } else if (pj > tj) {\n                        targetActions.emplace_back('M', 'L');\n                        pj--;\n                    }\n                }\n                \n                if ((int)targetActions.size() > maxDepth) break;\n            }\n        }\n        \n        // Execute actions and update blocks\n        for (auto& action : targetActions) {\n            char act = action.first;\n            char dir = action.second;\n            \n            if (act == 'M') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        cur_i += DI[d];\n                        cur_j += DJ[d];\n                        break;\n                    }\n                }\n            } else if (act == 'S') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        tie(cur_i, cur_j) = getSlideEnd(cur_i, cur_j, DI[d], DJ[d]);\n                        break;\n                    }\n                }\n            } else if (act == 'A') {\n                int bi = cur_i, bj = cur_j;\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        bi += DI[d];\n                        bj += DJ[d];\n                        break;\n                    }\n                }\n                if (blocks.count({bi, bj})) blocks.erase({bi, bj});\n                else blocks.insert({bi, bj});\n            }\n            allActions.emplace_back(act, dir);\n        }\n    }\n    \n    for (auto& action : allActions) {\n        cout << action.first << \" \" << action.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\n// Check if two rectangles overlap (have positive area intersection)\nbool rectangles_overlap(const Rect& a, const Rect& b) {\n    int x_overlap = max(0, min(a.x2, b.x2) - max(a.x1, b.x1));\n    int y_overlap = max(0, min(a.y2, b.y2) - max(a.y1, b.y1));\n    return x_overlap > 0 && y_overlap > 0;\n}\n\n// Validate all rectangles are non-overlapping\nbool validate_rectangles(const vector<Rect>& rects) {\n    int n = rects.size();\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            if (rectangles_overlap(rects[i], rects[j])) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Validate all rectangles are within bounds\nbool validate_bounds(const vector<Rect>& rects) {\n    for (int i = 0; i < (int)rects.size(); i++) {\n        if (rects[i].x1 < 0 || rects[i].y1 < 0 || \n            rects[i].x2 > 10000 || rects[i].y2 > 10000 ||\n            rects[i].x1 >= rects[i].x2 || rects[i].y1 >= rects[i].y2) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Recursive space partitioning - GUARANTEES no overlaps by construction\nvoid partition(vector<int>& indices, const vector<Company>& companies, \n               Rect region, vector<Rect>& result) {\n    if (indices.empty()) return;\n    \n    if (indices.size() == 1) {\n        int idx = indices[0];\n        result[companies[idx].id] = region;\n        return;\n    }\n    \n    // Calculate total area needed for this region\n    long long total_area = 0;\n    int min_x = 10001, max_x = -1, min_y = 10001, max_y = -1;\n    for (int idx : indices) {\n        total_area += companies[idx].r;\n        min_x = min(min_x, companies[idx].x);\n        max_x = max(max_x, companies[idx].x);\n        min_y = min(min_y, companies[idx].y);\n        max_y = max(max_y, companies[idx].y);\n    }\n    \n    // Determine split direction based on point distribution\n    bool split_vertical = (max_x - min_x) >= (max_y - min_y);\n    \n    // Sort indices for splitting\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        if (split_vertical) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        } else {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        }\n    });\n    \n    // Find split point that balances area\n    long long left_area = 0;\n    int split_idx = 1;\n    long long best_diff = LLONG_MAX;\n    \n    for (int i = 0; i < (int)indices.size() - 1; i++) {\n        left_area += companies[indices[i]].r;\n        long long diff = abs(2 * left_area - total_area);\n        if (diff < best_diff) {\n            best_diff = diff;\n            split_idx = i + 1;\n        }\n    }\n    \n    long long left_sum = 0;\n    for (int i = 0; i < split_idx; i++) {\n        left_sum += companies[indices[i]].r;\n    }\n    \n    vector<int> left_indices(indices.begin(), indices.begin() + split_idx);\n    vector<int> right_indices(indices.begin() + split_idx, indices.end());\n    \n    Rect left_region = region, right_region = region;\n    \n    if (split_vertical) {\n        // Vertical split - ensure split line doesn't cut through any point\n        // Find safe split position between left and right point sets\n        int left_max_x = -1, right_min_x = 10001;\n        for (int idx : left_indices) {\n            left_max_x = max(left_max_x, companies[idx].x);\n        }\n        for (int idx : right_indices) {\n            right_min_x = min(right_min_x, companies[idx].x);\n        }\n        \n        // Calculate ideal split based on area ratio\n        int ideal_split = region.x1 + (int)((left_sum * (region.x2 - region.x1) + total_area/2) / total_area);\n        \n        // Find safe split position\n        int split_x;\n        if (left_max_x < right_min_x) {\n            // There's a gap between point sets - split in the gap\n            split_x = max(region.x1 + 1, min(region.x2 - 1, (left_max_x + right_min_x + 1) / 2));\n        } else {\n            // Points overlap in x - use ideal split but ensure it's valid\n            split_x = max(region.x1 + 1, min(region.x2 - 1, ideal_split));\n        }\n        \n        // Ensure both regions have positive area\n        if (split_x <= region.x1) split_x = region.x1 + 1;\n        if (split_x >= region.x2) split_x = region.x2 - 1;\n        split_x = max(region.x1 + 1, min(region.x2 - 1, split_x));\n        \n        left_region.x2 = split_x;\n        right_region.x1 = split_x;\n    } else {\n        // Horizontal split\n        int left_max_y = -1, right_min_y = 10001;\n        for (int idx : left_indices) {\n            left_max_y = max(left_max_y, companies[idx].y);\n        }\n        for (int idx : right_indices) {\n            right_min_y = min(right_min_y, companies[idx].y);\n        }\n        \n        int ideal_split = region.y1 + (int)((left_sum * (region.y2 - region.y1) + total_area/2) / total_area);\n        \n        int split_y;\n        if (left_max_y < right_min_y) {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, (left_max_y + right_min_y + 1) / 2));\n        } else {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, ideal_split));\n        }\n        \n        if (split_y <= region.y1) split_y = region.y1 + 1;\n        if (split_y >= region.y2) split_y = region.y2 - 1;\n        split_y = max(region.y1 + 1, min(region.y2 - 1, split_y));\n        \n        left_region.y2 = split_y;\n        right_region.y1 = split_y;\n    }\n    \n    // Ensure both regions have positive area\n    if (left_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x1 + 1;\n            right_region.x1 = region.x1 + 1;\n        } else {\n            left_region.y2 = region.y1 + 1;\n            right_region.y1 = region.y1 + 1;\n        }\n    }\n    if (right_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x2 - 1;\n            right_region.x1 = region.x2 - 1;\n        } else {\n            left_region.y2 = region.y2 - 1;\n            right_region.y1 = region.y2 - 1;\n        }\n    }\n    \n    partition(left_indices, companies, left_region, result);\n    partition(right_indices, companies, right_region, result);\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    long long total_r = 0;\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        total_r += companies[i].r;\n    }\n    \n    // Create order based on spatial locality\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    \n    // Sort by x + y for better spatial coherence\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        return companies[i].x + companies[i].y < companies[j].x + companies[j].y;\n    });\n    \n    // Initial partitioning - NO post-adjustment\n    vector<Rect> rects(n);\n    Rect full_region = {0, 0, 10000, 10000};\n    partition(order, companies, full_region, rects);\n    \n    // VALIDATE before output\n    #ifdef DEBUG\n    if (!validate_rectangles(rects)) {\n        cerr << \"ERROR: Overlaps detected!\" << endl;\n    }\n    if (!validate_bounds(rects)) {\n        cerr << \"ERROR: Bounds violated!\" << endl;\n    }\n    #endif\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        cout << rects[i].x1 << \" \" << rects[i].y1 << \" \" \n             << rects[i].x2 << \" \" << rects[i].y2 << \"\\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\nusing namespace std;\n\n// Global grid data\nconst int H = 50;\nconst int W = 50;\nvector<vector<int>> tile_id;\nvector<vector<int>> score_val;\nint max_tile = 0;\n\n// Search state\nvector<char> visited_tiles;\nmt19937 rng;\n\n// Heuristic extension of the path\nvoid extend_path(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    // Directions: U, D, L, R\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    \n    while (true) {\n        // Collect valid neighbors\n        struct Cand {\n            int r, c, score, degree;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    int s = score_val[nr][nc];\n                    int deg = 0;\n                    // Lookahead 1 step: count available moves from neighbor\n                    for(int k=0; k<4; ++k) {\n                        int nnr = nr + dr[k];\n                        int nnc = nc + dc[k];\n                        if(nnr >= 0 && nnr < H && nnc >= 0 && nnc < W) {\n                            if(!visited_tiles[tile_id[nnr][nnc]]) deg++;\n                        }\n                    }\n                    cands[count++] = {nr, nc, s, deg};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort candidates: higher (score + degree) first\n        // Since count <= 4, simple sort is very fast\n        for(int i=0; i<count-1; ++i) {\n            for(int j=0; j<count-1-i; ++j) {\n                int val1 = cands[j].score + cands[j].degree;\n                int val2 = cands[j+1].score + cands[j+1].degree;\n                if(val1 < val2) {\n                    swap(cands[j], cands[j+1]);\n                }\n            }\n        }\n        \n        // Pick from top min(3, count) to add randomness\n        int K = (count < 3) ? count : 3;\n        int idx = (int)(rng() % K);\n        \n        int nr = cands[idx].r;\n        int nc = cands[idx].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    tile_id.assign(H, vector<int>(W));\n    max_tile = 0;\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> tile_id[i][j];\n            if (tile_id[i][j] > max_tile) max_tile = tile_id[i][j];\n        }\n    }\n    \n    score_val.assign(H, vector<int>(W));\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> score_val[i][j];\n        }\n    }\n    \n    visited_tiles.assign(max_tile + 1, 0);\n    \n    // Seed RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Initial Solution\n    vector<pair<int, int>> current_path;\n    current_path.reserve(2500);\n    current_path.push_back({si, sj});\n    visited_tiles[tile_id[si][sj]] = 1;\n    long long current_score = score_val[si][sj];\n    \n    extend_path(current_path, current_score);\n    \n    vector<pair<int, int>> best_path = current_path;\n    long long best_score = current_score;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    double temperature = 500.0; \n    \n    // Main Search Loop (Simulated Annealing / Iterated Local Search)\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto ms = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (ms > 1900) break; // Stop at 1.9s to ensure output within 2.0s\n        \n        // Cooling schedule\n        temperature *= 0.9995;\n        if (temperature < 1.0) temperature = 1.0;\n        \n        // Backup current state to allow rollback if move is rejected\n        vector<pair<int, int>> path_backup = current_path;\n        long long score_backup = current_score;\n        \n        // Select a cut point uniformly\n        int cut_idx = (int)(rng() % current_path.size());\n        \n        // Rollback visited tiles for the part we are cutting\n        for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n            int r = current_path[i].first;\n            int c = current_path[i].second;\n            visited_tiles[tile_id[r][c]] = 0;\n        }\n        current_path.resize(cut_idx + 1);\n        \n        // Recalculate score for the prefix\n        long long temp_score = 0;\n        for(const auto& p : current_path) temp_score += score_val[p.first][p.second];\n        \n        // Extend path from cut point\n        extend_path(current_path, temp_score);\n        \n        // Simulated Annealing Acceptance Criterion\n        bool accept = false;\n        if (temp_score > current_score) {\n            accept = true;\n        } else {\n            double diff = (double)(temp_score - current_score);\n            double prob = exp(diff / temperature);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = temp_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n            }\n        } else {\n            // Revert to backup state\n            \n            // 1. Unmark the tiles added in the failed extension\n            for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 0;\n            }\n            \n            // 2. Restore path and score\n            current_path = path_backup;\n            current_score = score_backup;\n            \n            // 3. Re-mark the tiles of the original suffix that were unmarked at the start\n            for (size_t i = cut_idx + 1; i < current_path.size(); ++i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 1;\n            }\n        }\n    }\n    \n    // Construct Output String\n    string res;\n    if (best_path.size() > 1) {\n        res.reserve(best_path.size() - 1);\n        for (size_t i = 1; i < best_path.size(); ++i) {\n            int dr = best_path[i].first - best_path[i-1].first;\n            int dc = best_path[i].second - best_path[i-1].second;\n            if (dr == -1) res += 'U';\n            else if (dr == 1) res += 'D';\n            else if (dc == -1) res += 'L';\n            else if (dc == 1) res += 'R';\n        }\n    }\n    cout << res << endl;\n    \n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Solver {\n    double h[N][N-1];  // horizontal edges: h[i][j] = edge from (i,j) to (i,j+1)\n    double v[N-1][N];  // vertical edges: v[i][j] = edge from (i,j) to (i+1,j)\n    int h_cnt[N][N-1];\n    int v_cnt[N-1][N];\n    \n    Solver() {\n        for(int i = 0; i < N; i++) {\n            for(int j = 0; j < N-1; j++) {\n                h[i][j] = 5000.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for(int i = 0; i < N-1; i++) {\n            for(int j = 0; j < N; j++) {\n                v[i][j] = 5000.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n    \n    // Get edge weight with bounds checking\n    double get_weight(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v[i-1][j] : 1e9;\n        if(dir == 'D') return (i < N-1) ? v[i][j] : 1e9;\n        if(dir == 'L') return (j > 0) ? h[i][j-1] : 1e9;\n        if(dir == 'R') return (j < N-1) ? h[i][j] : 1e9;\n        return 1e9;\n    }\n    \n    // Get visit count for an edge\n    int get_count(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v_cnt[i-1][j] : 0;\n        if(dir == 'D') return (i < N-1) ? v_cnt[i][j] : 0;\n        if(dir == 'L') return (j > 0) ? h_cnt[i][j-1] : 0;\n        if(dir == 'R') return (j < N-1) ? h_cnt[i][j] : 0;\n        return 0;\n    }\n    \n    pair<string, double> dijkstra(int si, int sj, int ti, int tj, double temp) {\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<char>> move(N, vector<char>(N, 0));\n        \n        dist[si][sj] = 0;\n        pq.push({0.0, si, sj});\n        \n        const char dirs[] = {'U', 'D', 'L', 'R'};\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while(!pq.empty()) {\n            auto [d, i, j] = pq.top();\n            pq.pop();\n            \n            if(d > dist[i][j] + 1e-9) continue;\n            if(i == ti && j == tj) break;\n            \n            for(int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                \n                if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double w = get_weight(i, j, dirs[dir]);\n                if(w >= 1e9) continue;\n                \n                // Exploration bonus: prefer less-visited edges\n                int cnt = get_count(i, j, dirs[dir]);\n                double bonus = temp / (cnt + 1);\n                double new_dist = d + w + bonus;\n                \n                if(new_dist < dist[ni][nj]) {\n                    dist[ni][nj] = new_dist;\n                    prev[ni][nj] = {i, j};\n                    move[ni][nj] = dirs[dir];\n                    pq.push({new_dist, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path;\n        int ci = ti, cj = tj;\n        while(ci != si || cj != sj) {\n            path += move[ci][cj];\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        \n        return {path, dist[ti][tj]};\n    }\n    \n    void update(const string& path, int si, int sj, int observed, int query_num) {\n        if(path.empty()) return;\n        \n        // Calculate estimated cost and track vertices\n        double estimated = 0;\n        int ci = si, cj = sj;\n        vector<tuple<int, int, char>> edges;\n        \n        for(char c : path) {\n            double w = get_weight(ci, cj, c);\n            estimated += w;\n            edges.push_back({ci, cj, c});\n            \n            if(c == 'U') ci--;\n            else if(c == 'D') ci++;\n            else if(c == 'L') cj--;\n            else if(c == 'R') cj++;\n        }\n        \n        if(estimated < 1) estimated = 1;\n        double ratio = (double)observed / estimated;\n        \n        // Learning rate decreases over time\n        double lr = 0.30 * pow(0.992, query_num);\n        lr = max(lr, 0.01);\n        \n        // Update edges on path\n        for(auto& [i, j, c] : edges) {\n            if(c == 'U') {\n                v[i-1][j] = (1-lr) * v[i-1][j] + lr * v[i-1][j] * ratio;\n                v_cnt[i-1][j]++;\n            } else if(c == 'D') {\n                v[i][j] = (1-lr) * v[i][j] + lr * v[i][j] * ratio;\n                v_cnt[i][j]++;\n            } else if(c == 'L') {\n                h[i][j-1] = (1-lr) * h[i][j-1] + lr * h[i][j-1] * ratio;\n                h_cnt[i][j-1]++;\n            } else if(c == 'R') {\n                h[i][j] = (1-lr) * h[i][j] + lr * h[i][j] * ratio;\n                h_cnt[i][j]++;\n            }\n        }\n        \n        // Smoothing: propagate information to same row/column\n        smooth(query_num);\n    }\n    \n    void smooth(int query_num) {\n        double smooth_lr = 0.05 * pow(0.995, query_num);\n        \n        // Smooth horizontal edges within each row\n        for(int i = 0; i < N; i++) {\n            double row_avg = 0;\n            int row_cnt = 0;\n            for(int j = 0; j < N-1; j++) {\n                if(h_cnt[i][j] > 0) {\n                    row_avg += h[i][j];\n                    row_cnt++;\n                }\n            }\n            if(row_cnt > 0) {\n                row_avg /= row_cnt;\n                for(int j = 0; j < N-1; j++) {\n                    if(h_cnt[i][j] > 0) {\n                        h[i][j] = (1-smooth_lr) * h[i][j] + smooth_lr * row_avg;\n                    }\n                }\n            }\n        }\n        \n        // Smooth vertical edges within each column\n        for(int j = 0; j < N; j++) {\n            double col_avg = 0;\n            int col_cnt = 0;\n            for(int i = 0; i < N-1; i++) {\n                if(v_cnt[i][j] > 0) {\n                    col_avg += v[i][j];\n                    col_cnt++;\n                }\n            }\n            if(col_cnt > 0) {\n                col_avg /= col_cnt;\n                for(int i = 0; i < N-1; i++) {\n                    if(v_cnt[i][j] > 0) {\n                        v[i][j] = (1-smooth_lr) * v[i][j] + smooth_lr * col_avg;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    mt19937 rng(42);\n    Solver solver;\n    \n    for(int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Exploration temperature decreases over time\n        // Higher early for exploration, lower later for exploitation\n        double temp = 300.0 * pow(0.994, k);\n        \n        auto [path, est_cost] = solver.dijkstra(si, sj, ti, tj, temp);\n        \n        cout << path << \"\\n\";\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        solver.update(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> S[i];\n    }\n\n    vector<string> grid(N, string(N, '.'));\n    vector<int> indices(M);\n    for (int i = 0; i < M; ++i) indices[i] = i;\n\n    // Process longer strings first to lock in more constrained placements\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return S[a].size() > S[b].size();\n    });\n\n    for (int idx : indices) {\n        const string& s = S[idx];\n        int k = s.size();\n        int best_orient = -1;\n        int best_start_i = -1;\n        int best_start_j = -1;\n        int max_dot = -1;\n\n        // Check all horizontal placements\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int col = (j + p) % N;\n                    if (grid[i][col] != '.' && grid[i][col] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[i][col] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 0;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        // Check all vertical placements\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ++i) {\n                int dot_count = 0;\n                bool compatible = true;\n                for (int p = 0; p < k; ++p) {\n                    int row = (i + p) % N;\n                    if (grid[row][j] != '.' && grid[row][j] != s[p]) {\n                        compatible = false;\n                        break;\n                    }\n                    if (grid[row][j] == '.') {\n                        dot_count++;\n                    }\n                }\n                if (compatible && dot_count > max_dot) {\n                    max_dot = dot_count;\n                    best_orient = 1;\n                    best_start_i = i;\n                    best_start_j = j;\n                }\n            }\n        }\n\n        if (max_dot >= 0) {\n            for (int p = 0; p < k; ++p) {\n                int i, j;\n                if (best_orient == 0) {\n                    i = best_start_i;\n                    j = (best_start_j + p) % N;\n                } else {\n                    i = (best_start_i + p) % N;\n                    j = best_start_j;\n                }\n                if (grid[i][j] == '.') {\n                    grid[i][j] = s[p];\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << grid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <map>\n#include <functional>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> h_id, v_id;\nint h_count = 0, v_count = 0;\n\nint flatten(int r, int c) {\n    return r * N + c;\n}\n\nPoint unflatten(int idx) {\n    return {idx / N, idx % N};\n}\n\nint get_cost(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N || grid[r][c] == '#') return 1e9;\n    return grid[r][c] - '0';\n}\n\n// Reconstruct path from parents\nstring reconstruct_path(int start_node, int end_node, const vector<int>& parent) {\n    if (start_node == end_node) return \"\";\n    vector<int> path;\n    int curr = end_node;\n    while (curr != start_node) {\n        if (curr == -1) return \"\";\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    \n    string res = \"\";\n    int curr_r = start_node / N;\n    int curr_c = start_node % N;\n    \n    for (int node : path) {\n        int nr = node / N;\n        int nc = node % N;\n        if (nr < curr_r) res += 'U';\n        else if (nr > curr_r) res += 'D';\n        else if (nc < curr_c) res += 'L';\n        else if (nc > curr_c) res += 'R';\n        curr_r = nr;\n        curr_c = nc;\n    }\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // 1. Identify Segments\n    h_id.assign(N, vector<int>(N, -1));\n    v_id.assign(N, vector<int>(N, -1));\n\n    // Horizontal\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            int start = j;\n            while (j < N && grid[i][j] != '#') j++;\n            for (int k = start; k < j; ++k) {\n                h_id[i][k] = h_count;\n            }\n            h_count++;\n        }\n    }\n\n    // Vertical\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            int start = i;\n            while (i < N && grid[i][j] != '#') i++;\n            for (int k = start; k < i; ++k) {\n                v_id[k][j] = v_count;\n            }\n            v_count++;\n        }\n    }\n\n    // 2. Build Bipartite Graph\n    vector<pair<int, int>> edges; \n    vector<Point> edge_to_point;\n    map<pair<int, int>, int> edge_index;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                int h = h_id[i][j];\n                int v = v_id[i][j];\n                if (edge_index.find({h, v}) == edge_index.end()) {\n                    edge_index[{h, v}] = (int)edges.size();\n                    edges.push_back({h, v});\n                    edge_to_point.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> bip_adj(h_count);\n    for (auto& e : edges) {\n        bip_adj[e.first].push_back(e.second);\n    }\n\n    // 3. Max Bipartite Matching (DFS)\n    vector<int> match_h(h_count, -1), match_v(v_count, -1);\n\n    function<bool(int, vector<bool>&)> dfs = [&](int u, vector<bool>& visited) {\n        for (int v : bip_adj[u]) {\n            if (visited[v]) continue;\n            visited[v] = true;\n            if (match_v[v] < 0 || dfs(match_v[v], visited)) {\n                match_h[u] = v;\n                match_v[v] = u;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    for (int i = 0; i < h_count; ++i) {\n        vector<bool> visited(v_count, false);\n        dfs(i, visited);\n    }\n\n    // 4. Construct Edge Cover\n    vector<bool> h_covered(h_count, false);\n    vector<bool> v_covered(v_count, false);\n    vector<bool> edge_in_cover(edges.size(), false);\n    vector<Point> selected_points;\n\n    // Add matching edges\n    for (int i = 0; i < h_count; ++i) {\n        if (match_h[i] != -1) {\n            auto it = edge_index.find({i, match_h[i]});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[match_h[i]] = true;\n            }\n        }\n    }\n\n    // Cover unmatched H\n    for (int i = 0; i < h_count; ++i) {\n        if (!h_covered[i] && !bip_adj[i].empty()) {\n            int v = bip_adj[i][0];\n            auto it = edge_index.find({i, v});\n            if (it != edge_index.end()) {\n                edge_in_cover[it->second] = true;\n                h_covered[i] = true;\n                v_covered[v] = true;\n            }\n        }\n    }\n    // Cover unmatched V\n    for (int i = 0; i < v_count; ++i) {\n        if (!v_covered[i]) {\n            for (size_t j = 0; j < edges.size(); ++j) {\n                if (edges[j].second == i) {\n                    edge_in_cover[j] = true;\n                    v_covered[i] = true;\n                    h_covered[edges[j].first] = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    for (size_t i = 0; i < edges.size(); ++i) {\n        if (edge_in_cover[i]) {\n            selected_points.push_back(edge_to_point[i]);\n        }\n    }\n\n    // Add start point\n    Point start_p = {si, sj};\n    bool start_present = false;\n    for (auto& p : selected_points) {\n        if (p == start_p) {\n            start_present = true;\n            break;\n        }\n    }\n    if (!start_present) selected_points.push_back(start_p);\n\n    int K = (int)selected_points.size();\n    vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n    vector<vector<int>> parents(K, vector<int>(N * N, -1));\n\n    // 5. All-Pairs Shortest Paths\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < K; ++i) {\n        int sr = selected_points[i].r;\n        int sc = selected_points[i].c;\n        int start_node = flatten(sr, sc);\n        \n        vector<long long> d(N * N, -1);\n        vector<int> p(N * N, -1);\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n\n        d[start_node] = 0;\n        pq.push({0, start_node});\n\n        while (!pq.empty()) {\n            auto [dist_val, u] = pq.top();\n            pq.pop();\n\n            if (d[u] != -1 && dist_val > d[u]) continue;\n\n            Point pu = unflatten(u);\n            for (int k = 0; k < 4; ++k) {\n                int nr = pu.r + dr[k];\n                int nc = pu.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                    int v = flatten(nr, nc);\n                    long long new_dist = dist_val + get_cost(nr, nc);\n                    if (d[v] == -1 || new_dist < d[v]) {\n                        d[v] = new_dist;\n                        p[v] = u;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n        \n        for (int j = 0; j < K; ++j) {\n            int tr = selected_points[j].r;\n            int tc = selected_points[j].c;\n            int t_node = flatten(tr, tc);\n            dist_mat[i][j] = d[t_node];\n        }\n        parents[i] = p;\n    }\n\n    // 6. TSP\n    int start_idx = -1;\n    for(int i = 0; i < K; ++i) {\n        if(selected_points[i] == start_p) {\n            start_idx = i;\n            break;\n        }\n    }\n    \n    // Nearest Neighbor\n    vector<int> tour;\n    vector<bool> visited(K, false);\n    int curr = start_idx;\n    tour.push_back(curr);\n    visited[curr] = true;\n    \n    for (int i = 0; i < K - 1; ++i) {\n        int next = -1;\n        long long min_d = -1;\n        for (int j = 0; j < K; ++j) {\n            if (!visited[j]) {\n                if (next == -1 || dist_mat[curr][j] < min_d) {\n                    min_d = dist_mat[curr][j];\n                    next = j;\n                }\n            }\n        }\n        if (next != -1) {\n            tour.push_back(next);\n            visited[next] = true;\n            curr = next;\n        }\n    }\n    \n    // 2-opt\n    bool improved = true;\n    int iterations = 0;\n    while (improved && iterations < 2000) {\n        improved = false;\n        iterations++;\n        for (int i = 0; i < K - 1; ++i) {\n            for (int j = i + 1; j < K; ++j) {\n                if (i + 1 >= j) continue;\n                \n                int u = tour[i];\n                int v = tour[i+1];\n                int x = tour[j];\n                int y = tour[(j+1)%K];\n                \n                if (dist_mat[u][x] == -1 || dist_mat[v][y] == -1) continue;\n                if (dist_mat[u][v] == -1 || dist_mat[x][y] == -1) continue;\n\n                long long old_cost = dist_mat[u][v] + dist_mat[x][y];\n                long long new_cost = dist_mat[u][x] + dist_mat[v][y];\n                \n                if (new_cost < old_cost) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Reconstruct Full Path\n    string final_path = \"\";\n    for (int i = 0; i < K; ++i) {\n        int u = tour[i];\n        int v = tour[(i + 1) % K];\n        string segment = reconstruct_path(flatten(selected_points[u].r, selected_points[u].c), \n                                          flatten(selected_points[v].r, selected_points[v].c), \n                                          parents[u]);\n        final_path += segment;\n    }\n\n    cout << final_path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconst int MAX_N = 1005;\nconst int MAX_DAY = 2000;\nconst int STOP_ASSIGN_DAY = 1700; // Stop assigning tasks at day 1700\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int in_degree = 0;\n    vector<int> dependents;\n    int priority = 0;\n    int status = -1; // -1: not started, 0: running, 1: done\n    int assigned_member = -1;\n    int start_day = 0;\n};\n\nstruct Member {\n    int id;\n    vector<int> s;\n    int busy_until = 0;\n    int current_task = -1;\n    int start_day = 0;\n    int tasks_completed = 0;\n    bool has_active_task = false;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, K, R;\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    vector<Task> tasks(N + 1);\n    int max_task_difficulty = 0;\n    for (int i = 1; i <= N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        int task_sum = 0;\n        for (int j = 0; j < K; ++j) {\n            cin >> tasks[i].d[j];\n            task_sum += tasks[i].d[j];\n        }\n        max_task_difficulty = max(max_task_difficulty, task_sum);\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        tasks[v].in_degree++;\n        tasks[u].dependents.push_back(v);\n    }\n\n    // Compute priority using bitsets for reachability\n    vector<bitset<MAX_N>> reach(N + 1);\n    for (int i = N; i >= 1; --i) {\n        reach[i][i] = 1;\n        for (int v : tasks[i].dependents) {\n            reach[i] |= reach[v];\n        }\n        tasks[i].priority = (int)reach[i].count();\n    }\n\n    vector<Member> members(M + 1);\n    for (int j = 1; j <= M; ++j) {\n        members[j].id = j;\n        members[j].s.assign(K, 0);\n        members[j].busy_until = 0;\n        members[j].has_active_task = false;\n    }\n\n    vector<int> ready_tasks;\n    ready_tasks.reserve(N);\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            ready_tasks.push_back(i);\n        }\n    }\n\n    int current_day = 0;\n    const double ALPHA_BASE = 0.3;\n    int completed_count = 0;\n    int active_member_count = 0;\n\n    while (true) {\n        current_day++;\n        \n        vector<pair<int, int>> assignments;\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int j = 1; j <= M; ++j) {\n            if (!members[j].has_active_task) {\n                free_members.push_back(j);\n            }\n        }\n\n        // Stop assigning tasks after STOP_ASSIGN_DAY\n        bool can_assign = (current_day <= STOP_ASSIGN_DAY);\n        \n        if (can_assign && !free_members.empty() && !ready_tasks.empty()) {\n            vector<int> candidates;\n            candidates.reserve(ready_tasks.size());\n            for (int t_idx : ready_tasks) {\n                if (tasks[t_idx].status == -1) {\n                    candidates.push_back(t_idx);\n                }\n            }\n            \n            sort(candidates.begin(), candidates.end(), [&](int a, int b) {\n                return tasks[a].priority > tasks[b].priority;\n            });\n\n            for (int t_idx : candidates) {\n                if (tasks[t_idx].status != -1) continue;\n                if (free_members.empty()) break;\n\n                int best_m = -1;\n                int min_t = 2000000000;\n                \n                for (int m_idx : free_members) {\n                    int w = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                            w += tasks[t_idx].d[k] - members[m_idx].s[k];\n                        }\n                    }\n                    // Very conservative estimate with large buffer\n                    int t_est = max(1, w + 10);\n                    \n                    // Ensure task completes well before day 2000\n                    if (current_day + t_est - 1 >= MAX_DAY - 10) continue;\n                    \n                    if (t_est < min_t) {\n                        min_t = t_est;\n                        best_m = m_idx;\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_idx});\n                    tasks[t_idx].status = 0;\n                    tasks[t_idx].assigned_member = best_m;\n                    tasks[t_idx].start_day = current_day;\n                    \n                    members[best_m].busy_until = current_day + min_t - 1;\n                    members[best_m].current_task = t_idx;\n                    members[best_m].start_day = current_day;\n                    members[best_m].has_active_task = true;\n                    active_member_count++;\n                    \n                    // Remove from free_members\n                    for (auto it = free_members.begin(); it != free_members.end(); ++it) {\n                        if (*it == best_m) {\n                            free_members.erase(it);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << \"\\n\";\n        \n        // Output skill predictions for visualization\n        if (current_day % 100 == 1) {\n            for (int j = 1; j <= M; ++j) {\n                if (members[j].tasks_completed > 0) {\n                    cout << \"#s \" << j;\n                    for (int k = 0; k < K; ++k) {\n                        cout << \" \" << members[j].s[k];\n                    }\n                    cout << \"\\n\";\n                }\n            }\n        }\n        cout.flush();\n\n        // Read completion info from Judge\n        int n_fin;\n        cin >> n_fin;\n        if (n_fin == -1) {\n            // All tasks should be complete at this point\n            // If we have active members, that's an error in our logic\n            break;\n        }\n\n        vector<int> finished_members(n_fin);\n        for (int i = 0; i < n_fin; ++i) {\n            cin >> finished_members[i];\n        }\n\n        // Update state and Skill Estimates\n        for (int m_idx : finished_members) {\n            int t_idx = members[m_idx].current_task;\n            if (t_idx == -1) continue;\n\n            int duration = current_day - members[m_idx].start_day + 1;\n            int t_obs = duration;\n            \n            // Skill Update Logic\n            int w_pred = 0;\n            vector<int> active_dims;\n            active_dims.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                    w_pred += tasks[t_idx].d[k] - members[m_idx].s[k];\n                    active_dims.push_back(k);\n                }\n            }\n            int t_pred = (w_pred == 0) ? 1 : w_pred;\n            \n            double error = (double)t_obs - t_pred;\n            \n            if (!active_dims.empty()) {\n                double alpha = ALPHA_BASE / sqrt(max(1, members[m_idx].tasks_completed + 1));\n                alpha = min(alpha, 0.5);\n                \n                double update_per_dim = alpha * error / active_dims.size();\n                \n                for (int k : active_dims) {\n                    double new_s = members[m_idx].s[k] - update_per_dim;\n                    new_s = max(0.0, new_s);\n                    new_s = min((double)tasks[t_idx].d[k] + 20, new_s);\n                    members[m_idx].s[k] = (int)round(new_s);\n                }\n            }\n\n            tasks[t_idx].status = 1;\n            completed_count++;\n            members[m_idx].current_task = -1;\n            members[m_idx].has_active_task = false;\n            members[m_idx].tasks_completed++;\n            active_member_count--;\n\n            // Update Dependencies\n            for (int v : tasks[t_idx].dependents) {\n                tasks[v].in_degree--;\n                if (tasks[v].in_degree == 0) {\n                    ready_tasks.push_back(v);\n                }\n            }\n        }\n        \n        // Safety check: if we're past stop day and have no active tasks, all done\n        if (current_day > STOP_ASSIGN_DAY && active_member_count == 0 && completed_count == N) {\n            // All tasks completed, will receive -1 next iteration\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n};\n\ninline int manhattan(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nconst Point CENTER = {400, 400};\nvector<Order> orders(1000);\nPoint pickups[1000], deliveries[1000];\n\n// Path: sequence of 100 nodes (50 pickups + 50 deliveries)\n// Each node: (order_id, type) where type 0=pickup, 1=delivery\nstruct Node {\n    int order_id;\n    int type; // 0=pickup, 1=delivery\n};\n\nvector<Node> path;\nbool selected[1000];\n\nint calc_cost(const vector<Node>& p) {\n    int cost = 0;\n    Point prev = CENTER;\n    for (const auto& node : p) {\n        Point curr = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cost += manhattan(prev, curr);\n        prev = curr;\n    }\n    cost += manhattan(prev, CENTER);\n    return cost;\n}\n\n// Validate path: each selected order has pickup before delivery\nbool validate_path(const vector<Node>& p, const bool* sel) {\n    int pickup_pos[1000];\n    fill(pickup_pos, pickup_pos + 1000, -1);\n    \n    for (int i = 0; i < 100; ++i) {\n        if (p[i].type == 0) {\n            pickup_pos[p[i].order_id] = i;\n        } else {\n            if (pickup_pos[p[i].order_id] == -1) return false;\n            if (pickup_pos[p[i].order_id] >= i) return false;\n        }\n    }\n    \n    // Check all selected orders are in path\n    for (int i = 0; i < 1000; ++i) {\n        if (sel[i]) {\n            if (pickup_pos[i] == -1) return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read input\n    for (int i = 0; i < 1000; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        pickups[i] = {orders[i].ax, orders[i].ay};\n        deliveries[i] = {orders[i].cx, orders[i].cy};\n    }\n    \n    mt19937 rng(1337);\n    \n    // Initial selection: pick 50 orders with smallest round-trip cost\n    vector<pair<int, int>> scores;\n    scores.reserve(1000);\n    for (int i = 0; i < 1000; ++i) {\n        int score = manhattan(CENTER, pickups[i]) + \n                    manhattan(pickups[i], deliveries[i]) + \n                    manhattan(deliveries[i], CENTER);\n        scores.push_back({score, i});\n    }\n    sort(scores.begin(), scores.end());\n    \n    fill(selected, selected + 1000, false);\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected[scores[i].second] = true;\n        selected_orders.push_back(scores[i].second);\n    }\n    \n    // Initial path: sort by angle from center, pickup then delivery for each\n    vector<pair<double, int>> angled;\n    angled.reserve(50);\n    for (int oid : selected_orders) {\n        int mx = (pickups[oid].x + deliveries[oid].x) / 2;\n        int my = (pickups[oid].y + deliveries[oid].y) / 2;\n        double angle = atan2(my - 400, mx - 400);\n        angled.push_back({angle, oid});\n    }\n    sort(angled.begin(), angled.end());\n    \n    path.clear();\n    path.reserve(100);\n    for (const auto& p : angled) {\n        path.push_back({p.second, 0}); // pickup\n        path.push_back({p.second, 1}); // delivery\n    }\n    \n    int best_cost = calc_cost(path);\n    vector<Node> best_path = path;\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.90;\n    \n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    uniform_int_distribution<int> dist_idx(0, 98);\n    \n    double temp = 5000.0;\n    int iter = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        temp *= 0.99995;\n        if (temp < 0.5) temp = 0.5;\n        \n        // Operation: swap two nodes while maintaining constraints\n        int i = dist_idx(rng);\n        int j = dist_idx(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        \n        // Ensure j > i\n        if (j <= i) { j = i + 1; if (j >= 100) { i = 98; j = 99; } }\n        \n        Node ni = path[i];\n        Node nj = path[j];\n        \n        // Find positions of complementary nodes\n        int ni_comp = -1, nj_comp = -1;\n        for (int k = 0; k < 100; ++k) {\n            if (k == i || k == j) continue;\n            if (path[k].order_id == ni.order_id) ni_comp = k;\n            if (path[k].order_id == nj.order_id) nj_comp = k;\n        }\n        \n        // Check if swap is valid\n        bool valid = true;\n        \n        // After swap: ni goes to position j, nj goes to position i\n        // For ni: if it's pickup (0), need comp (delivery) to be after j\n        //         if it's delivery (1), need comp (pickup) to be before j\n        if (ni.type == 0) { // pickup moving to j\n            if (ni_comp != -1 && ni_comp < j) valid = false;\n        } else { // delivery moving to j\n            if (ni_comp != -1 && ni_comp > j) valid = false;\n        }\n        \n        if (valid && nj.type == 0) { // pickup moving to i\n            if (nj_comp != -1 && nj_comp < i) valid = false;\n        } else if (valid) { // delivery moving to i\n            if (nj_comp != -1 && nj_comp > i) valid = false;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate delta cost (only affected edges)\n        auto get_point = [&](int idx, const vector<Node>& p) -> Point {\n            if (idx < 0 || idx >= 100) return CENTER;\n            if (p[idx].type == 0) return pickups[p[idx].order_id];\n            return deliveries[p[idx].order_id];\n        };\n        \n        int delta = 0;\n        \n        // Edges affected: (i-1,i), (i,i+1), (j-1,j), (j,j+1)\n        // But need to handle adjacency carefully\n        \n        vector<int> affected;\n        if (i > 0) affected.push_back(i - 1);\n        affected.push_back(i);\n        if (i < 99) affected.push_back(i + 1);\n        if (j > 0 && j - 1 != i) affected.push_back(j - 1);\n        if (j < 99 && j != i + 1) affected.push_back(j);\n        if (j < 99) affected.push_back(j + 1);\n        \n        // Remove duplicates and sort\n        sort(affected.begin(), affected.end());\n        affected.erase(unique(affected.begin(), affected.end()), affected.end());\n        \n        // Calculate old cost for affected edges\n        int old_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, path);\n                Point p2 = get_point(k + 1, path);\n                old_cost += manhattan(p1, p2);\n            }\n        }\n        \n        // Create new path (just for these positions)\n        vector<Node> new_path = path;\n        swap(new_path[i], new_path[j]);\n        \n        // Calculate new cost for affected edges\n        int new_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, new_path);\n                Point p2 = get_point(k + 1, new_path);\n                new_cost += manhattan(p1, p2);\n            }\n        }\n        \n        delta = new_cost - old_cost;\n        \n        if (delta < 0 || dist_01(rng) < exp(-delta / temp)) {\n            swap(path[i], path[j]);\n            int cur_cost = calc_cost(path);\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_path = path;\n            }\n        }\n        \n        iter++;\n        if (iter % 10000 == 0) {\n            // Occasionally try a different initialization\n            if (dist_01(rng) < 0.1) {\n                // Shuffle and rebuild\n                shuffle(selected_orders.begin(), selected_orders.end(), rng);\n                path.clear();\n                for (int oid : selected_orders) {\n                    path.push_back({oid, 0});\n                    path.push_back({oid, 1});\n                }\n                int c = calc_cost(path);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_path = path;\n                }\n            }\n        }\n    }\n    \n    // Final validation\n    if (!validate_path(best_path, selected)) {\n        // Rebuild path from selected orders\n        path.clear();\n        for (int i = 0; i < 1000; ++i) {\n            if (selected[i]) {\n                path.push_back({i, 0});\n                path.push_back({i, 1});\n            }\n        }\n        best_path = path;\n        best_cost = calc_cost(best_path);\n    }\n    \n    // Output\n    cout << 50;\n    for (int i = 0; i < 1000; ++i) {\n        if (selected[i]) cout << \" \" << (i + 1);\n    }\n    cout << \"\\n\";\n    \n    cout << 102;\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    for (const auto& node : best_path) {\n        Point p = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Disjoint Set Union with path compression and union by rank\nstruct DSU {\n    vector<int> parent, rank_, size_;\n    int components;\n    \n    DSU(int n) : parent(n), rank_(n, 0), size_(n, 1), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    \n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        size_[x] += size_[y];\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        components--;\n        return true;\n    }\n    \n    int getSize(int x) {\n        return size_[find(x)];\n    }\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    // Read vertex coordinates\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    // Read edge endpoints and precompute expected distances\n    vector<pair<int, int>> edges(M);\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n        int u = edges[i].first, v = edges[i].second;\n        double dist = hypot(coords[u].first - coords[v].first, \n                           coords[u].second - coords[v].second);\n        d[i] = (int)round(dist);\n    }\n    \n    DSU dsu(N);\n    \n    // Process each edge online\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first, v = edges[i].second;\n        int remaining = M - 1 - i;  // Edges after this one (including current = remaining + 1)\n        int needed = dsu.components - 1;  // Minimum edges needed for connectivity\n        \n        bool connects = (dsu.find(u) != dsu.find(v));\n        bool accept = false;\n        \n        if (connects) {\n            // Edge quality ratio (actual length / minimum possible length)\n            double ratio = (double)l / max(1, d[i]);\n            \n            // Connectivity urgency: how critical is it to accept connecting edges?\n            // Use remaining + 1 to include current edge in available count\n            int available = remaining + 1;\n            double urgency = (double)needed / max(1, available);\n            \n            // Progress through the edge stream (0.0 to 1.0)\n            double progress = (double)i / (M - 1);\n            \n            // Base threshold: expected value is 2.0, max is 3.0\n            // We want to accept edges with ratio <= threshold\n            double threshold = 2.3;\n            \n            // Phase 1: Early phase (first 30%) - be selective but not too aggressive\n            if (progress < 0.3) {\n                threshold = 2.0 + urgency * 0.5;\n            }\n            // Phase 2: Middle phase (30-60%) - moderate selectivity\n            else if (progress < 0.6) {\n                threshold = 2.2 + urgency * 0.6;\n            }\n            // Phase 3: Late phase (60-80%) - prioritize connectivity\n            else if (progress < 0.8) {\n                threshold = 2.5 + urgency * 0.5;\n            }\n            // Phase 4: Critical phase (80%+) - very aggressive on connectivity\n            else {\n                threshold = 2.8 + urgency * 0.2;\n            }\n            \n            // Safety mechanism 1: Large buffer when running low on edges\n            // With M=1995 and N=400, we need 399 edges minimum\n            // But many edges will be redundant, so we need significant buffer\n            int safety_margin = 80;\n            if (available <= needed + safety_margin) {\n                threshold = 3.0;  // Accept any connecting edge\n            }\n            \n            // Safety mechanism 2: Critical zone - must accept all connecting edges\n            if (available <= needed + 30) {\n                accept = true;\n            }\n            // Safety mechanism 3: Very urgent - almost always accept\n            else if (urgency > 0.6) {\n                threshold = 3.0;\n            }\n            // Safety mechanism 4: Moderate urgency\n            else if (urgency > 0.4) {\n                threshold = max(threshold, 2.7);\n            }\n            \n            // Apply threshold if not already forced to accept\n            if (!accept && ratio <= threshold) {\n                accept = true;\n            }\n            \n            // Component size bonus: prefer edges connecting larger components\n            // This helps reduce components faster\n            if (!accept && connects) {\n                int combined_size = dsu.getSize(u) + dsu.getSize(v);\n                if (combined_size > N / 2 && ratio <= threshold + 0.3) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept && connects) {\n            dsu.unite(u, v);\n            cout << 1 << \"\\n\";\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        cout.flush();  // Ensure output is sent immediately\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nclass Solver {\nprivate:\n    int N, M;\n    vector<Position> petPos;\n    vector<int> petType;\n    vector<Position> humanPos;\n    vector<vector<bool>> impassable;\n    vector<vector<bool>> humanTarget;\n    \n    bool isValid(int x, int y) const {\n        return x >= 1 && x <= GRID_SIZE && y >= 1 && y <= GRID_SIZE;\n    }\n    \n    bool isPassable(int x, int y) const {\n        if (!isValid(x, y)) return false;\n        return !impassable[x-1][y-1];\n    }\n    \n    bool hasPetAdjacent(int x, int y) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (const auto& pet : petPos) {\n                    if (pet.x == nx && pet.y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    bool hasHumanAdjacent(int x, int y, int excludeIdx = -1) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (int i = 0; i < M; i++) {\n                    if (i == excludeIdx) continue;\n                    if (humanPos[i].x == nx && humanPos[i].y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    vector<vector<bool>> computeReachable(const Position& start) const {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        queue<Position> q;\n        \n        if (isPassable(start.x, start.y)) {\n            visited[start.x-1][start.y-1] = true;\n            q.push(start);\n        }\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        \n        while (!q.empty()) {\n            Position cur = q.front();\n            q.pop();\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = cur.x + dx[d], ny = cur.y + dy[d];\n                if (isPassable(nx, ny) && !visited[nx-1][ny-1]) {\n                    visited[nx-1][ny-1] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        \n        return visited;\n    }\n    \n    int countPetsInRegion(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (const auto& pet : petPos) {\n            if (region[pet.x-1][pet.y-1]) {\n                count++;\n            }\n        }\n        return count;\n    }\n    \n    int countReachable(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (region[i][j]) count++;\n            }\n        }\n        return count;\n    }\n    \n    // Calculate minimum distance from position to any pet\n    int minPetDistance(int x, int y) const {\n        int minDist = 1000;\n        for (const auto& pet : petPos) {\n            int dist = abs(pet.x - x) + abs(pet.y - y);\n            minDist = min(minDist, dist);\n        }\n        return minDist;\n    }\n    \n    // Check if blocking this square would help create a partition\n    double evaluateBlockScore(int x, int y, int humanIdx) const {\n        double score = 0;\n        \n        // Base score for blocking\n        score += 100;\n        \n        // Bonus for being far from pets (safer)\n        int petDist = minPetDistance(x, y);\n        score += petDist * 5;\n        \n        // Bonus for continuing existing walls\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int wallCount = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny) && impassable[nx-1][ny-1]) {\n                wallCount++;\n            }\n        }\n        score += wallCount * 20;\n        \n        // Prefer edges and corners for better partitioning\n        if (x == 1 || x == GRID_SIZE || y == 1 || y == GRID_SIZE) {\n            score += 15;\n        }\n        if ((x == 1 || x == GRID_SIZE) && (y == 1 || y == GRID_SIZE)) {\n            score += 10;\n        }\n        \n        // Penalize if too close to this human (want to expand)\n        int humanDist = abs(x - humanPos[humanIdx].x) + abs(y - humanPos[humanIdx].y);\n        if (humanDist < 3) {\n            score -= (3 - humanDist) * 10;\n        }\n        \n        return score;\n    }\n    \n    // Evaluate move score\n    double evaluateMoveScore(int newX, int newY, int humanIdx) const {\n        double score = 0;\n        \n        // Count potential blocking opportunities from new position\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int blockOptions = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = newX + dx[d], ny = newY + dy[d];\n            if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !hasPetAdjacent(nx, ny)) {\n                blockOptions++;\n            }\n        }\n        score += blockOptions * 30;\n        \n        // Distance from pets\n        int petDist = minPetDistance(newX, newY);\n        score += petDist * 3;\n        \n        // Spread humans out\n        for (int i = 0; i < M; i++) {\n            if (i == humanIdx) continue;\n            int dist = abs(newX - humanPos[i].x) + abs(newY - humanPos[i].y);\n            if (dist < 5) {\n                score -= (5 - dist) * 5;\n            }\n        }\n        \n        return score;\n    }\n    \npublic:\n    void readInput() {\n        cin >> N;\n        petPos.resize(N);\n        petType.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petPos[i].x >> petPos[i].y >> petType[i];\n        }\n        \n        cin >> M;\n        humanPos.resize(M);\n        for (int i = 0; i < M; i++) {\n            cin >> humanPos[i].x >> humanPos[i].y;\n        }\n        \n        impassable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        humanTarget.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    }\n    \n    void readPetMoves() {\n        for (int i = 0; i < N; i++) {\n            string move;\n            cin >> move;\n            if (move != \".\") {\n                int x = petPos[i].x, y = petPos[i].y;\n                for (char c : move) {\n                    int nx = x, ny = y;\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    \n                    if (isValid(nx, ny) && isPassable(nx, ny)) {\n                        x = nx;\n                        y = ny;\n                    }\n                }\n                petPos[i] = {x, y};\n            }\n        }\n    }\n    \n    string decideActions(int turn) {\n        string actions(M, '.');\n        \n        // Track which squares will be blocked this turn (to avoid conflicts)\n        vector<vector<bool>> willBlock(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        char blockChars[] = {'u', 'd', 'l', 'r'};\n        char moveChars[] = {'U', 'D', 'L', 'R'};\n        \n        // First pass: identify best blocking opportunities\n        vector<pair<double, int>> humanScores(M);\n        for (int i = 0; i < M; i++) {\n            int x = humanPos[i].x, y = humanPos[i].y;\n            double bestScore = -1e18;\n            int bestD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1]) {\n                    if (!hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                        double score = evaluateBlockScore(nx, ny, i);\n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestD = d;\n                        }\n                    }\n                }\n            }\n            \n            humanScores[i] = {bestScore, bestD};\n        }\n        \n        // Second pass: execute actions (prioritize high-score humans)\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return humanScores[a].first > humanScores[b].first;\n        });\n        \n        for (int idx : order) {\n            int i = idx;\n            int x = humanPos[i].x, y = humanPos[i].y;\n            int bestD = humanScores[i].second;\n            \n            if (bestD >= 0) {\n                int nx = x + dx[bestD], ny = y + dy[bestD];\n                // Double check it's still available\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1] &&\n                    !hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                    actions[i] = blockChars[bestD];\n                    impassable[nx-1][ny-1] = true;\n                    willBlock[nx-1][ny-1] = true;\n                    continue;\n                }\n            }\n            \n            // Try to move to better position\n            double bestMoveScore = -1e18;\n            int bestMoveD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && isPassable(nx, ny)) {\n                    // Check if this square won't be blocked by others\n                    bool willBeBlocked = false;\n                    for (int j = 0; j < M; j++) {\n                        if (j == i) continue;\n                        int jd = humanScores[j].second;\n                        if (jd >= 0) {\n                            int tx = humanPos[j].x + dx[jd], ty = humanPos[j].y + dy[jd];\n                            if (tx == nx && ty == ny) {\n                                willBeBlocked = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (!willBeBlocked) {\n                        double score = evaluateMoveScore(nx, ny, i);\n                        if (score > bestMoveScore) {\n                            bestMoveScore = score;\n                            bestMoveD = d;\n                        }\n                    }\n                }\n            }\n            \n            if (bestMoveD >= 0 && bestMoveScore > 0) {\n                actions[i] = moveChars[bestMoveD];\n                humanPos[i].x += dx[bestMoveD];\n                humanPos[i].y += dy[bestMoveD];\n            }\n        }\n        \n        return actions;\n    }\n    \n    void solve() {\n        readInput();\n        \n        for (int turn = 0; turn < MAX_TURNS; turn++) {\n            string actions = decideActions(turn);\n            cout << actions << endl;\n            \n            if (turn < MAX_TURNS - 1) {\n                readPetMoves();\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}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int GRID_SIZE = 20;\nconst int MAX_STEPS = 200;\n\nstruct Problem {\n    int si, sj, ti, tj;\n    double p;\n    vector<string> h;\n    vector<string> v;\n};\n\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dirChar[4] = {'U', 'D', 'L', 'R'};\n\ninline bool canMove(const Problem& prob, int i, int j, int dir) {\n    int ni = i + di[dir];\n    int nj = j + dj[dir];\n    \n    if (ni < 0 || ni >= GRID_SIZE || nj < 0 || nj >= GRID_SIZE) return false;\n    \n    if (dir == 0) {\n        if (prob.v[ni][j] == '1') return false;\n    } else if (dir == 1) {\n        if (prob.v[i][j] == '1') return false;\n    } else if (dir == 2) {\n        if (prob.h[i][nj] == '1') return false;\n    } else {\n        if (prob.h[i][j] == '1') return false;\n    }\n    return true;\n}\n\n// Fast DP-based expected score evaluation\ndouble evaluatePathDP(const Problem& prob, const string& path) {\n    int L = path.size();\n    \n    // V[i][j] = probability of being at position (i,j)\n    vector<vector<double>> prob_grid(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    prob_grid[prob.si][prob.sj] = 1.0;\n    \n    double expectedScore = 0.0;\n    double arrivedProb = 0.0;\n    \n    for (int t = 0; t < L; t++) {\n        int dir;\n        if (path[t] == 'U') dir = 0;\n        else if (path[t] == 'D') dir = 1;\n        else if (path[t] == 'L') dir = 2;\n        else dir = 3;\n        \n        vector<vector<double>> next_prob(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n        \n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (prob_grid[i][j] < 1e-12) continue;\n                \n                // If already at target, stay there\n                if (i == prob.ti && j == prob.tj) {\n                    next_prob[i][j] += prob_grid[i][j];\n                    continue;\n                }\n                \n                // Probability p: forget, stay in place\n                next_prob[i][j] += prob.p * prob_grid[i][j];\n                \n                // Probability 1-p: try to move\n                if (canMove(prob, i, j, dir)) {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    next_prob[ni][nj] += (1.0 - prob.p) * prob_grid[i][j];\n                } else {\n                    next_prob[i][j] += (1.0 - prob.p) * prob_grid[i][j];\n                }\n            }\n        }\n        \n        // Add score for new arrivals at this step\n        double newProb = next_prob[prob.ti][prob.tj] - arrivedProb;\n        if (newProb > 0) {\n            expectedScore += newProb * (401.0 - (t + 1));\n        }\n        arrivedProb = next_prob[prob.ti][prob.tj];\n        \n        prob_grid = next_prob;\n    }\n    \n    return expectedScore;\n}\n\nstring bfsPath(const Problem& prob) {\n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n    vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    vector<pair<int, int>> queue;\n    queue.reserve(400);\n    \n    queue.push_back({prob.si, prob.sj});\n    visited[prob.si][prob.sj] = true;\n    \n    int head = 0;\n    while (head < (int)queue.size()) {\n        auto [ci, cj] = queue[head++];\n        if (ci == prob.ti && cj == prob.tj) break;\n        \n        vector<int> dirs = {0, 1, 2, 3};\n        sort(dirs.begin(), dirs.end(), [&](int a, int b) {\n            int nai = ci + di[a], naj = cj + dj[a];\n            int nbi = ci + di[b], nbj = cj + dj[b];\n            return abs(nai - prob.ti) + abs(naj - prob.tj) < \n                   abs(nbi - prob.ti) + abs(nbj - prob.tj);\n        });\n        \n        for (int dir : dirs) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {ci, cj};\n                    parentDir[ni][nj] = dir;\n                    queue.push_back({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (!visited[prob.ti][prob.tj]) return \"\";\n    \n    string path = \"\";\n    int ci = prob.ti, cj = prob.tj;\n    while (ci != prob.si || cj != prob.sj) {\n        int dir = parentDir[ci][cj];\n        path += dirChar[dir];\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    return path;\n}\n\nstring dpPath(const Problem& prob, int pathLen) {\n    vector<vector<double>> V_cur(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    vector<vector<double>> V_next(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    \n    // DP with 2 layers - backward from target\n    for (int k = 1; k <= pathLen; k++) {\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (i == prob.ti && j == prob.tj) {\n                    V_next[i][j] = 401.0 - (pathLen - k);\n                    continue;\n                }\n                \n                double bestVal = 0.0;\n                for (int dir = 0; dir < 4; dir++) {\n                    double val = prob.p * V_cur[i][j];\n                    \n                    if (canMove(prob, i, j, dir)) {\n                        val += (1.0 - prob.p) * V_cur[i + di[dir]][j + dj[dir]];\n                    } else {\n                        val += (1.0 - prob.p) * V_cur[i][j];\n                    }\n                    \n                    if (val > bestVal) bestVal = val;\n                }\n                V_next[i][j] = bestVal;\n            }\n        }\n        swap(V_cur, V_next);\n    }\n    \n    // Construct path greedily following DP policy\n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    \n    for (int k = pathLen; k > 0 && (ci != prob.ti || cj != prob.tj); k--) {\n        int bestDir = 1;\n        double bestVal = -1e18;\n        \n        // FIXED: Use ci, cj instead of i, j\n        for (int dir = 0; dir < 4; dir++) {\n            double val = prob.p * V_cur[ci][cj];\n            if (canMove(prob, ci, cj, dir)) {\n                val += (1.0 - prob.p) * V_cur[ci + di[dir]][cj + dj[dir]];\n            } else {\n                val += (1.0 - prob.p) * V_cur[ci][cj];\n            }\n            \n            if (val > bestVal) {\n                bestVal = val;\n                bestDir = dir;\n            }\n        }\n        \n        path += dirChar[bestDir];\n        if (canMove(prob, ci, cj, bestDir)) {\n            ci += di[bestDir];\n            cj += dj[bestDir];\n        }\n    }\n    \n    while ((int)path.size() < pathLen) path += 'R';\n    \n    return path;\n}\n\nstring directPath(const Problem& prob, int maxLen) {\n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    \n    while ((int)path.size() < maxLen && (ci != prob.ti || cj != prob.tj)) {\n        int bestDir = -1;\n        int bestDist = 1e9;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                int dist = abs(ni - prob.ti) + abs(nj - prob.tj);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestDir = dir;\n                }\n            }\n        }\n        \n        if (bestDir == -1) break;\n        \n        path += dirChar[bestDir];\n        ci += di[bestDir];\n        cj += dj[bestDir];\n    }\n    \n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Problem prob;\n    cin >> prob.si >> prob.sj >> prob.ti >> prob.tj >> prob.p;\n    \n    prob.h.resize(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; i++) cin >> prob.h[i];\n    \n    prob.v.resize(GRID_SIZE - 1);\n    for (int i = 0; i < GRID_SIZE - 1; i++) cin >> prob.v[i];\n    \n    string bestPath = \"\";\n    double bestScore = 0.0;\n    \n    // Strategy 1: BFS shortest path (fast, reliable)\n    string bfs = bfsPath(prob);\n    if (!bfs.empty()) {\n        for (int extra = 0; extra <= 30; extra += 10) {\n            string padded = bfs;\n            while ((int)padded.size() < (int)bfs.size() + extra && (int)padded.size() < MAX_STEPS) {\n                padded += 'R';\n            }\n            if ((int)padded.size() <= MAX_STEPS) {\n                double score = evaluatePathDP(prob, padded);\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestPath = padded;\n                }\n            }\n        }\n    }\n    \n    // Strategy 2: Direct greedy path\n    string direct = directPath(prob, MAX_STEPS);\n    if (!direct.empty()) {\n        double score = evaluatePathDP(prob, direct);\n        if (score > bestScore) {\n            bestScore = score;\n            bestPath = direct;\n        }\n    }\n    \n    // Strategy 3: DP-based paths (limited lengths)\n    for (int pathLen = 40; pathLen <= 150; pathLen += 20) {\n        string path = dpPath(prob, pathLen);\n        if ((int)path.size() <= MAX_STEPS) {\n            double score = evaluatePathDP(prob, path);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = path;\n            }\n        }\n    }\n    \n    // Strategy 4: Simple fallback\n    if (bestPath.empty()) {\n        bestPath = \"\";\n        int ci = prob.si, cj = prob.sj;\n        while ((int)bestPath.size() < MAX_STEPS) {\n            if (ci < prob.ti && canMove(prob, ci, cj, 1)) {\n                bestPath += 'D';\n                ci++;\n            } else if (cj < prob.tj && canMove(prob, ci, cj, 3)) {\n                bestPath += 'R';\n                cj++;\n            } else {\n                break;\n            }\n            if (ci == prob.ti && cj == prob.tj) break;\n        }\n    }\n    \n    // Ensure valid output\n    if ((int)bestPath.size() > MAX_STEPS) {\n        bestPath = bestPath.substr(0, MAX_STEPS);\n    }\n    if (bestPath.empty()) {\n        bestPath = \"R\";\n    }\n    \n    cout << bestPath << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entering_direction] = exiting_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0: curve\n    {3, -1, -1, 0},  // 1: curve\n    {-1, -1, 3, 2},  // 2: curve\n    {-1, 2, 1, -1},  // 3: curve\n    {1, 0, 3, 2},    // 4: double curve\n    {3, 2, 1, 0},    // 5: double curve\n    {2, -1, 0, -1},  // 6: straight\n    {-1, 3, -1, 1},  // 7: straight\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint grid[N][N];\nint rot[N][N];\n\ninline int rotate_tile(int t, int r) {\n    if (t <= 3) return (t + r) % 4;\n    else if (t <= 5) return 4 + ((t - 4 + r) % 2);\n    else return 6 + ((t - 6 + r) % 2);\n}\n\ninline int get_tile(int i, int j) {\n    return rotate_tile(grid[i][j], rot[i][j]);\n}\n\n// Fast loop tracing with step limit\nint trace_loop(int si, int sj, int sd, int max_steps = 500) {\n    int i = si, j = sj, d = sd;\n    for (int len = 1; len <= max_steps; len++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 == -1) return 0;\n        i += di[d2];\n        j += dj[d2];\n        d = (d2 + 2) % 4;\n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        if (i == si && j == sj && d == sd) return len;\n    }\n    return 0;\n}\n\n// Sample-based loop detection (faster than full scan)\npair<long long, long long> sample_loops(mt19937& rng, int samples = 200) {\n    vector<int> loops;\n    \n    for (int s = 0; s < samples; s++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        int d = rng() % 4;\n        \n        int len = trace_loop(i, j, d, 600);\n        if (len > 1) {\n            loops.push_back(len);\n        }\n    }\n    \n    // Also check strategic points (edges, corners)\n    for (int i = 0; i < N; i += 5) {\n        for (int j = 0; j < N; j += 5) {\n            for (int d = 0; d < 4; d++) {\n                int len = trace_loop(i, j, d, 600);\n                if (len > 1) loops.push_back(len);\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    // Get unique top 2\n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Full scan for final evaluation\npair<long long, long long> full_scan_loops() {\n    vector<int> loops;\n    static bool vis[N][N][4];\n    memset(vis, 0, sizeof(vis));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                if (vis[i][j][d]) continue;\n                \n                vector<tuple<int,int,int>> path;\n                int ci = i, cj = j, cd = d;\n                \n                while (ci >= 0 && ci < N && cj >= 0 && cj < N && !vis[ci][cj][cd]) {\n                    vis[ci][cj][cd] = true;\n                    path.push_back({ci, cj, cd});\n                    \n                    int t = get_tile(ci, cj);\n                    int d2 = to[t][cd];\n                    if (d2 == -1) break;\n                    \n                    ci += di[d2];\n                    cj += dj[d2];\n                    cd = (d2 + 2) % 4;\n                }\n                \n                if (ci >= 0 && ci < N && cj >= 0 && cj < N) {\n                    for (int k = 0; k < (int)path.size(); k++) {\n                        if (get<0>(path[k]) == ci && \n                            get<1>(path[k]) == cj && \n                            get<2>(path[k]) == cd) {\n                            int loop_len = path.size() - k;\n                            if (loop_len > 1) {\n                                loops.push_back(loop_len);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Evaluate connectivity score for a tile (heuristic)\nint connectivity_score(int i, int j, int r) {\n    int score = 0;\n    int old_rot = rot[i][j];\n    rot[i][j] = r;\n    \n    // Check all 4 directions\n    for (int d = 0; d < 4; d++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 != -1) {\n            int ni = i + di[d2];\n            int nj = j + dj[d2];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nt = get_tile(ni, nj);\n                int back_d = (d2 + 2) % 4;\n                if (to[nt][back_d] != -1) {\n                    score += 10;\n                }\n            }\n        }\n    }\n    \n    rot[i][j] = old_rot;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Multiple restarts with different seeds\n    long long global_best = 0;\n    int best_rot[N][N];\n    memset(best_rot, 0, sizeof(best_rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    int restart = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Leave 150ms for final output\n        if (elapsed >= 1850) break;\n        \n        // Initialize rotations\n        memset(rot, 0, sizeof(rot));\n        \n        // Smart initialization: try to create connections\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int best_r = 0;\n                int best_score = -1;\n                for (int r = 0; r < 4; r++) {\n                    int score = connectivity_score(i, j, r);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n        \n        // Add some randomness to initial configuration\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (rng() % 3 == 0) {\n                    rot[i][j] = rng() % 4;\n                }\n            }\n        }\n        \n        // Get initial score\n        auto [l1, l2] = sample_loops(rng, 100);\n        long long current_score = l1 * l2;\n        long long local_best = current_score;\n        \n        // Simulated annealing with adaptive temperature\n        double temp = 500.0;\n        int iterations = 0;\n        int no_improve = 0;\n        \n        while (elapsed < 1850) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1850) break;\n            \n            // Adaptive temperature based on time remaining\n            double time_ratio = (1850.0 - elapsed) / 1850.0;\n            temp = 500.0 * pow(time_ratio, 2.0) + 1.0;\n            \n            // Number of tiles to change (increases with temperature)\n            int num_changes = 1 + (int)(3.0 * temp / 500.0);\n            num_changes = min(num_changes, 5);\n            \n            vector<pair<int,int>> changes;\n            vector<int> old_rots;\n            \n            for (int c = 0; c < num_changes; c++) {\n                int i = rng() % N;\n                int j = rng() % N;\n                changes.push_back({i, j});\n                old_rots.push_back(rot[i][j]);\n                rot[i][j] = (old_rots.back() + 1 + rng() % 3) % 4;\n            }\n            \n            auto [nl1, nl2] = sample_loops(rng, 80);\n            long long new_score = nl1 * nl2;\n            \n            bool accept = false;\n            if (new_score >= current_score) {\n                accept = true;\n                if (new_score > local_best) {\n                    local_best = new_score;\n                    no_improve = 0;\n                    memcpy(best_rot, rot, sizeof(rot));\n                }\n            } else if (temp > 0.5) {\n                double prob = exp((double)(new_score - current_score) / temp);\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (!accept) {\n                for (int c = 0; c < num_changes; c++) {\n                    rot[changes[c].first][changes[c].second] = old_rots[c];\n                }\n            } else {\n                current_score = new_score;\n            }\n            \n            iterations++;\n            no_improve++;\n            \n            // Restart if stuck\n            if (no_improve > 5000 && restart < 3) {\n                break;\n            }\n        }\n        \n        if (local_best > global_best) {\n            global_best = local_best;\n        }\n        \n        restart++;\n    }\n    \n    // Restore best configuration\n    memcpy(rot, best_rot, sizeof(rot));\n    \n    // Final full evaluation\n    auto [fl1, fl2] = full_scan_loops();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << rot[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int LEFT = 1, UP = 2, RIGHT = 4, DOWN = 8;\n// When we output 'U', empty square moves UP (tile above slides down)\nconst int dr[4] = {-1, 1, 0, 0};  // U, D, L, R - empty square movement\nconst int dc[4] = {0, 0, -1, 1};\nconst char dirs[4] = {'U', 'D', 'L', 'R'};\n\nint N;\nlong long T;\nvector<vector<int>> board;\nint emptyR, emptyC;\nstring operations;\nmt19937 rng(42);\n\n// Check if two adjacent cells have matching connections\ninline bool connects(int r1, int c1, int r2, int c2) {\n    if (board[r1][c1] == 0 || board[r2][c2] == 0) return false;\n    if (r2 == r1 + 1) return (board[r1][c1] & DOWN) && (board[r2][c2] & UP);\n    if (r2 == r1 - 1) return (board[r1][c1] & UP) && (board[r2][c2] & DOWN);\n    if (c2 == c1 + 1) return (board[r1][c1] & RIGHT) && (board[r2][c2] & LEFT);\n    if (c2 == c1 - 1) return (board[r1][c1] & LEFT) && (board[r2][c2] & RIGHT);\n    return false;\n}\n\n// Compute size of largest connected tree\nint computeMaxTree() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int maxTree = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] != 0 && !visited[i][j]) {\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                \n                while (!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    size++;\n                    \n                    for (int d = 0; d < 4; d++) {\n                        int nr = r + dr[d], nc = c + dc[d];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                            board[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                maxTree = max(maxTree, size);\n            }\n        }\n    }\n    return maxTree;\n}\n\n// Count matching edge pairs\nint countEdges() {\n    int count = 0;\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            if (connects(i, j, i + 1, j)) count++;\n        }\n    }\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N - 1; j++) {\n            if (connects(i, j, i, j + 1)) count++;\n        }\n    }\n    return count;\n}\n\ndouble evaluate() {\n    int treeSize = computeMaxTree();\n    int edges = countEdges();\n    double score = treeSize * 100.0 + edges * 10.0;\n    if (treeSize == N * N - 1) score += 100000.0;\n    return score;\n}\n\n// Execute a move: output direction D means empty square moves in direction D\nbool executeMove(int dir) {\n    int nr = emptyR + dr[dir];\n    int nc = emptyC + dc[dir];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n    if (board[nr][nc] == 0) return false;\n    if (operations.size() >= (size_t)T) return false;\n    \n    board[emptyR][emptyC] = board[nr][nc];\n    board[nr][nc] = 0;\n    emptyR = nr;\n    emptyC = nc;\n    operations += dirs[dir];\n    return true;\n}\n\n// BFS to get path for empty square to reach target position\nstring getEmptyPath(int targetR, int targetC) {\n    if (emptyR == targetR && emptyC == targetC) return \"\";\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<int>> dirUsed(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({emptyR, emptyC});\n    visited[emptyR][emptyC] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        \n        if (r == targetR && c == targetC) {\n            string path;\n            int cr = r, cc = c;\n            while (parent[cr][cc].first != -1) {\n                path += dirs[dirUsed[cr][cc]];\n                int pr = parent[cr][cc].first;\n                int pc = parent[cr][cc].second;\n                cr = pr; cc = pc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                dirUsed[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\";\n}\n\n// Get all valid moves (direction for empty square to move)\nvector<int> getValidMoves() {\n    vector<int> moves;\n    for (int d = 0; d < 4; d++) {\n        int nr = emptyR + dr[d];\n        int nc = emptyC + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N && board[nr][nc] != 0) {\n            moves.push_back(d);\n        }\n    }\n    return moves;\n}\n\n// Save and restore board state\nstruct BoardState {\n    vector<vector<int>> board;\n    int emptyR, emptyC;\n    string ops;\n    \n    void save() {\n        board = ::board;\n        emptyR = ::emptyR;\n        emptyC = ::emptyC;\n        ops = operations;\n    }\n    \n    void restore() {\n        ::board = board;\n        ::emptyR = emptyR;\n        ::emptyC = emptyC;\n        operations = ops;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> T;\n    \n    board.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') {\n                board[i][j] = c - '0';\n            } else {\n                board[i][j] = c - 'a' + 10;\n            }\n            if (board[i][j] == 0) {\n                emptyR = i;\n                emptyC = j;\n            }\n        }\n    }\n    \n    BoardState bestState;\n    bestState.save();\n    int bestTreeSize = computeMaxTree();\n    double bestScore = evaluate();\n    \n    auto startSearchTime = chrono::steady_clock::now();\n    \n    // Simulated annealing with multiple phases\n    double temperature = 100.0;\n    int noImprovement = 0;\n    int iter = 0;\n    \n    while (operations.size() < (size_t)T) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        \n        // Reserve time buffer\n        if (elapsed > 2800) break;\n        \n        int currentTreeSize = computeMaxTree();\n        if (currentTreeSize == N * N - 1) {\n            bestTreeSize = currentTreeSize;\n            bestState.save();\n            break;\n        }\n        \n        vector<int> moves = getValidMoves();\n        if (moves.empty()) break;\n        \n        // Evaluate each move\n        vector<pair<double, int>> moveScores;\n        for (int d : moves) {\n            // Save state\n            auto savedBoard = board;\n            int savedER = emptyR, savedEC = emptyC;\n            auto savedOps = operations;\n            \n            // Make move\n            executeMove(d);\n            double score = evaluate();\n            moveScores.push_back({score, d});\n            \n            // Restore state\n            board = savedBoard;\n            emptyR = savedER;\n            emptyC = savedEC;\n            operations = savedOps;\n        }\n        \n        // Sort by score\n        sort(moveScores.begin(), moveScores.end(), [](auto& a, auto& b) {\n            return a.first > b.first;\n        });\n        \n        // Select move using simulated annealing\n        int selectedDir = moveScores[0].second;\n        double currentScore = bestScore;\n        \n        for (int i = 0; i < min((int)moveScores.size(), 10); i++) {\n            double delta = moveScores[i].first - currentScore;\n            if (delta >= 0) {\n                selectedDir = moveScores[i].second;\n                break;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                double prob = exp(delta / temperature);\n                if (dist(rng) < prob) {\n                    selectedDir = moveScores[i].second;\n                    break;\n                }\n            }\n        }\n        \n        // Execute selected move\n        executeMove(selectedDir);\n        double newScore = evaluate();\n        \n        if (newScore > bestScore) {\n            bestScore = newScore;\n            bestTreeSize = computeMaxTree();\n            bestState.save();\n            noImprovement = 0;\n        } else {\n            noImprovement++;\n        }\n        \n        // Adaptive temperature\n        iter++;\n        if (iter % 100 == 0) {\n            temperature *= 0.95;\n        }\n        if (noImprovement > 500) {\n            temperature *= 0.8;\n            noImprovement = 0;\n        }\n        \n        // Check remaining time for aggressive cooling\n        elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 2500) {\n            temperature *= 0.9;\n        }\n    }\n    \n    // Restore best state and output\n    bestState.restore();\n    cout << bestState.ops << endl;\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n\nusing namespace std;\n\nstruct Strawberry {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n    \n    long long side(long long x, long long y) const {\n        return (qx - px) * (y - py) - (qy - py) * (x - px);\n    }\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> cuts;\nmt19937 rng(42);\n\n// Check if line passes through any strawberry\nbool lineHitsStrawberry(const Line& line) {\n    for (int i = 0; i < N; i++) {\n        if (line.side(strawberries[i].x, strawberries[i].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Count strawberries on each side\nvoid countSides(const Line& line, const vector<int>& region, int& pos, int& neg) {\n    pos = neg = 0;\n    for (int idx : region) {\n        long long s = line.side(strawberries[idx].x, strawberries[idx].y);\n        if (s > 0) pos++;\n        else if (s < 0) neg++;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Start with all strawberries in one region\n    vector<vector<int>> regions;\n    vector<int> initial(N);\n    for (int i = 0; i < N; i++) initial[i] = i;\n    regions.push_back(initial);\n    \n    // Greedy: add cuts one by one\n    for (int cutNum = 0; cutNum < K; cutNum++) {\n        Line bestLine;\n        int bestScore = -1;\n        int bestRegionIdx = -1;\n        int bestPos = 0, bestNeg = 0;\n        \n        // Limit search time per cut\n        int maxCandidates = 50;\n        \n        for (size_t r = 0; r < regions.size() && regions[r].size() > 1; r++) {\n            const auto& region = regions[r];\n            \n            // Generate candidate lines\n            for (int trial = 0; trial < maxCandidates; trial++) {\n                Line line;\n                \n                if (trial < 20 && region.size() >= 2) {\n                    // Line through two random strawberries in region\n                    int i1 = rng() % region.size();\n                    int i2 = rng() % region.size();\n                    if (i1 == i2) i2 = (i2 + 1) % region.size();\n                    \n                    const auto& s1 = strawberries[region[i1]];\n                    const auto& s2 = strawberries[region[i2]];\n                    \n                    // Perpendicular offset\n                    long long dx = s2.x - s1.x;\n                    long long dy = s2.y - s1.y;\n                    int offset = (rng() % 5) - 2;\n                    if (offset == 0) offset = 1;\n                    \n                    line = {s1.x - dy * offset, s1.y + dx * offset,\n                           s2.x - dy * offset, s2.y + dx * offset};\n                } else {\n                    // Random angle line\n                    double angle = rng() % 360 * 3.14159265359 / 180.0;\n                    long long offset = (rng() % 20001) - 10000;\n                    long long px = (long long)(offset * cos(angle));\n                    long long py = (long long)(offset * sin(angle));\n                    long long dx = (long long)(cos(angle) * 20000);\n                    long long dy = (long long)(sin(angle) * 20000);\n                    line = {px, py, px - dy, py + dx};\n                }\n                \n                // Quick safety check (sample a few strawberries)\n                bool safe = true;\n                for (int check = 0; check < min(20, N); check++) {\n                    int idx = rng() % N;\n                    if (line.side(strawberries[idx].x, strawberries[idx].y) == 0) {\n                        safe = false;\n                        break;\n                    }\n                }\n                if (!safe) continue;\n                \n                // Full safety check\n                if (lineHitsStrawberry(line)) continue;\n                \n                int pos, neg;\n                countSides(line, region, pos, neg);\n                \n                if (pos == 0 || neg == 0) continue;  // Doesn't split\n                \n                // Score: prefer splits that create useful piece sizes\n                int score = 0;\n                for (int d = 1; d <= 10; d++) {\n                    if (a[d] > 0) {\n                        if (pos == d) score += 1000;\n                        if (neg == d) score += 1000;\n                    }\n                }\n                // Bonus for balanced splits (more regions)\n                score += min(pos, neg) * 10;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestLine = line;\n                    bestRegionIdx = r;\n                    bestPos = pos;\n                    bestNeg = neg;\n                }\n            }\n            \n            // Early exit if we found a good cut\n            if (bestScore >= 1000) break;\n        }\n        \n        // If no good cut found, stop\n        if (bestScore < 0) break;\n        \n        // Apply the cut\n        cuts.push_back(bestLine);\n        \n        // Update regions\n        vector<vector<int>> newRegions;\n        for (size_t r = 0; r < regions.size(); r++) {\n            if ((int)r != bestRegionIdx) {\n                newRegions.push_back(regions[r]);\n                continue;\n            }\n            \n            vector<int> posStraws, negStraws;\n            for (int idx : regions[r]) {\n                long long s = bestLine.side(strawberries[idx].x, strawberries[idx].y);\n                if (s > 0) posStraws.push_back(idx);\n                else if (s < 0) negStraws.push_back(idx);\n            }\n            \n            if (!posStraws.empty()) newRegions.push_back(posStraws);\n            if (!negStraws.empty()) newRegions.push_back(negStraws);\n        }\n        regions = newRegions;\n    }\n    \n    // If we have few cuts, add some grid cuts as backup\n    if (cuts.size() < K / 2) {\n        for (int i = 0; i < 20 && cuts.size() < K; i++) {\n            long long x = -8000 + i * 800;\n            Line line = {x, -15000, x, 15000};\n            if (!lineHitsStrawberry(line)) {\n                bool splits = false;\n                for (const auto& region : regions) {\n                    int pos, neg;\n                    countSides(line, region, pos, neg);\n                    if (pos > 0 && neg > 0) {\n                        splits = true;\n                        break;\n                    }\n                }\n                if (splits) {\n                    cuts.push_back(line);\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << cuts.size() << \"\\n\";\n    for (const auto& line : cuts) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Global variables\nint N, M;\nbool has_dot[65][65];\nbool used_edge[65][65][4]; // 0: X+, 1: Y+, 2: Diag /, 3: Diag \\\nvector<int> row_dots[65]; // row_dots[y] contains list of x\nvector<int> col_dots[65]; // col_dots[x] contains list of y\n\nstruct Point {\n    int x, y;\n    long long w;\n};\n\nvector<Point> sorted_points;\nvector<array<int, 8>> result_moves;\n\nauto start_time = chrono::steady_clock::now();\nconst double TIME_LIMIT = 4.8;\n\n// Check if an edge is used\n// Edge types:\n// 0: (x, y) to (x+1, y) -> stored at (x, y)\n// 1: (x, y) to (x, y+1) -> stored at (x, y)\n// 2: (x, y) to (x+1, y+1) -> stored at (x, y)\n// 3: (x, y) to (x-1, y+1) -> stored at (x, y) (start point has larger x)\nbool is_edge_used(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        if (y < 0 || y >= N - 1) return false;\n        return used_edge[x1][y][1];\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        if (x < 0 || x >= N - 1) return false;\n        return used_edge[x][y1][0];\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) { // Diag /\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][2];\n            } else { // Diag \\ (x1 < x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][3];\n            }\n        } else { // x1 > x2\n            if (y1 < y2) { // Diag \\ (x1 > x2, y1 < y2) -> Start is (x1, y1)\n                if (x1 < 0 || x1 >= N - 1 || y1 < 0 || y1 >= N - 1) return false;\n                return used_edge[x1][y1][3];\n            } else { // Diag / (x1 > x2, y1 > y2) -> Start is (x2, y2)\n                if (x2 < 0 || x2 >= N - 1 || y2 < 0 || y2 >= N - 1) return false;\n                return used_edge[x2][y2][2];\n            }\n        }\n    }\n    return false;\n}\n\nvoid mark_edge(int x1, int y1, int x2, int y2) {\n    if (x1 == x2) {\n        int y = min(y1, y2);\n        used_edge[x1][y][1] = true;\n    } else if (y1 == y2) {\n        int x = min(x1, x2);\n        used_edge[x][y1][0] = true;\n    } else if (abs(x1 - x2) == abs(y1 - y2)) {\n        if (x1 < x2) {\n            if (y1 < y2) used_edge[x1][y1][2] = true;\n            else used_edge[x2][y2][3] = true;\n        } else {\n            if (y1 < y2) used_edge[x1][y1][3] = true;\n            else used_edge[x2][y2][2] = true;\n        }\n    }\n}\n\n// Check perimeter constraints\n// pts: 4 vertices in order\n// dots: 3 existing dots that are allowed to be on perimeter\nbool check_perimeter(const vector<pair<int,int>>& pts, const vector<pair<int,int>>& dots) {\n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        \n        if (is_edge_used(x1, y1, x2, y2)) return false;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0) ? 0 : (dx / steps);\n        int sy = (dy == 0) ? 0 : (dy / steps);\n        \n        for (int k = 1; k < steps; ++k) {\n            int cx = x1 + k * sx;\n            int cy = y1 + k * sy;\n            if (has_dot[cx][cy]) {\n                bool allowed = false;\n                for (const auto& d : dots) {\n                    if (d.first == cx && d.second == cy) {\n                        allowed = true;\n                        break;\n                    }\n                }\n                if (!allowed) return false;\n            }\n        }\n    }\n    return true;\n}\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    vector<pair<int,int>> rect_pts;\n    vector<pair<int,int>> dot_pts;\n};\n\n// Try to find a valid rectangle for empty point (x, y)\n// Returns true if found, and fills 'move'\nbool try_fill(int x, int y, Move& out_move) {\n    // 1. Axis Aligned\n    // We need (x, yp), (xp, y), (xp, yp) to be dots.\n    // To avoid iterator invalidation, we copy relevant parts or just use indices.\n    // Since we return immediately, we can just use references but NOT modify vectors.\n    \n    for (int yp : row_dots[y]) {\n        if (yp == y) continue;\n        for (int xp : col_dots[x]) {\n            if (xp == x) continue;\n            if (has_dot[xp][yp]) {\n                // Candidate found\n                // Vertices: (x, y), (xp, y), (xp, yp), (x, yp)\n                vector<pair<int,int>> rect = {{x, y}, {xp, y}, {xp, yp}, {x, yp}};\n                vector<pair<int,int>> dots = {{xp, y}, {xp, yp}, {x, yp}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xp, y, xp, yp, x, yp, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // 2. 45-degree\n    // Case A: Vertical Diagonal (x, y) and (x, yd)\n    for (int yd : col_dots[x]) {\n        if (yd == y) continue;\n        int dy = yd - y;\n        if (abs(dy) % 2 != 0) continue;\n        int w = abs(dy) / 2;\n        int ym = y + dy / 2;\n        int x2 = x - w;\n        int x3 = x + w;\n        \n        if (x2 >= 0 && x2 < N && x3 >= 0 && x3 < N) {\n            if (has_dot[x2][ym] && has_dot[x3][ym]) {\n                // Vertices: (x, y), (x3, ym), (x, yd), (x2, ym)\n                vector<pair<int,int>> rect = {{x, y}, {x3, ym}, {x, yd}, {x2, ym}};\n                vector<pair<int,int>> dots = {{x, yd}, {x2, ym}, {x3, ym}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, x3, ym, x, yd, x2, ym, rect, dots};\n                    return true;\n                }\n            }\n        }\n    }\n    // Case B: Horizontal Diagonal (x, y) and (xd, y)\n    for (int xd : row_dots[y]) {\n        if (xd == x) continue;\n        int dx = xd - x;\n        if (abs(dx) % 2 != 0) continue;\n        int w = abs(dx) / 2;\n        int xm = x + dx / 2;\n        int y2 = y - w;\n        int y3 = y + w;\n        \n        if (y2 >= 0 && y2 < N && y3 >= 0 && y3 < N) {\n            if (has_dot[xm][y2] && has_dot[xm][y3]) {\n                // Vertices: (x, y), (xm, y3), (xd, y), (xm, y2)\n                vector<pair<int,int>> rect = {{x, y}, {xm, y3}, {xd, y}, {xm, y2}};\n                vector<pair<int,int>> dots = {{xd, y}, {xm, y2}, {xm, y3}};\n                if (check_perimeter(rect, dots)) {\n                    out_move = {x, y, xm, y3, xd, y, xm, y2, rect, dots};\n                    return true;\n                }\n            }\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 >> M)) return 0;\n    \n    long long c = (N - 1) / 2;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        has_dot[x][y] = true;\n        row_dots[y].push_back(x);\n        col_dots[x].push_back(y);\n    }\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            sorted_points.push_back({x, y, w});\n        }\n    }\n    \n    sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n        return a.w > b.w;\n    });\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        bool found = false;\n        Move best_move;\n        \n        for (const auto& p : sorted_points) {\n            if (has_dot[p.x][p.y]) continue;\n            if (row_dots[p.y].empty() && col_dots[p.x].empty()) continue;\n            \n            if (try_fill(p.x, p.y, best_move)) {\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) break;\n        \n        // Apply move\n        result_moves.push_back({best_move.x1, best_move.y1, best_move.x2, best_move.y2, \n                                best_move.x3, best_move.y3, best_move.x4, best_move.y4});\n        \n        has_dot[best_move.x1][best_move.y1] = true;\n        row_dots[best_move.y1].push_back(best_move.x1);\n        col_dots[best_move.x1].push_back(best_move.y1);\n        \n        for (size_t i = 0; i < 4; ++i) {\n            mark_edge(best_move.rect_pts[i].first, best_move.rect_pts[i].second, \n                      best_move.rect_pts[(i + 1) % 4].first, best_move.rect_pts[(i + 1) % 4].second);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& m : result_moves) {\n        cout << m[0] << \" \" << m[1] << \" \" << m[2] << \" \" << m[3] << \" \" \n             << m[4] << \" \" << m[5] << \" \" << m[6] << \" \" << m[7] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 10;\n\nstruct Candy {\n    int flavor;\n    int row, col;\n};\n\nclass GameState {\npublic:\n    array<array<int, N>, N> grid;  // 0 = empty, 1-3 = flavor\n    vector<Candy> candies;\n    \n    GameState() {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = 0;\n    }\n    \n    GameState(const GameState& other) = default;\n    \n    void placeCandy(int row, int col, int flavor) {\n        grid[row][col] = flavor;\n        candies.push_back({flavor, row, col});\n    }\n    \n    vector<pair<int,int>> getEmptyCells() const {\n        vector<pair<int,int>> empty;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    empty.push_back({i, j});\n                }\n            }\n        }\n        return empty;\n    }\n    \n    GameState tilt(char dir) const {\n        GameState result = *this;\n        auto& g = result.grid;\n        \n        if (dir == 'F') {  // Forward (up)\n            for (int j = 0; j < N; j++) {\n                int writeRow = 0;\n                for (int i = 0; i < N; i++) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow++;\n                    }\n                }\n            }\n        } else if (dir == 'B') {  // Backward (down)\n            for (int j = 0; j < N; j++) {\n                int writeRow = N - 1;\n                for (int i = N - 1; i >= 0; i--) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow--;\n                    }\n                }\n            }\n        } else if (dir == 'L') {  // Left\n            for (int i = 0; i < N; i++) {\n                int writeCol = 0;\n                for (int j = 0; j < N; j++) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol++;\n                    }\n                }\n            }\n        } else if (dir == 'R') {  // Right\n            for (int i = 0; i < N; i++) {\n                int writeCol = N - 1;\n                for (int j = N - 1; j >= 0; j--) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol--;\n                    }\n                }\n            }\n        }\n        \n        // Update candy positions\n        result.candies.clear();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (g[i][j] != 0) {\n                    result.candies.push_back({g[i][j], i, j});\n                }\n            }\n        }\n        \n        return result;\n    }\n    \n    int countSameFlavorAdjacency() const {\n        int count = 0;\n        const int dr[] = {-1, 1, 0, 0};\n        const int dc[] = {0, 0, -1, 1};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) continue;\n                for (int d = 0; d < 4; d++) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (grid[ni][nj] == grid[i][j]) {\n                            count++;\n                        }\n                    }\n                }\n            }\n        }\n        return count / 2;  // Each adjacency counted twice\n    }\n    \n    vector<int> getComponentSizes() const {\n        vector<int> sizes;\n        array<array<bool, N>, N> visited{};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0 && !visited[i][j]) {\n                    int flavor = grid[i][j];\n                    int size = 0;\n                    vector<pair<int,int>> stack = {{i, j}};\n                    visited[i][j] = true;\n                    \n                    while (!stack.empty()) {\n                        auto [r, c] = stack.back();\n                        stack.pop_back();\n                        size++;\n                        \n                        const int dr[] = {-1, 1, 0, 0};\n                        const int dc[] = {0, 0, -1, 1};\n                        \n                        for (int d = 0; d < 4; d++) {\n                            int nr = r + dr[d], nc = c + dc[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                if (!visited[nr][nc] && grid[nr][nc] == flavor) {\n                                    visited[nr][nc] = true;\n                                    stack.push_back({nr, nc});\n                                }\n                            }\n                        }\n                    }\n                    sizes.push_back(size);\n                }\n            }\n        }\n        return sizes;\n    }\n    \n    double evaluateScore() const {\n        auto sizes = getComponentSizes();\n        array<int, 4> flavorCount{};\n        \n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] != 0)\n                    flavorCount[grid[i][j]]++;\n        \n        double numerator = 0;\n        for (int s : sizes) numerator += s * s;\n        \n        double denominator = 0;\n        for (int f = 1; f <= 3; f++) denominator += flavorCount[f] * flavorCount[f];\n        \n        if (denominator == 0) return 0;\n        return 1e6 * numerator / denominator;\n    }\n    \n    // Heuristic evaluation for greedy selection\n    double heuristicEvaluate(const vector<int>& futureFlavors, int lookAhead) const {\n        double score = countSameFlavorAdjacency() * 10.0;\n        \n        // Add component size bonus\n        auto sizes = getComponentSizes();\n        for (int s : sizes) {\n            score += s * s * 0.5;\n        }\n        \n        // Consider future flavors - prefer tilts that create space for upcoming flavors\n        if (lookAhead > 0 && !futureFlavors.empty()) {\n            array<int, 4> flavorCount{};\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (grid[i][j] != 0)\n                        flavorCount[grid[i][j]]++;\n            \n            // Bonus for having clusters of flavors that appear soon\n            for (int f = 1; f <= 3; f++) {\n                if (flavorCount[f] > 0) {\n                    int upcoming = 0;\n                    for (int i = 0; i < min(lookAhead, (int)futureFlavors.size()); i++) {\n                        if (futureFlavors[i] == f) upcoming++;\n                    }\n                    score += upcoming * flavorCount[f] * 0.3;\n                }\n            }\n        }\n        \n        return score;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read flavor sequence\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    GameState state;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Find the p-th empty cell (1-indexed)\n        auto empty = state.getEmptyCells();\n        int row = empty[p - 1].first;\n        int col = empty[p - 1].second;\n        \n        // Place the candy\n        state.placeCandy(row, col, flavors[t]);\n        \n        // Skip tilt on last candy (nothing happens)\n        if (t == 99) {\n            cout << 'F' << endl;\n            continue;\n        }\n        \n        // Evaluate all 4 tilt directions\n        vector<pair<double, char>> evaluations;\n        \n        for (char dir : dirs) {\n            GameState next = state.tilt(dir);\n            \n            // Base heuristic score\n            double score = next.heuristicEvaluate(\n                vector<int>(flavors.begin() + t + 1, flavors.end()),\n                5\n            );\n            \n            // Add some randomness for exploration\n            score += (rng() % 100) * 0.01;\n            \n            evaluations.push_back({score, dir});\n        }\n        \n        // Select best direction\n        sort(evaluations.begin(), evaluations.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        char bestDir = evaluations[0].second;\n        cout << bestDir << endl;\n        \n        // Update state\n        state = state.tilt(bestDir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n#include <map>\n\nusing namespace std;\n\n// Compute degree sequence from edge string (sorted)\nvector<int> computeDegreeSeq(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Count edges\nint countEdges(const string& edges) {\n    int cnt = 0;\n    for (char c : edges) {\n        if (c == '1') cnt++;\n    }\n    return cnt;\n}\n\n// Compute degree moments (spectral-like features)\ndouble computeDegreeMoment(const vector<int>& deg, int k) {\n    if (deg.empty()) return 0;\n    double sum = 0;\n    for (int d : deg) {\n        sum += pow(d, k);\n    }\n    return sum / deg.size();\n}\n\n// Compute degree entropy (measure of degree distribution uniformity)\ndouble computeDegreeEntropy(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    int total = accumulate(deg.begin(), deg.end(), 0);\n    if (total == 0) return 0;\n    double entropy = 0;\n    for (int d : deg) {\n        if (d > 0) {\n            double p = (double)d / total;\n            entropy -= p * log2(p);\n        }\n    }\n    return entropy;\n}\n\n// Sum of squared degrees\nlong long computeSumSqDegrees(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2\nint count2Paths(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    int paths = 0;\n    for (int d : deg) {\n        paths += d * (d - 1) / 2;\n    }\n    return paths;\n}\n\n// Count connected components\nint countConnectedComponents(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    \n    vector<bool> visited(N, false);\n    int components = 0;\n    for (int i = 0; i < N; i++) {\n        if (!visited[i]) {\n            components++;\n            vector<int> q = {i};\n            visited[i] = true;\n            int head = 0;\n            while (head < (int)q.size()) {\n                int u = q[head++];\n                for (int v = 0; v < N; v++) {\n                    if (adj[u][v] && !visited[v]) {\n                        visited[v] = true;\n                        q.push_back(v);\n                    }\n                }\n            }\n        }\n    }\n    return components;\n}\n\n// Build adjacency matrix\nvector<vector<bool>> buildAdj(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    return adj;\n}\n\n// Count triangles (use sparingly, only for low eps)\nint countTriangles(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    int triangles = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!adj[i][j]) continue;\n            for (int k = j + 1; k < N; k++) {\n                if (adj[i][k] && adj[j][k]) {\n                    triangles++;\n                }\n            }\n        }\n    }\n    return triangles;\n}\n\nstruct GraphInfo {\n    string edges;\n    int edge_count;\n    vector<int> degree_seq;\n    long long sum_sq_deg;\n    int two_paths;\n    int triangles;\n    int components;\n    double degree_var;\n    double degree_entropy;\n    double moment3;\n    double moment4;\n};\n\n// Generate different graph types for diversity\nstring generateGraph(int N, int target_edges, int graph_type, int seed) {\n    int total_edges = N * (N - 1) / 2;\n    string g(total_edges, '0');\n    \n    mt19937 rng(seed);\n    \n    if (graph_type == 0) {\n        // Regular-like: spread edges evenly across vertices\n        vector<int> deg(N, 0);\n        vector<pair<int,int>> all_edges;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                all_edges.push_back({i, j});\n            }\n        }\n        \n        // Sort by sum of current degrees (prefer connecting low-degree vertices)\n        shuffle(all_edges.begin(), all_edges.end(), rng);\n        \n        int added = 0;\n        for (auto& [i, j] : all_edges) {\n            if (added >= target_edges) break;\n            int idx = i * N - i * (i + 1) / 2 + (j - i - 1);\n            if (idx >= 0 && idx < total_edges) {\n                g[idx] = '1';\n                added++;\n            }\n        }\n    } else if (graph_type == 1) {\n        // Bipartite-like: prefer edges between two halves\n        vector<int> positions;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                bool cross = (i < N/2) != (j < N/2);\n                positions.push_back(i * N - i * (i + 1) / 2 + (j - i - 1));\n            }\n        }\n        \n        // Sort to put cross-edges first\n        vector<pair<int,int>> edge_info;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                int idx = i * N - i * (i + 1) / 2 + (j - i - 1);\n                bool cross = (i < N/2) != (j < N/2);\n                edge_info.push_back({!cross, idx}); // cross-edges get lower sort key\n            }\n        }\n        sort(edge_info.begin(), edge_info.end());\n        \n        for (int i = 0; i < target_edges && i < (int)edge_info.size(); i++) {\n            if (edge_info[i].second >= 0 && edge_info[i].second < total_edges) {\n                g[edge_info[i].second] = '1';\n            }\n        }\n    } else if (graph_type == 2) {\n        // Clustered: prefer edges within groups\n        vector<pair<int,int>> edge_info;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                int idx = i * N - i * (i + 1) / 2 + (j - i - 1);\n                bool same_group = (i * 3 / N) == (j * 3 / N);\n                edge_info.push_back({!same_group, idx}); // same-group edges first\n            }\n        }\n        sort(edge_info.begin(), edge_info.end());\n        \n        for (int i = 0; i < target_edges && i < (int)edge_info.size(); i++) {\n            if (edge_info[i].second >= 0 && edge_info[i].second < total_edges) {\n                g[edge_info[i].second] = '1';\n            }\n        }\n    } else {\n        // Random-like: uniformly distributed\n        vector<int> positions(total_edges);\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n        \n        for (int i = 0; i < target_edges && i < total_edges; i++) {\n            g[positions[i]] = '1';\n        }\n    }\n    \n    return g;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n    \n    // More aggressive N selection based on difficulty\n    // Key insight: for high M and high eps, we need maximum separation\n    double difficulty = (M / 100.0) * (eps / 0.4);\n    \n    int N;\n    if (eps < 0.02) {\n        N = 18;\n    } else if (eps < 0.05) {\n        N = 25;\n    } else if (eps < 0.08) {\n        N = 32;\n    } else if (eps < 0.12) {\n        N = 42;\n    } else if (eps < 0.16) {\n        N = 52;\n    } else if (eps < 0.20) {\n        N = 65;\n    } else if (eps < 0.25) {\n        N = 78;\n    } else if (eps < 0.30) {\n        N = 88;\n    } else if (eps < 0.35) {\n        N = 95;\n    } else {\n        N = 100;\n    }\n    \n    // For very large M, push N higher\n    if (M >= 70) N = min(100, N + 5);\n    if (M >= 90) N = min(100, N + 5);\n    \n    N = max(4, min(100, N));\n    int total_edges = N * (N - 1) / 2;\n    \n    // Store graph information\n    vector<GraphInfo> graphs(M);\n    \n    // Generate diverse graphs using different structures\n    for (int k = 0; k < M; k++) {\n        GraphInfo& info = graphs[k];\n        \n        // Target edge count - evenly distributed\n        int target_edges = M > 1 ? (k * total_edges) / (M - 1) : total_edges / 2;\n        target_edges = max(0, min(total_edges, target_edges));\n        info.edge_count = target_edges;\n        \n        // Choose graph type based on position to ensure diversity\n        int graph_type = k % 4;\n        \n        // Generate graph with structural variation\n        info.edges = generateGraph(N, target_edges, graph_type, 2024 + k * 137);\n        \n        // Compute all features\n        info.degree_seq = computeDegreeSeq(info.edges, N);\n        info.sum_sq_deg = computeSumSqDegrees(info.degree_seq);\n        info.two_paths = count2Paths(info.edges, N);\n        info.triangles = (eps < 0.15) ? countTriangles(info.edges, N) : 0;\n        info.components = countConnectedComponents(info.edges, N);\n        \n        // Degree statistics\n        double mean_deg = (double)accumulate(info.degree_seq.begin(), info.degree_seq.end(), 0) / N;\n        double var = 0;\n        for (int d : info.degree_seq) {\n            var += (d - mean_deg) * (d - mean_deg);\n        }\n        info.degree_var = var / N;\n        info.degree_entropy = computeDegreeEntropy(info.degree_seq);\n        info.moment3 = computeDegreeMoment(info.degree_seq, 3);\n        info.moment4 = computeDegreeMoment(info.degree_seq, 4);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << graphs[k].edges << \"\\n\";\n    }\n    cout << flush;\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        if (h.empty() || h.length() != (size_t)total_edges) {\n            cout << 0 << \"\\n\";\n            cout << flush;\n            continue;\n        }\n        \n        // Compute query features\n        int h_edges = countEdges(h);\n        vector<int> h_deg = computeDegreeSeq(h, N);\n        long long h_sum_sq = computeSumSqDegrees(h_deg);\n        int h_2paths = count2Paths(h, N);\n        int h_triangles = (eps < 0.15) ? countTriangles(h, N) : 0;\n        int h_components = countConnectedComponents(h, N);\n        \n        double h_mean_deg = (double)accumulate(h_deg.begin(), h_deg.end(), 0) / N;\n        double h_var = 0;\n        for (int d : h_deg) {\n            h_var += (d - h_mean_deg) * (d - h_mean_deg);\n        }\n        double h_degree_var = h_var / N;\n        double h_entropy = computeDegreeEntropy(h_deg);\n        double h_m3 = computeDegreeMoment(h_deg, 3);\n        double h_m4 = computeDegreeMoment(h_deg, 4);\n        \n        // Noise-aware scoring\n        // Expected variance in edge count due to noise: total_edges * eps * (1-eps)\n        double edge_noise_var = total_edges * eps * (1.0 - eps);\n        double edge_noise_std = sqrt(max(1.0, edge_noise_var));\n        \n        int best_k = 0;\n        double best_log_prob = -1e18;\n        \n        for (int k = 0; k < M; k++) {\n            double log_prob = 0;\n            \n            // Edge count (Gaussian model)\n            double edge_diff = h_edges - graphs[k].edge_count;\n            log_prob -= 0.5 * (edge_diff * edge_diff) / (edge_noise_var + 1);\n            \n            // Sum of squared degrees\n            double sq_diff = (double)(h_sum_sq - graphs[k].sum_sq_deg);\n            double sq_noise = N * N * eps * 0.5; // Approximate\n            log_prob -= 0.5 * (sq_diff * sq_diff) / (sq_noise * sq_noise + 1);\n            \n            // 2-path count\n            double path_diff = h_2paths - graphs[k].two_paths;\n            double path_noise = total_edges * N * eps * 0.1;\n            log_prob -= 0.5 * (path_diff * path_diff) / (path_noise * path_noise + 1);\n            \n            // Degree variance\n            double var_diff = h_degree_var - graphs[k].degree_var;\n            log_prob -= var_diff * var_diff * N * (1.0 - eps) * 2;\n            \n            // Degree entropy\n            double ent_diff = h_entropy - graphs[k].degree_entropy;\n            log_prob -= ent_diff * ent_diff * 50;\n            \n            // Higher moments (for additional discrimination)\n            double m3_diff = h_m3 - graphs[k].moment3;\n            log_prob -= m3_diff * m3_diff * 0.001;\n            \n            double m4_diff = h_m4 - graphs[k].moment4;\n            log_prob -= m4_diff * m4_diff * 0.0001;\n            \n            // Triangle count (only for low eps)\n            if (eps < 0.15) {\n                double tri_diff = h_triangles - graphs[k].triangles;\n                double tri_noise = graphs[k].triangles * eps * 3 + 1;\n                log_prob -= 0.5 * (tri_diff * tri_diff) / (tri_noise * tri_noise + 1);\n            }\n            \n            // Component count (discrete penalty)\n            if (h_components != graphs[k].components) {\n                log_prob -= 3.0;\n            }\n            \n            if (log_prob > best_log_prob) {\n                best_log_prob = log_prob;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nstruct Edge {\n    int id;\n    int u, v;\n    long long w;\n    double mid_x, mid_y;\n    double importance;\n};\n\nclass Solver {\npublic:\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<vector<pair<int, int>>> adj;\n    vector<pair<int, int>> coords;\n    vector<vector<long long>> base_dist;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    static constexpr long long INF = 1e18;\n    static constexpr long long UNREACHABLE = 1000000000;\n    \n    void compute_base_distances() {\n        base_dist.assign(N, vector<long long>(N, INF));\n        \n        for (int src = 0; src < N; src++) {\n            base_dist[src][src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > base_dist[src][u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < base_dist[src][v]) {\n                        base_dist[src][v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n    }\n    \n    void compute_edge_importance() {\n        vector<double> importance(M, 0);\n        \n        int samples = min(N, 30);\n        for (int i = 0; i < samples; i++) {\n            int src = i * N / samples;\n            vector<long long> dist(N, INF);\n            vector<int> parent_edge(N, -1);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        parent_edge[v] = edge_idx;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int v = 0; v < N; v++) {\n                if (v != src && parent_edge[v] != -1) {\n                    importance[parent_edge[v]] += 1.0;\n                }\n            }\n        }\n        \n        long long max_w = 1;\n        for (auto& e : edges) max_w = max(max_w, e.w);\n        \n        double center_x = 500, center_y = 500;\n        for (int i = 0; i < M; i++) {\n            double dist_from_center = hypot(edges[i].mid_x - center_x, edges[i].mid_y - center_y);\n            double weight_factor = 1.0 + (max_w - edges[i].w) / (double)max_w * 0.3;\n            double spatial_factor = 1.0 + dist_from_center / 1000.0;\n            edges[i].importance = importance[i] * weight_factor * spatial_factor;\n        }\n    }\n    \n    long long compute_day_frustration_fast(const vector<int>& edges_to_remove) {\n        if (edges_to_remove.empty()) return 0;\n        \n        vector<bool> edge_removed(M, false);\n        for (int idx : edges_to_remove) {\n            edge_removed[idx] = true;\n        }\n        \n        long long total_increase = 0;\n        int samples = min(N, 15);\n        \n        for (int src = 0; src < samples; src++) {\n            int src_idx = src * N / samples;\n            vector<long long> dist(N, INF);\n            dist[src_idx] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src_idx});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    if (edge_removed[edge_idx]) continue;\n                    \n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int dst = 0; dst < samples; dst++) {\n                if (src == dst) continue;\n                int dst_idx = dst * N / samples;\n                \n                long long d_k = (dist[dst_idx] >= INF) ? UNREACHABLE : dist[dst_idx];\n                long long d_base = (base_dist[src_idx][dst_idx] >= INF) ? UNREACHABLE : base_dist[src_idx][dst_idx];\n                \n                total_increase += max(0LL, d_k - d_base);\n            }\n        }\n        \n        double scale = (double)(N * (N - 1)) / (samples * (samples - 1));\n        return (long long)(total_increase * scale);\n    }\n    \n    vector<int> solve() {\n        start_time = chrono::steady_clock::now();\n        \n        compute_base_distances();\n        compute_edge_importance();\n        \n        // Sort edges by importance (descending)\n        vector<int> edge_order(M);\n        iota(edge_order.begin(), edge_order.end(), 0);\n        sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n            return edges[a].importance > edges[b].importance;\n        });\n        \n        // Initial assignment with spatial awareness\n        vector<int> assignment(M, -1);\n        vector<vector<int>> day_edges(D);\n        vector<double> day_center_x(D, 500), day_center_y(D, 500);\n        vector<long long> day_importance(D, 0);\n        \n        for (int edge_idx : edge_order) {\n            int best_day = 0;\n            double best_score = 1e18;\n            \n            for (int d = 0; d < D; d++) {\n                if ((int)day_edges[d].size() < K) {\n                    // Score based on importance balance and spatial spread\n                    double importance_score = day_importance[d];\n                    double spatial_score = 0;\n                    if (!day_edges[d].empty()) {\n                        spatial_score = hypot(edges[edge_idx].mid_x - day_center_x[d], \n                                            edges[edge_idx].mid_y - day_center_y[d]);\n                    }\n                    double score = importance_score * 0.7 - spatial_score * 0.3;\n                    \n                    if (score < best_score) {\n                        best_score = score;\n                        best_day = d;\n                    }\n                }\n            }\n            \n            assignment[edge_idx] = best_day + 1;\n            day_edges[best_day].push_back(edge_idx);\n            day_importance[best_day] += (long long)(edges[edge_idx].importance * 1000);\n            \n            // Update day center\n            int n = day_edges[best_day].size();\n            day_center_x[best_day] = (day_center_x[best_day] * (n-1) + edges[edge_idx].mid_x) / n;\n            day_center_y[best_day] = (day_center_y[best_day] * (n-1) + edges[edge_idx].mid_y) / n;\n        }\n        \n        // Compute initial day frustrations\n        vector<long long> day_frustration(D);\n        long long current_total = 0;\n        for (int d = 0; d < D; d++) {\n            day_frustration[d] = compute_day_frustration_fast(day_edges[d]);\n            current_total += day_frustration[d];\n        }\n        \n        long long best_total = current_total;\n        vector<int> best_assignment = assignment;\n        \n        // Aggressive local search with time budget\n        double time_limit = 5.3;\n        double temperature = 0.8;\n        int iteration = 0;\n        int no_improve_count = 0;\n        \n        vector<double> edge_selection_prob(M);\n        double total_importance = 0;\n        for (int i = 0; i < M; i++) {\n            edge_selection_prob[i] = edges[i].importance + 1.0;\n            total_importance += edge_selection_prob[i];\n        }\n        \n        while (no_improve_count < 50) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Select edge biased by importance\n            double r = uniform_real_distribution<>(0.0, total_importance)(rng);\n            int edge_idx = 0;\n            double cumsum = 0;\n            for (int i = 0; i < M; i++) {\n                cumsum += edge_selection_prob[i];\n                if (r <= cumsum) {\n                    edge_idx = i;\n                    break;\n                }\n            }\n            \n            int old_day = assignment[edge_idx] - 1;\n            int new_day = uniform_int_distribution<>(0, D - 1)(rng);\n            \n            if (new_day == old_day || (int)day_edges[new_day].size() >= K) {\n                continue;\n            }\n            \n            // Fast delta computation\n            vector<int> old_day_temp;\n            old_day_temp.reserve(day_edges[old_day].size());\n            for (int e : day_edges[old_day]) {\n                if (e != edge_idx) old_day_temp.push_back(e);\n            }\n            \n            vector<int> new_day_temp = day_edges[new_day];\n            new_day_temp.push_back(edge_idx);\n            \n            long long new_old = compute_day_frustration_fast(old_day_temp);\n            long long new_new = compute_day_frustration_fast(new_day_temp);\n            \n            long long delta = (new_old + new_new) - (day_frustration[old_day] + day_frustration[new_day]);\n            \n            double accept_prob = exp(-delta / (temperature * max(1LL, current_total / D) + 1));\n            \n            if (delta < 0 || uniform_real_distribution<>(0.0, 1.0)(rng) < accept_prob) {\n                assignment[edge_idx] = new_day + 1;\n                \n                auto it = find(day_edges[old_day].begin(), day_edges[old_day].end(), edge_idx);\n                if (it != day_edges[old_day].end()) day_edges[old_day].erase(it);\n                day_edges[new_day].push_back(edge_idx);\n                \n                day_frustration[old_day] = new_old;\n                day_frustration[new_day] = new_new;\n                \n                current_total += delta;\n                \n                if (current_total < best_total) {\n                    best_total = current_total;\n                    best_assignment = assignment;\n                    no_improve_count = 0;\n                } else {\n                    no_improve_count++;\n                }\n            } else {\n                no_improve_count++;\n            }\n            \n            iteration++;\n            temperature *= 0.9998;\n        }\n        \n        return best_assignment;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    Solver solver;\n    solver.N = N;\n    solver.M = M;\n    solver.D = D;\n    solver.K = K;\n    solver.rng.seed(42);\n    \n    solver.edges.resize(M);\n    solver.adj.resize(N);\n    solver.coords.resize(N);\n    \n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        solver.edges[i] = {i, u, v, (long long)w, 0, 0, 0};\n        solver.adj[u].push_back({v, i});\n        solver.adj[v].push_back({u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        int u = solver.edges[i].u;\n        int v = solver.edges[i].v;\n        solver.edges[i].mid_x = (solver.coords[u].first + solver.coords[v].first) / 2.0;\n        solver.edges[i].mid_y = (solver.coords[u].second + solver.coords[v].second) / 2.0;\n    }\n    \n    auto assignment = solver.solve();\n    \n    for (int i = 0; i < M; i++) {\n        cout << assignment[i] << (i == M - 1 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D;\n    cin >> D;\n    \n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; i++) cin >> f1[i];\n    for (int i = 0; i < D; i++) cin >> r1[i];\n    for (int i = 0; i < D; i++) cin >> f2[i];\n    for (int i = 0; i < D; i++) cin >> r2[i];\n    \n    // Compute valid positions\n    vector<vector<vector<bool>>> valid1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> valid2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[z][y][x] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Common positions\n    vector<vector<vector<bool>>> common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                common[z][y][x] = valid1[z][y][x] && valid2[z][y][x];\n            }\n        }\n    }\n    \n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    int block_id = 1;\n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    // Step 1: For each z-layer, find minimum cells to satisfy silhouettes\n    // Prioritize common positions for shared blocks\n    vector<vector<vector<bool>>> used1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> used2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // For each z-layer in arrangement 1\n    for (int z = 0; z < D; z++) {\n        // Find which x positions need blocks (front silhouette)\n        vector<int> need_x;\n        for (int x = 0; x < D; x++) {\n            if (f1[z][x] == '1') need_x.push_back(x);\n        }\n        \n        // Find which y positions need blocks (right silhouette)\n        vector<int> need_y;\n        for (int y = 0; y < D; y++) {\n            if (r1[z][y] == '1') need_y.push_back(y);\n        }\n        \n        // Greedy: place blocks at common positions first\n        set<int> covered_x, covered_y;\n        \n        // First pass: use common positions\n        for (int x : need_x) {\n            for (int y : need_y) {\n                if (common[z][y][x] && !covered_x.count(x) && !covered_y.count(y)) {\n                    used1[z][y][x] = true;\n                    covered_x.insert(x);\n                    covered_y.insert(y);\n                }\n            }\n        }\n        \n        // Second pass: cover remaining x\n        for (int x : need_x) {\n            if (!covered_x.count(x)) {\n                for (int y : need_y) {\n                    if (valid1[z][y][x]) {\n                        used1[z][y][x] = true;\n                        covered_x.insert(x);\n                        if (!covered_y.count(y)) covered_y.insert(y);\n                        break;\n                    }\n                }\n            }\n        }\n        \n        // Third pass: cover remaining y\n        for (int y : need_y) {\n            if (!covered_y.count(y)) {\n                for (int x : need_x) {\n                    if (valid1[z][y][x]) {\n                        used1[z][y][x] = true;\n                        covered_y.insert(y);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // For each z-layer in arrangement 2\n    for (int z = 0; z < D; z++) {\n        vector<int> need_x, need_y;\n        for (int x = 0; x < D; x++) {\n            if (f2[z][x] == '1') need_x.push_back(x);\n        }\n        for (int y = 0; y < D; y++) {\n            if (r2[z][y] == '1') need_y.push_back(y);\n        }\n        \n        set<int> covered_x, covered_y;\n        \n        // First pass: use common positions (already marked in used1)\n        for (int x : need_x) {\n            for (int y : need_y) {\n                if (common[z][y][x] && !covered_x.count(x) && !covered_y.count(y)) {\n                    used2[z][y][x] = true;\n                    covered_x.insert(x);\n                    covered_y.insert(y);\n                }\n            }\n        }\n        \n        // Second pass: cover remaining x\n        for (int x : need_x) {\n            if (!covered_x.count(x)) {\n                for (int y : need_y) {\n                    if (valid2[z][y][x]) {\n                        used2[z][y][x] = true;\n                        covered_x.insert(x);\n                        if (!covered_y.count(y)) covered_y.insert(y);\n                        break;\n                    }\n                }\n            }\n        }\n        \n        // Third pass: cover remaining y\n        for (int y : need_y) {\n            if (!covered_y.count(y)) {\n                for (int x : need_x) {\n                    if (valid2[z][y][x]) {\n                        used2[z][y][x] = true;\n                        covered_y.insert(y);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Mark common used positions as shared\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used1[z][y][x] && used2[z][y][x] && common[z][y][x]) {\n                    b1[z][y][x] = -1; // Mark for shared block assignment\n                    b2[z][y][x] = -1;\n                }\n            }\n        }\n    }\n    \n    // Step 2: Assign connected components as blocks\n    // First: shared blocks (common positions used in both)\n    vector<vector<vector<bool>>> visited_shared(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (b1[z][y][x] == -1 && !visited_shared[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited_shared[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                b1[nz][ny][nx] == -1 && !visited_shared[nz][ny][nx]) {\n                                visited_shared[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Second: arrangement 1 only\n    vector<vector<vector<bool>>> visited1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used1[z][y][x] && b1[z][y][x] == 0 && !visited1[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited1[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used1[nz][ny][nx] && b1[nz][ny][nx] == 0 && !visited1[nz][ny][nx]) {\n                                visited1[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Third: arrangement 2 only\n    vector<vector<vector<bool>>> visited2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used2[z][y][x] && b2[z][y][x] == 0 && !visited2[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited2[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used2[nz][ny][nx] && b2[nz][ny][nx] == 0 && !visited2[nz][ny][nx]) {\n                                visited2[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    \n    // Output in correct order: x*D^2 + y*D + z\n    for (int i = 0; i < 2; i++) {\n        vector<int> output;\n        output.reserve(D * D * D);\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                    output.push_back(i == 0 ? b1[z][y][x] : b2[z][y][x]);\n                }\n            }\n        }\n        \n        for (int j = 0; j < (int)output.size(); j++) {\n            cout << output[j] << (j == (int)output.size() - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <numeric>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        return parent[x] == x ? x : parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        parent[y] = x;\n        return true;\n    }\n};\n\nlong long dist_ll(Point a, Point b) {\n    long long dx = a.x - b.x;\n    long long dy = a.y - b.y;\n    return round(sqrt(dx * dx + dy * dy));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    vector<Point> stations(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n    }\n    \n    vector<Point> residents(K);\n    for (int i = 0; i < K; i++) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n    \n    // Precompute distances from each resident to each station\n    vector<vector<long long>> resident_station_dist(K, vector<long long>(N));\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            resident_station_dist[k][i] = dist_ll(residents[k], stations[i]);\n        }\n    }\n    \n    // Build MST from station 0 for initial connectivity\n    vector<pair<long long, int>> mst_edges;\n    vector<Edge> sorted_edges = edges;\n    sort(sorted_edges.begin(), sorted_edges.end(), \n         [](const Edge& a, const Edge& b) { return a.w < b.w; });\n    \n    DSU dsu(N);\n    vector<int> edge_in_mst(M, 0);\n    long long mst_cost = 0;\n    int edges_added = 0;\n    \n    for (int i = 0; i < M && edges_added < N - 1; i++) {\n        int idx = -1;\n        for (int j = 0; j < M; j++) {\n            if (edge_in_mst[j]) continue;\n            if (edges[j].w == sorted_edges[i].w && \n                dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                idx = j;\n                break;\n            }\n        }\n        if (idx == -1) {\n            for (int j = 0; j < M; j++) {\n                if (edge_in_mst[j]) continue;\n                if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                    idx = j;\n                    break;\n                }\n            }\n        }\n        if (idx != -1) {\n            dsu.unite(edges[idx].u, edges[idx].v);\n            edge_in_mst[idx] = 1;\n            mst_cost += edges[idx].w;\n            edges_added++;\n        }\n    }\n    \n    // Find connected component from station 0\n    vector<int> reachable(N, 0);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (edge_in_mst[i]) {\n            adj[edges[i].u].push_back(edges[i].v);\n            adj[edges[i].v].push_back(edges[i].u);\n        }\n    }\n    \n    queue<int> q;\n    q.push(0);\n    reachable[0] = 1;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (!reachable[v]) {\n                reachable[v] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Assign residents to nearest reachable station\n    vector<long long> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        long long min_dist = 1e18;\n        int best_station = -1;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i]) {\n                if (resident_station_dist[k][i] < min_dist) {\n                    min_dist = resident_station_dist[k][i];\n                    best_station = i;\n                }\n            }\n        }\n        if (best_station != -1 && min_dist <= 5000) {\n            P[best_station] = max(P[best_station], min_dist);\n        }\n    }\n    \n    // Calculate initial cost\n    auto calc_cost = [&]() -> long long {\n        long long cost = 0;\n        for (int i = 0; i < N; i++) {\n            cost += P[i] * P[i];\n        }\n        for (int i = 0; i < M; i++) {\n            if (edge_in_mst[i]) {\n                cost += edges[i].w;\n            }\n        }\n        return cost;\n    };\n    \n    auto check_coverage = [&]() -> bool {\n        for (int k = 0; k < K; k++) {\n            bool covered = false;\n            for (int i = 0; i < N; i++) {\n                if (reachable[i] && resident_station_dist[k][i] <= P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n            if (!covered) return false;\n        }\n        return true;\n    };\n    \n    long long best_cost = calc_cost();\n    vector<int> best_edge_state = edge_in_mst;\n    vector<long long> best_P = P;\n    \n    // Try adding beneficial edges\n    mt19937 rng(42);\n    for (int iter = 0; iter < 500; iter++) {\n        vector<int> current_edge_state = best_edge_state;\n        vector<long long> current_P = best_P;\n        \n        // Recompute reachable\n        vector<int> cur_reachable(N, 0);\n        vector<vector<int>> cur_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (current_edge_state[i]) {\n                cur_adj[edges[i].u].push_back(edges[i].v);\n                cur_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> cq;\n        cq.push(0);\n        cur_reachable[0] = 1;\n        while (!cq.empty()) {\n            int u = cq.front(); cq.pop();\n            for (int v : cur_adj[u]) {\n                if (!cur_reachable[v]) {\n                    cur_reachable[v] = 1;\n                    cq.push(v);\n                }\n            }\n        }\n        \n        // Try adding a random edge\n        int edge_to_add = uniform_int_distribution<>(0, M-1)(rng);\n        if (!current_edge_state[edge_to_add]) {\n            current_edge_state[edge_to_add] = 1;\n            \n            // Recompute reachable\n            fill(cur_reachable.begin(), cur_reachable.end(), 0);\n            for (int i = 0; i < N; i++) cur_adj[i].clear();\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    cur_adj[edges[i].u].push_back(edges[i].v);\n                    cur_adj[edges[i].v].push_back(edges[i].u);\n                }\n            }\n            cq = queue<int>();\n            cq.push(0);\n            cur_reachable[0] = 1;\n            while (!cq.empty()) {\n                int u = cq.front(); cq.pop();\n                for (int v : cur_adj[u]) {\n                    if (!cur_reachable[v]) {\n                        cur_reachable[v] = 1;\n                        cq.push(v);\n                    }\n                }\n            }\n            \n            // Recalculate P\n            fill(current_P.begin(), current_P.end(), 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    current_P[best_station] = max(current_P[best_station], min_dist);\n                }\n            }\n            \n            // Calculate new cost\n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += current_P[i] * current_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            // Check if all residents covered\n            bool all_covered = true;\n            for (int k = 0; k < K; k++) {\n                bool covered = false;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i] && resident_station_dist[k][i] <= current_P[i]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    all_covered = false;\n                    break;\n                }\n            }\n            \n            if (all_covered && new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = current_edge_state;\n                best_P = current_P;\n            }\n        }\n    }\n    \n    // Try removing expensive edges if possible\n    vector<pair<long long, int>> edge_by_cost;\n    for (int i = 0; i < M; i++) {\n        if (best_edge_state[i]) {\n            edge_by_cost.push_back({edges[i].w, i});\n        }\n    }\n    sort(edge_by_cost.rbegin(), edge_by_cost.rend());\n    \n    for (auto& [w, idx] : edge_by_cost) {\n        vector<int> test_edge_state = best_edge_state;\n        test_edge_state[idx] = 0;\n        \n        // Check if still connected\n        vector<int> test_reachable(N, 0);\n        vector<vector<int>> test_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (test_edge_state[i]) {\n                test_adj[edges[i].u].push_back(edges[i].v);\n                test_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> tq;\n        tq.push(0);\n        test_reachable[0] = 1;\n        while (!tq.empty()) {\n            int u = tq.front(); tq.pop();\n            for (int v : test_adj[u]) {\n                if (!test_reachable[v]) {\n                    test_reachable[v] = 1;\n                    tq.push(v);\n                }\n            }\n        }\n        \n        // Check if all residents still coverable\n        bool all_coverable = true;\n        for (int k = 0; k < K; k++) {\n            bool can_cover = false;\n            for (int i = 0; i < N; i++) {\n                if (test_reachable[i] && resident_station_dist[k][i] <= 5000) {\n                    can_cover = true;\n                    break;\n                }\n            }\n            if (!can_cover) {\n                all_coverable = false;\n                break;\n            }\n        }\n        \n        if (all_coverable) {\n            vector<long long> test_P(N, 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (test_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    test_P[best_station] = max(test_P[best_station], min_dist);\n                }\n            }\n            \n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += test_P[i] * test_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (test_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = test_edge_state;\n                best_P = test_P;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << best_P[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << best_edge_state[i] << (i == M-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cstring>\n\nusing namespace std;\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\nint N = 30;\nint grid[30][30];\nPoint pos[465]; \n\nvector<tuple<int, int, int, int>> ops;\n\n// Directions for neighbors\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid swap_balls(int x1, int y1, int x2, int y2) {\n    int v1 = grid[x1][y1];\n    int v2 = grid[x2][y2];\n    grid[x1][y1] = v2;\n    grid[x2][y2] = v1;\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n}\n\n// Anchor marks cells in the current row that already contain a correct value\nbool anchor[30][30];\n\n// BFS to find closest needed value and move it to (tr, tc)\nint find_and_move(int tr, int tc, int val_min, int val_max) {\n    Point target = {tr, tc};\n    \n    static int dist[30][30];\n    static Point parent[30][30];\n    static bool visited[30][30];\n    \n    // Reset visited\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            visited[i][j] = false;\n        }\n    }\n    \n    queue<Point> q;\n    q.push(target);\n    visited[tr][tc] = true;\n    dist[tr][tc] = 0;\n    parent[tr][tc] = {-1, -1};\n    \n    Point best_pos = {-1, -1};\n    \n    while(!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n        \n        // Check if this cell has a needed value\n        int val = grid[curr.x][curr.y];\n        if (val >= val_min && val <= val_max) {\n            best_pos = curr;\n            break; \n        }\n        \n        // Expand neighbors\n        for(int i=0; i<6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (is_valid(nx, ny)) {\n                // Obstacle checks\n                if (nx < tr) continue; // Rows above are fixed\n                if (nx == tr && ny < tc) continue; // Cols left in current row are fixed\n                if (nx == tr && anchor[nx][ny]) continue; // Anchors in current row are fixed\n                \n                if (!visited[nx][ny]) {\n                    visited[nx][ny] = true;\n                    dist[nx][ny] = dist[curr.x][curr.y] + 1;\n                    parent[nx][ny] = curr;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n    \n    if (best_pos.x == -1) return -1;\n    \n    // Reconstruct path from best_pos to target\n    vector<Point> path;\n    Point curr = best_pos;\n    while (true) {\n        path.push_back(curr);\n        if (curr == target) break;\n        curr = parent[curr.x][curr.y];\n    }\n    \n    // Execute swaps: move value from path[0] to path.back()\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        swap_balls(path[i].x, path[i].y, path[i+1].x, path[i+1].y);\n    }\n    \n    return grid[tr][tc];\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> grid[i][j];\n            pos[grid[i][j]] = {i, j};\n        }\n    }\n    \n    ops.reserve(10000);\n    \n    // Process each row from top to bottom\n    for (int r = 0; r < N; ++r) {\n        int row_min = r * (r + 1) / 2;\n        int row_max = (r + 1) * (r + 2) / 2 - 1;\n        \n        // Identify anchors: cells in Row r that already have a value belonging to Row r\n        memset(anchor, 0, sizeof(anchor));\n        for (int c = 0; c <= r; ++c) {\n            if (grid[r][c] >= row_min && grid[r][c] <= row_max) {\n                anchor[r][c] = true;\n            }\n        }\n        \n        // Fill row r positions 0 to r\n        for (int c = 0; c <= r; ++c) {\n            // If this cell is an anchor, it already has a valid value for this row.\n            // We keep it in place to minimize swaps.\n            if (anchor[r][c]) continue;\n            \n            // Otherwise, find the closest value belonging to this row from the free region\n            // and move it here.\n            int val = find_and_move(r, c, row_min, row_max);\n            if (val == -1) {\n                // Should not happen as there are exactly enough values\n                return 1;\n            }\n            // After move, grid[r][c] contains a value in [row_min, row_max].\n            // It is effectively fixed for subsequent steps in this row (handled by ny < tc check).\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \" << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0;\nconst int ENTRANCE_J = 4;\n\nstruct Container {\n    int id;\n    int pi, pj;\n    bool retrieved;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    int D_val;\n    cin >> D_val >> N;\n    \n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n    \n    // Compute BFS distance from entrance for all cells\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    vector<pair<int,int>> cells;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    dist[ENTRANCE_I][ENTRANCE_J] = 0;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (!(ci == ENTRANCE_I && cj == ENTRANCE_J)) {\n            cells.push_back({ci, cj});\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                dist[ni][nj] == -1 && !obstacle[ni][nj]) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Sort cells by distance (farthest first for storage)\n    sort(cells.begin(), cells.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        return dist[a.first][a.second] > dist[b.first][b.second];\n    });\n    \n    // Track which cells are occupied\n    vector<vector<int>> cellContainer(D, vector<int>(D, -1)); // -1 = empty, otherwise container index\n    \n    vector<Container> containers;\n    int totalContainers = D * D - 1 - N;\n    \n    // Storage phase\n    for (int d = 0; d < totalContainers; d++) {\n        int t;\n        cin >> t;\n        \n        // BFS to find all reachable empty cells\n        int bestI = -1, bestJ = -1;\n        int bestDist = -1;\n        \n        queue<pair<int,int>> bq;\n        bq.push({ENTRANCE_I, ENTRANCE_J});\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        visited[ENTRANCE_I][ENTRANCE_J] = true;\n        \n        while (!bq.empty()) {\n            auto [ci, cj] = bq.front();\n            bq.pop();\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int ni = ci + di_arr[dir];\n                int nj = cj + dj_arr[dir];\n                \n                if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                    !visited[ni][nj] && !obstacle[ni][nj] && cellContainer[ni][nj] == -1) {\n                    visited[ni][nj] = true;\n                    bq.push({ni, nj});\n                    \n                    // This cell is reachable and empty, consider it\n                    if (dist[ni][nj] > bestDist) {\n                        bestDist = dist[ni][nj];\n                        bestI = ni;\n                        bestJ = nj;\n                    }\n                }\n            }\n        }\n        \n        if (bestI == -1) {\n            // Fallback: find any reachable empty cell\n            for (int i = 0; i < D; i++) {\n                for (int j = 0; j < D; j++) {\n                    if (cellContainer[i][j] == -1 && !obstacle[i][j] && \n                        !(i == ENTRANCE_I && j == ENTRANCE_J)) {\n                        if (dist[i][j] > bestDist) {\n                            bestDist = dist[i][j];\n                            bestI = i;\n                            bestJ = j;\n                        }\n                    }\n                }\n            }\n        }\n        \n        int containerIdx = containers.size();\n        containers.push_back({t, bestI, bestJ, false});\n        cellContainer[bestI][bestJ] = containerIdx;\n        cout << bestI << \" \" << bestJ << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval phase - greedily pick lowest ID accessible container\n    vector<pair<int,int>> retrievalOrder;\n    \n    for (int step = 0; step < totalContainers; step++) {\n        // Find all accessible containers via BFS\n        int bestIdx = -1;\n        int bestId = totalContainers + 1;\n        \n        queue<pair<int,int>> bq;\n        bq.push({ENTRANCE_I, ENTRANCE_J});\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        visited[ENTRANCE_I][ENTRANCE_J] = true;\n        \n        while (!bq.empty()) {\n            auto [ci, cj] = bq.front();\n            bq.pop();\n            \n            for (int dir = 0; dir < 4; dir++) {\n                int ni = ci + di_arr[dir];\n                int nj = cj + dj_arr[dir];\n                \n                if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                    !visited[ni][nj] && !obstacle[ni][nj]) {\n                    visited[ni][nj] = true;\n                    \n                    int containerAtCell = cellContainer[ni][nj];\n                    \n                    if (containerAtCell == -1) {\n                        // Empty cell - can traverse through\n                        bq.push({ni, nj});\n                    } else {\n                        // Cell has a container - can retrieve but not traverse through\n                        if (!containers[containerAtCell].retrieved && \n                            containers[containerAtCell].id < bestId) {\n                            bestId = containers[containerAtCell].id;\n                            bestIdx = containerAtCell;\n                        }\n                        // Don't push to queue - can't traverse through container\n                    }\n                }\n            }\n        }\n        \n        if (bestIdx == -1) {\n            cerr << \"Error: No accessible container found at step \" << step << endl;\n            return 1;\n        }\n        \n        containers[bestIdx].retrieved = true;\n        int ri = containers[bestIdx].pi;\n        int rj = containers[bestIdx].pj;\n        cellContainer[ri][rj] = -1; // Mark as empty now\n        retrievalOrder.push_back({ri, rj});\n    }\n    \n    // Output retrieval order\n    for (auto& [qi, qj] : retrievalOrder) {\n        cout << qi << \" \" << qj << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    // Use a 2D vector to store the grid. \n    // n=50 is small, so memory usage is negligible.\n    vector<vector<int>> grid(n, vector<int>(n));\n\n    // Read the input grid\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    // Output the grid exactly as is.\n    // Reasoning:\n    // 1. The input constraints state 1 <= c_{i,j} <= m, so there are no 0s in the input.\n    // 2. The score is (number of 0s) + 1. Since input has 0 zeros, Score = 1.\n    // 3. Score 1 is the theoretical minimum (count cannot be negative).\n    // 4. The input is guaranteed to satisfy connectivity for colors 1..m.\n    // 5. Color 0 connectivity is satisfied via the \"outside\" region (as per problem note).\n    // 6. Adjacencies are preserved because the map is identical.\n    // Thus, echoing the input is the optimal and safest strategy.\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 <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Elo-style ratings for relative weight estimation\n    vector<double> rating(N, 1000.0);\n    vector<int> comparison_count(N, 0);\n    \n    mt19937_64 rng(42);\n    \n    int queries_used = 0;\n    \n    auto update_elo = [&](int i, int j, int result) {\n        const double K = 25.0;\n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        double actual_i, actual_j;\n        if (result < 0) {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result > 0) {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else {\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n    };\n    \n    // Phase 1: Generate all pairs and shuffle\n    vector<pair<int, int>> all_pairs;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            all_pairs.push_back({i, j});\n        }\n    }\n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    \n    // Execute comparisons - MUST complete exactly Q queries\n    int pair_idx = 0;\n    while (queries_used < Q) {\n        int i, j;\n        \n        if (pair_idx < (int)all_pairs.size()) {\n            i = all_pairs[pair_idx].first;\n            j = all_pairs[pair_idx].second;\n            pair_idx++;\n        } else {\n            // Ran out of unique pairs, use random pairs\n            i = rng() % N;\n            j = rng() % N;\n            if (i == j) j = (j + 1) % N;\n        }\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        comparison_count[i]++;\n        comparison_count[j]++;\n        \n        int cmp_result = 0;\n        if (result == \"<\") cmp_result = -1;\n        else if (result == \">\") cmp_result = 1;\n        \n        update_elo(i, j, cmp_result);\n    }\n    \n    // Phase 2: Convert ratings to weights\n    vector<double> weight(N);\n    double min_rating = *min_element(rating.begin(), rating.end());\n    double max_rating = *max_element(rating.begin(), rating.end());\n    double rating_range = max(1.0, max_rating - min_rating);\n    \n    for (int i = 0; i < N; i++) {\n        double normalized = (rating[i] - min_rating) / rating_range;\n        weight[i] = exp(normalized * 5.0);\n    }\n    \n    // Phase 3: Multi-way partitioning\n    // Sort items by weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return weight[a] > weight[b];\n    });\n    \n    // Greedy assignment: heaviest items to lightest groups\n    vector<double> group_weight(D, 0.0);\n    vector<int> assignment(N, 0);\n    vector<vector<int>> groups(D);\n    \n    for (int idx : indices) {\n        int best_group = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] < group_weight[best_group]) {\n                best_group = g;\n            }\n        }\n        assignment[idx] = best_group;\n        group_weight[best_group] += weight[idx];\n        groups[best_group].push_back(idx);\n    }\n    \n    // Phase 4: Local search optimization (limited iterations for speed)\n    auto calculate_variance = [&]() -> double {\n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        double variance = 0;\n        for (int g = 0; g < D; g++) {\n            variance += (group_weight[g] - mean) * (group_weight[g] - mean);\n        }\n        return variance;\n    };\n    \n    int max_iterations = 1000;\n    for (int iter = 0; iter < max_iterations; iter++) {\n        bool improved = false;\n        \n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        // Find heaviest and lightest groups\n        int heaviest_g = 0, lightest_g = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] > group_weight[heaviest_g]) heaviest_g = g;\n            if (group_weight[g] < group_weight[lightest_g]) lightest_g = g;\n        }\n        \n        if (heaviest_g == lightest_g) break;\n        \n        // Try moving item from heaviest to lightest\n        for (int i : groups[heaviest_g]) {\n            double new_w_h = group_weight[heaviest_g] - weight[i];\n            double new_w_l = group_weight[lightest_g] + weight[i];\n            \n            double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n            double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                (new_w_l - mean) * (new_w_l - mean);\n            \n            if (new_contrib < old_contrib - 1e-9) {\n                assignment[i] = lightest_g;\n                \n                auto it = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                groups[heaviest_g].erase(it);\n                groups[lightest_g].push_back(i);\n                \n                group_weight[heaviest_g] = new_w_h;\n                group_weight[lightest_g] = new_w_l;\n                \n                improved = true;\n                break;\n            }\n        }\n        \n        // Try swapping items\n        if (!improved && !groups[heaviest_g].empty() && !groups[lightest_g].empty()) {\n            for (int i : groups[heaviest_g]) {\n                for (int j : groups[lightest_g]) {\n                    double new_w_h = group_weight[heaviest_g] - weight[i] + weight[j];\n                    double new_w_l = group_weight[lightest_g] - weight[j] + weight[i];\n                    \n                    double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                        (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n                    double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                        (new_w_l - mean) * (new_w_l - mean);\n                    \n                    if (new_contrib < old_contrib - 1e-9) {\n                        assignment[i] = lightest_g;\n                        assignment[j] = heaviest_g;\n                        \n                        auto it_i = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                        auto it_j = find(groups[lightest_g].begin(), groups[lightest_g].end(), j);\n                        *it_i = j;\n                        *it_j = i;\n                        \n                        group_weight[heaviest_g] = new_w_h;\n                        group_weight[lightest_g] = new_w_l;\n                        \n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Validate all assignments are in valid range\n    for (int i = 0; i < N; i++) {\n        if (assignment[i] < 0) assignment[i] = 0;\n        if (assignment[i] >= D) assignment[i] = D - 1;\n    }\n    \n    // Output 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 <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    \n    int bps = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<int> box_stack(n + 1);\n    vector<int> box_height(n + 1);\n    vector<bool> removed(n + 1, false);\n    \n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < bps; j++) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            box_stack[box] = i;\n            box_height[box] = j;\n        }\n    }\n    \n    vector<pair<int, int>> ops;\n    \n    auto update_positions = [&](int s) {\n        for (size_t i = 0; i < stacks[s].size(); i++) {\n            int b = stacks[s][i];\n            box_stack[b] = s;\n            box_height[b] = (int)i;\n        }\n    };\n    \n    // Estimate future energy cost to access box v from current state\n    auto estimate_access_cost = [&](int v, int current_target) -> int {\n        if (removed[v] || v <= current_target) return 0;\n        \n        int s = box_stack[v];\n        int h = box_height[v];\n        int top = (int)stacks[s].size() - 1;\n        \n        if (h == top) return 1;  // Already at top, just need to move when accessed\n        \n        // Count boxes above that will be removed before v\n        int boxes_to_move = 0;\n        for (int i = h + 1; i <= top; i++) {\n            int b = stacks[s][i];\n            if (!removed[b] && b > current_target) {\n                boxes_to_move++;\n            }\n        }\n        \n        return boxes_to_move + 1;  // Energy to clear path + move v\n    };\n    \n    // Calculate total estimated future energy for a destination choice\n    auto estimate_future_energy = [&](int dest, const vector<int>& moving_boxes, \n                                       int current_target, const vector<vector<int>>& temp_stacks) -> long long {\n        long long cost = 0;\n        \n        // Cost for boxes we're moving now (they'll need to be accessed later)\n        for (int b : moving_boxes) {\n            if (removed[b] || b <= current_target) continue;\n            \n            // Find position in destination after move\n            int future_height = (int)temp_stacks[dest].size();\n            \n            // Boxes above this in destination that will be accessed first\n            int blocking = 0;\n            for (int i = current_target + 1; i < b && i <= n; i++) {\n                if (!removed[i]) {\n                    // Check if this future target is in dest stack above our box\n                    if (box_stack[i] == dest && box_height[i] >= future_height) {\n                        blocking++;\n                    }\n                }\n            }\n            \n            cost += blocking + 1;\n        }\n        \n        // Cost for existing boxes in destination (might be blocked by our move)\n        for (size_t i = 0; i < temp_stacks[dest].size(); i++) {\n            int b = temp_stacks[dest][i];\n            if (removed[b] || b <= current_target) continue;\n            \n            // Check if any moving box blocks this\n            for (int mb : moving_boxes) {\n                if (!removed[mb] && mb > current_target && mb < b) {\n                    cost += 2;  // Will need extra move\n                }\n            }\n        }\n        \n        return cost;\n    };\n    \n    auto find_best_destination = [&](int exclude_stack, const vector<int>& moving_boxes, \n                                      int current_target) -> int {\n        int best = -1;\n        long long best_score = -1000000000000LL;\n        \n        // Create temporary stack state for simulation\n        vector<vector<int>> temp_stacks = stacks;\n        \n        for (int d = 0; d < m; d++) {\n            if (d == exclude_stack) continue;\n            \n            long long score = 0;\n            int dest_size = (int)temp_stacks[d].size();\n            \n            // Massive bonus for empty stacks (workspace)\n            if (temp_stacks[d].empty()) {\n                score += 100000000;\n            } else {\n                int dest_top = temp_stacks[d].back();\n                if (dest_top > current_target + 100) {\n                    score += (long long)dest_top * 1000;\n                } else if (dest_top > current_target + 50) {\n                    score += (long long)dest_top * 500;\n                } else if (dest_top > current_target) {\n                    score += (long long)dest_top * 200;\n                } else {\n                    score -= (long long)(current_target - dest_top + 1) * 50000;\n                }\n            }\n            \n            // Score each moving box\n            for (int b : moving_boxes) {\n                if (removed[b]) continue;\n                \n                int access_time = b - current_target;\n                \n                if (access_time > 150) {\n                    score += 30000;\n                } else if (access_time > 100) {\n                    score += 25000;\n                } else if (access_time > 50) {\n                    score += 20000;\n                } else if (access_time > 20) {\n                    score += 15000;\n                } else if (access_time > 10) {\n                    score += 10000;\n                } else if (access_time > 5) {\n                    score += 5000;\n                } else {\n                    // Very soon - should be at top of empty stack ideally\n                    if (temp_stacks[d].empty()) {\n                        score += 50000;\n                    } else {\n                        score -= 200000;\n                    }\n                }\n            }\n            \n            // Check blocking of future targets\n            for (int f = current_target + 1; f <= min(current_target + 60, n); f++) {\n                if (removed[f]) continue;\n                if (box_stack[f] == d && box_height[f] >= dest_size) {\n                    int dist = f - current_target;\n                    score -= (long long)(2000000 - dist * 20000);\n                }\n            }\n            \n            // Estimate actual future energy\n            long long future_energy = estimate_future_energy(d, moving_boxes, current_target, temp_stacks);\n            score -= future_energy * 100;\n            \n            // Stack size penalty (prefer less filled)\n            score -= (long long)temp_stacks[d].size() * 10000;\n            \n            // Bonus for good grouping (monotonic access times)\n            if (!temp_stacks[d].empty()) {\n                bool monotonic = true;\n                int last_access = temp_stacks[d].back() - current_target;\n                for (int b : moving_boxes) {\n                    if (!removed[b]) {\n                        int access = b - current_target;\n                        if (access < last_access && last_access < 50) {\n                            monotonic = false;\n                            break;\n                        }\n                        last_access = access;\n                    }\n                }\n                if (monotonic) score += 50000;\n            }\n            \n            // Prefer stacks with consistent access time ranges\n            if (!temp_stacks[d].empty()) {\n                int min_access = n, max_access = 0;\n                for (int b : temp_stacks[d]) {\n                    if (!removed[b] && b > current_target) {\n                        int access = b - current_target;\n                        min_access = min(min_access, access);\n                        max_access = max(max_access, access);\n                    }\n                }\n                if (max_access - min_access < 30) {\n                    score += 30000;\n                }\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best = d;\n            }\n        }\n        \n        if (best == -1) {\n            for (int d = 0; d < m; d++) {\n                if (d != exclude_stack) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n        \n        return best;\n    };\n    \n    // Consolidate stacks to free up workspace when beneficial\n    auto try_consolidate = [&]() {\n        int empty_count = 0;\n        for (int i = 0; i < m; i++) {\n            if (stacks[i].empty()) empty_count++;\n        }\n        \n        // If we have less than 2 empty stacks, try to consolidate\n        if (empty_count >= 2) return;\n        \n        // Find two stacks that can be merged\n        for (int i = 0; i < m; i++) {\n            if (stacks[i].empty()) continue;\n            \n            for (int j = i + 1; j < m; j++) {\n                if (stacks[j].empty()) continue;\n                \n                // Check if merging makes sense (similar access time ranges)\n                int min_i = n, max_i = 0, min_j = n, max_j = 0;\n                for (int b : stacks[i]) {\n                    if (!removed[b]) {\n                        min_i = min(min_i, b);\n                        max_i = max(max_i, b);\n                    }\n                }\n                for (int b : stacks[j]) {\n                    if (!removed[b]) {\n                        min_j = min(min_j, b);\n                        max_j = max(max_j, b);\n                    }\n                }\n                \n                // If ranges overlap significantly, consider merging\n                // (Skipping actual consolidation for simplicity - destination selection handles it)\n            }\n        }\n    };\n    \n    for (int target = 1; target <= n; target++) {\n        if (removed[target]) continue;\n        \n        int s = box_stack[target];\n        int h = box_height[target];\n        int top = (int)stacks[s].size() - 1;\n        \n        if (h == top) {\n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        } else {\n            // Collect ALL boxes above target\n            vector<int> moving_boxes;\n            for (int i = h + 1; i <= top; i++) {\n                moving_boxes.push_back(stacks[s][i]);\n            }\n            \n            int dest = find_best_destination(s, moving_boxes, target);\n            \n            int move_box = moving_boxes[0];\n            ops.push_back({move_box, dest + 1});\n            \n            stacks[s].resize(h + 1);\n            update_positions(s);\n            \n            for (int b : moving_boxes) {\n                stacks[dest].push_back(b);\n            }\n            update_positions(dest);\n            \n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        }\n        \n        // Try consolidation every 20 targets\n        if (target % 20 == 0) {\n            try_consolidate();\n        }\n    }\n    \n    for (const auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    vector<vector<int>> d(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    const int DI[] = {-1, 0, 1, 0};\n    const int DJ[] = {0, 1, 0, -1};\n    const char DIR[] = {'U', 'R', 'D', 'L'};\n    \n    // Check if move is valid (no wall)\n    auto can_move = [&](int i, int j, int dir) -> bool {\n        int ni = i + DI[dir], nj = j + DJ[dir];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        \n        if (dir == 0 && i > 0 && h[i-1][j] == '1') return false;\n        if (dir == 1 && v[i][j] == '1') return false;\n        if (dir == 2 && h[i][j] == '1') return false;\n        if (dir == 3 && j > 0 && v[i][j-1] == '1') return false;\n        \n        return true;\n    };\n    \n    // BFS to find shortest path from (si,sj) to (ti,tj)\n    auto find_path = [&](int si, int sj, int ti, int tj) -> string {\n        if (si == ti && sj == tj) return \"\";\n        \n        vector<vector<int>> bd(N, vector<int>(N, -1));\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n        vector<vector<int>> pdir(N, vector<int>(N, -1));\n        queue<pair<int,int>> bq;\n        \n        bd[si][sj] = 0;\n        bq.push({si, sj});\n        \n        while (!bq.empty()) {\n            auto [i, j] = bq.front();\n            bq.pop();\n            \n            if (i == ti && j == tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (can_move(i, j, dir)) {\n                    int ni = i + DI[dir], nj = j + DJ[dir];\n                    if (bd[ni][nj] == -1) {\n                        bd[ni][nj] = bd[i][j] + 1;\n                        parent[ni][nj] = {i, j};\n                        pdir[ni][nj] = dir;\n                        bq.push({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (bd[ti][tj] == -1) return \"\";\n        \n        string path = \"\";\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path += DIR[pdir[ci][cj]];\n            auto [pi, pj] = parent[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    // Create priority list of squares (higher d = higher priority for revisits)\n    vector<tuple<int, int, int>> squares;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            squares.push_back({d[i][j], i, j});\n        }\n    }\n    sort(squares.rbegin(), squares.rend());\n    \n    // DFS to create initial route that visits all squares and returns to (0,0)\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string route = \"\";\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        // Sort neighbors by d value (visit high-d squares first in spanning tree)\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            if (can_move(i, j, dir)) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        \n        for (auto [val, dir] : neighbors) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            route += DIR[dir];\n            dfs(ni, nj);\n            // Return: opposite direction - this ensures we return to (i,j)\n            int opp_dir = (dir + 2) % 4;\n            route += DIR[opp_dir];\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Verify the route ends at (0,0)\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    // If not at (0,0), add return path\n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        route += back;\n    }\n    \n    // Now optimize: add revisits to high-priority squares\n    // Strategy: insert round-trips to high-d squares at strategic points\n    const int MAX_LEN = 100000;\n    \n    if ((int)route.length() < MAX_LEN - 1000) {\n        // Calculate current visit counts\n        vector<vector<int>> visit_count(N, vector<int>(N, 0));\n        int pi = 0, pj = 0;\n        visit_count[0][0]++;\n        \n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            visit_count[pi][pj]++;\n        }\n        \n        // Try to add revisits to high-priority squares\n        // We'll insert round-trips at positions where we're close to target squares\n        string optimized = route;\n        \n        // Find all positions in the route\n        vector<pair<int,int>> positions;\n        positions.push_back({0, 0});\n        pi = 0; pj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            positions.push_back({pi, pj});\n        }\n        \n        // Add revisits to top priority squares\n        for (auto [val, ti, tj] : squares) {\n            if ((int)optimized.length() >= MAX_LEN - 500) break;\n            \n            // Find the closest position in route to this square\n            int best_idx = -1;\n            int best_dist = N * N;\n            for (int idx = 0; idx < (int)positions.size(); idx++) {\n                int dist = abs(positions[idx].first - ti) + abs(positions[idx].second - tj);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_idx = idx;\n                }\n            }\n            \n            if (best_idx >= 0 && best_dist < N) {\n                // Check if we should add a revisit\n                int current_visits = visit_count[ti][tj];\n                int target_visits = max(2, (int)(val * optimized.length() / 50000));\n                \n                if (current_visits < target_visits) {\n                    // Insert a round-trip to (ti, tj) at position best_idx\n                    int pi_pos = positions[best_idx].first;\n                    int pj_pos = positions[best_idx].second;\n                    \n                    string to_target = find_path(pi_pos, pj_pos, ti, tj);\n                    string back = find_path(ti, tj, pi_pos, pj_pos);\n                    \n                    if (!to_target.empty() && !back.empty() && \n                        (int)optimized.length() + (int)to_target.length() + (int)back.length() < MAX_LEN - 100) {\n                        // Insert at position best_idx\n                        string new_route = optimized.substr(0, best_idx);\n                        new_route += to_target + back;\n                        new_route += optimized.substr(best_idx);\n                        optimized = new_route;\n                        visit_count[ti][tj]++;\n                        \n                        // Update positions (simplified - just add the detour positions)\n                        // This is approximate but should work for validation\n                    }\n                }\n            }\n        }\n        \n        route = optimized;\n    }\n    \n    // Final validation: ensure route ends at (0,0)\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n            route += back;\n        } else {\n            // Truncate and add return path\n            route = route.substr(0, MAX_LEN - (int)back.length() - 10);\n            route += back;\n        }\n    }\n    \n    // Final validation: ensure all squares visited\n    vector<vector<bool>> final_visited(N, vector<bool>(N, false));\n    int vi = 0, vj = 0;\n    final_visited[0][0] = true;\n    \n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                vi += DI[dir];\n                vj += DJ[dir];\n                break;\n            }\n        }\n        if (vi < 0 || vi >= N || vj < 0 || vj >= N) {\n            // Invalid move - this shouldn't happen\n            cerr << \"Invalid move detected!\" << endl;\n            return 1;\n        }\n        final_visited[vi][vj] = true;\n    }\n    \n    // If any square not visited, we have a problem - but DFS should have visited all\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!final_visited[i][j]) {\n                cerr << \"Square (\" << i << \",\" << j << \") not visited!\" << endl;\n                // Try to add it if possible\n                if ((int)route.length() < MAX_LEN - 500) {\n                    string to_sq = find_path(0, 0, i, j);\n                    string back = find_path(i, j, 0, 0);\n                    if (!to_sq.empty() && !back.empty()) {\n                        route = to_sq + back + route;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure length constraint\n    if ((int)route.length() > MAX_LEN) {\n        route = route.substr(0, MAX_LEN);\n        // Re-validate end position\n        ci = 0; cj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n        }\n        if (ci != 0 || cj != 0) {\n            string back = find_path(ci, cj, 0, 0);\n            if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n                route += back;\n            }\n        }\n    }\n    \n    // One final check\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        // This is a critical error - truncate to make it valid\n        cerr << \"Warning: Route does not end at (0,0), truncating\" << endl;\n        // Find the last position that was at (0,0)\n        int last_zero = 0;\n        ci = 0; cj = 0;\n        for (int idx = 0; idx < (int)route.length(); idx++) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == route[idx]) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n            if (ci == 0 && cj == 0) {\n                last_zero = idx + 1;\n            }\n        }\n        route = route.substr(0, last_zero);\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<string> grid;\nvector<string> targets;\nvector<vector<pair<int, int>>> char_positions;\nvector<vector<int>> overlap;\nvector<vector<int>> min_dist;\n\ninline int dist(pair<int, int> p1, pair<int, int> p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\nint calc_overlap(const string& a, const string& b) {\n    int max_ov = 0;\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = 1; len <= max_len; len++) {\n        if (a.substr(a.size() - len) == b.substr(0, len)) {\n            max_ov = len;\n        }\n    }\n    return max_ov;\n}\n\n// Precompute minimum distance between any positions of two characters\nvoid precompute_min_dist() {\n    min_dist.assign(26, vector<int>(26, INT_MAX));\n    for (int c1 = 0; c1 < 26; c1++) {\n        for (int c2 = 0; c2 < 26; c2++) {\n            for (auto& p1 : char_positions[c1]) {\n                for (auto& p2 : char_positions[c2]) {\n                    min_dist[c1][c2] = min(min_dist[c1][c2], dist(p1, p2));\n                }\n            }\n        }\n    }\n}\n\n// Build solution with look-ahead position selection\npair<string, vector<pair<int, int>>> build_solution_lookahead(const vector<int>& order, int& total_cost, int lookahead = 2) {\n    string S;\n    S.reserve(1000);\n    vector<pair<int, int>> positions;\n    positions.reserve(5000);\n    pair<int, int> cur_pos = {si, sj};\n    total_cost = 0;\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        int overlap_len = 0;\n        \n        if ((int)S.size() >= 4) {\n            for (int len = min(5, (int)S.size()); len >= 1; len--) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    if (S[S.size() - len + k] != t[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        for (int i = overlap_len; i < 5; i++) {\n            char c = t[i];\n            int c_idx = c - 'A';\n            const auto& positions_c = char_positions[c_idx];\n            \n            // Look-ahead: consider cost to next characters\n            pair<int, int> best_pos = positions_c[0];\n            int best_score = INT_MAX;\n            \n            // Collect next characters for look-ahead\n            vector<int> next_chars;\n            int temp_i = i + 1;\n            int temp_idx = idx;\n            while ((int)next_chars.size() < lookahead) {\n                if (temp_i < 5) {\n                    next_chars.push_back(targets[temp_idx][temp_i] - 'A');\n                    temp_i++;\n                } else {\n                    // Find next string's first char\n                    bool found = false;\n                    for (int k = idx + 1; k < (int)order.size() && (int)next_chars.size() < lookahead; k++) {\n                        next_chars.push_back(targets[order[k]][0] - 'A');\n                        found = true;\n                        break;\n                    }\n                    if (!found) break;\n                }\n            }\n            \n            for (auto& pos : positions_c) {\n                int score = dist(cur_pos, pos);\n                \n                // Add look-ahead cost (weighted)\n                pair<int, int> prev_pos = pos;\n                for (size_t k = 0; k < next_chars.size(); k++) {\n                    int next_c = next_chars[k];\n                    int min_d = INT_MAX;\n                    for (auto& np : char_positions[next_c]) {\n                        min_d = min(min_d, dist(prev_pos, np));\n                    }\n                    score += min_d * (1.0 / (k + 1)); // Decreasing weight\n                    // Find best next position for continuation\n                    for (auto& np : char_positions[next_c]) {\n                        if (dist(prev_pos, np) == min_d) {\n                            prev_pos = np;\n                            break;\n                        }\n                    }\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_pos = pos;\n                }\n            }\n            \n            total_cost += dist(cur_pos, best_pos) + 1;\n            positions.push_back(best_pos);\n            S += c;\n            cur_pos = best_pos;\n        }\n    }\n    \n    return {S, positions};\n}\n\nbool check_coverage_fast(const string& S) {\n    for (int i = 0; i < M; i++) {\n        if (S.find(targets[i]) == string::npos) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Fast cost estimation without full build (for local search)\nint estimate_cost(const vector<int>& order, pair<int, int> start_pos) {\n    int cost = 0;\n    pair<int, int> cur_pos = start_pos;\n    string last_str = \"\";\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        int overlap_len = 0;\n        \n        if (!last_str.empty()) {\n            for (int len = min(5, (int)last_str.size()); len >= 1; len--) {\n                if (last_str.substr(last_str.size() - len) == t.substr(0, len)) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        for (int i = overlap_len; i < 5; i++) {\n            int c_idx = t[i] - 'A';\n            int min_d = INT_MAX;\n            for (auto& pos : char_positions[c_idx]) {\n                min_d = min(min_d, dist(cur_pos, pos));\n            }\n            cost += min_d + 1;\n            // Estimate new position as average of character positions\n            if (!char_positions[c_idx].empty()) {\n                cur_pos = char_positions[c_idx][0];\n            }\n        }\n        \n        last_str = t;\n    }\n    \n    return cost;\n}\n\nvector<int> build_greedy_order(mt19937& rng, bool randomize = false, bool use_position_cost = false) {\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    \n    uniform_int_distribution<int> dist_int(0, M - 1);\n    int start = randomize ? dist_int(rng) : 0;\n    \n    order.push_back(start);\n    used[start] = true;\n    \n    // Track estimated current position\n    pair<int, int> est_pos = {si, sj};\n    \n    for (int step = 1; step < M; step++) {\n        int last = order.back();\n        vector<pair<double, int>> candidates;\n        \n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                double score = overlap[last][i];\n                \n                if (use_position_cost) {\n                    // Factor in position distance\n                    int first_c = targets[i][overlap[last][i]] - 'A';\n                    int min_d = INT_MAX;\n                    for (auto& pos : char_positions[first_c]) {\n                        min_d = min(min_d, dist(est_pos, pos));\n                    }\n                    score = score * 2.0 - min_d * 0.1;\n                }\n                \n                candidates.push_back({score, i});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), [](const pair<double,int>& a, const pair<double,int>& b) {\n            return a.first > b.first;\n        });\n        \n        int top_k = randomize ? min((int)candidates.size(), 25) : 1;\n        uniform_int_distribution<int> pick_dist(0, top_k - 1);\n        int pick_idx = randomize ? pick_dist(rng) : 0;\n        int best_next = candidates[pick_idx].second;\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n        \n        // Update estimated position\n        int ov = overlap[last][best_next];\n        int first_c = targets[best_next][ov] - 'A';\n        if (!char_positions[first_c].empty()) {\n            int min_d = INT_MAX;\n            for (auto& pos : char_positions[first_c]) {\n                int d = dist(est_pos, pos);\n                if (d < min_d) {\n                    min_d = d;\n                    est_pos = pos;\n                }\n            }\n        }\n    }\n    \n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    grid.resize(N);\n    char_positions.resize(26);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    precompute_min_dist();\n    \n    overlap.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) {\n                overlap[i][j] = calc_overlap(targets[i], targets[j]);\n            }\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> best_order;\n    vector<pair<int, int>> best_positions;\n    int best_cost = INT_MAX;\n    \n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // Phase 1: Generate diverse initial solutions (0-600ms)\n    int trial = 0;\n    while (get_elapsed_ms() < 600) {\n        bool randomize = (trial % 2 != 0);\n        bool use_pos = (trial % 3 == 0);\n        vector<int> order = build_greedy_order(rng, randomize, use_pos);\n        \n        int cost;\n        auto [S, positions] = build_solution_lookahead(order, cost, 2);\n        \n        if ((int)positions.size() <= 5000 && check_coverage_fast(S)) {\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_order = order;\n                best_positions = positions;\n            }\n        }\n        trial++;\n    }\n    \n    // Phase 2: Local search with adjacent swaps (600-1200ms)\n    if (!best_order.empty()) {\n        uniform_int_distribution<int> swap_dist(0, M - 2);\n        \n        while (get_elapsed_ms() < 1200) {\n            bool improved = false;\n            \n            for (int iter = 0; iter < 50 && get_elapsed_ms() < 1200; iter++) {\n                int i = swap_dist(rng);\n                \n                vector<int> new_order = best_order;\n                swap(new_order[i], new_order[i + 1]);\n                \n                int cost;\n                auto [S, positions] = build_solution_lookahead(new_order, cost, 2);\n                \n                if ((int)positions.size() <= 5000 && check_coverage_fast(S) && cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                    improved = true;\n                }\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Phase 3: 2-opt local search (1200-1600ms)\n    if (!best_order.empty()) {\n        while (get_elapsed_ms() < 1600) {\n            bool improved = false;\n            \n            for (int i = 0; i < M - 2 && get_elapsed_ms() < 1600; i++) {\n                for (int j = i + 2; j < min(i + 10, M); j++) {\n                    vector<int> new_order = best_order;\n                    reverse(new_order.begin() + i + 1, new_order.begin() + j + 1);\n                    \n                    int cost;\n                    auto [S, positions] = build_solution_lookahead(new_order, cost, 2);\n                    \n                    if ((int)positions.size() <= 5000 && check_coverage_fast(S) && cost < best_cost - 10) {\n                        best_cost = cost;\n                        best_order = new_order;\n                        best_positions = positions;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Phase 4: Simulated annealing (1600-1900ms)\n    if (!best_order.empty()) {\n        double temperature = best_cost * 0.15;\n        double cooling_rate = 0.995;\n        uniform_real_distribution<double> dist_real(0.0, 1.0);\n        uniform_int_distribution<int> swap_dist(0, M - 2);\n        \n        vector<int> current_order = best_order;\n        int current_cost = best_cost;\n        \n        while (get_elapsed_ms() < 1900) {\n            int i = swap_dist(rng);\n            int j = i + 1 + (rng() % min(5, M - i - 1));\n            j = min(j, M - 1);\n            \n            vector<int> new_order = current_order;\n            swap(new_order[i], new_order[j]);\n            \n            int cost;\n            auto [S, positions] = build_solution_lookahead(new_order, cost, 2);\n            \n            bool accept = false;\n            if ((int)positions.size() <= 5000 && check_coverage_fast(S)) {\n                if (cost < current_cost) {\n                    accept = true;\n                } else if (temperature > 1) {\n                    double delta = (double)(cost - current_cost);\n                    double prob = exp(-delta / temperature);\n                    if (dist_real(rng) < prob) {\n                        accept = true;\n                    }\n                }\n            }\n            \n            if (accept) {\n                current_order = new_order;\n                current_cost = cost;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n    }\n    \n    // Final rebuild with best order and full look-ahead\n    if (!best_order.empty()) {\n        int cost;\n        auto [S, positions] = build_solution_lookahead(best_order, cost, 3);\n        best_positions = positions;\n    }\n    \n    // Fallback\n    if (best_positions.empty()) {\n        pair<int, int> cur_pos = {si, sj};\n        for (int i = 0; i < M; i++) {\n            for (char c : targets[i]) {\n                int c_idx = c - 'A';\n                pair<int, int> best_pos = char_positions[c_idx][0];\n                for (auto& pos : char_positions[c_idx]) {\n                    if (dist(cur_pos, pos) < dist(cur_pos, best_pos)) {\n                        best_pos = pos;\n                    }\n                }\n                best_positions.push_back(best_pos);\n                cur_pos = best_pos;\n            }\n        }\n    }\n    \n    for (auto& p : best_positions) {\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 <random>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for problem data\nint N, M;\ndouble eps;\nstruct Shape {\n    int id;\n    vector<pair<int, int>> cells;\n    int max_r, max_c;\n};\nvector<Shape> shapes;\n\n// Interaction functions\nvoid query_drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n}\n\nint read_drill() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid query_divine(const vector<pair<int, int>>& pts) {\n    cout << \"q \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_divine() {\n    int v;\n    cin >> v;\n    return v;\n}\n\nvoid guess(const vector<pair<int, int>>& pts) {\n    cout << \"a \" << pts.size();\n    for (auto p : pts) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n}\n\nint read_guess() {\n    int res;\n    cin >> res;\n    return res;\n}\n\n// Solver state\nvector<double> target_row_sum, target_col_sum;\nvector<int> current_pos; // r0, c0, r1, c1, ...\n\n// Evaluate loss\ndouble evaluate_loss(const vector<int>& pos) {\n    vector<int> r_sum(N, 0), c_sum(N, 0);\n    for (int k = 0; k < M; ++k) {\n        int r = pos[2 * k];\n        int c = pos[2 * k + 1];\n        const auto& shape = shapes[k];\n        for (auto& cell : shape.cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            // Bounds check technically not needed if pos is valid, but safe\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                r_sum[rr]++;\n                c_sum[cc]++;\n            }\n        }\n    }\n    double loss = 0;\n    for (int i = 0; i < N; ++i) {\n        double diff = r_sum[i] - target_row_sum[i];\n        loss += diff * diff;\n        diff = c_sum[i] - target_col_sum[i];\n        loss += diff * diff;\n    }\n    return loss;\n}\n\nint main() {\n    // Fast IO\n    cin.tie(NULL);\n    cout.tie(NULL);\n\n    // Read Input\n    if (!(cin >> N >> M >> eps)) return 0;\n    shapes.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shapes[k].id = k;\n        shapes[k].cells.resize(d);\n        int max_r = -1, max_c = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k].cells[i].first >> shapes[k].cells[i].second;\n            max_r = max(max_r, shapes[k].cells[i].first);\n            max_c = max(max_c, shapes[k].cells[i].second);\n        }\n        shapes[k].max_r = max_r;\n        shapes[k].max_c = max_c;\n    }\n\n    // 1. Query Rows and Cols\n    target_row_sum.resize(N);\n    target_col_sum.resize(N);\n    \n    // Helper to get target sum from observation\n    auto get_target = [&](int obs, int k) {\n        double mu = k * eps;\n        double scale = 1.0 - 2.0 * eps;\n        if (abs(scale) < 1e-9) return 0.0; \n        double est = (obs - mu) / scale;\n        return max(0.0, est);\n    };\n\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_pts;\n        row_pts.reserve(N);\n        for (int j = 0; j < N; ++j) row_pts.push_back({i, j});\n        query_divine(row_pts);\n        int obs = read_divine();\n        target_row_sum[i] = get_target(obs, N);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_pts;\n        col_pts.reserve(N);\n        for (int i = 0; i < N; ++i) col_pts.push_back({i, j});\n        query_divine(col_pts);\n        int obs = read_divine();\n        target_col_sum[j] = get_target(obs, N);\n    }\n\n    // 2. Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    current_pos.resize(2 * M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = N - 1 - shapes[k].max_r;\n        int max_c = N - 1 - shapes[k].max_c;\n        // Ensure non-negative range\n        if (max_r < 0) max_r = 0;\n        if (max_c < 0) max_c = 0;\n        current_pos[2 * k] = uniform_int_distribution<>(0, max_r)(rng);\n        current_pos[2 * k + 1] = uniform_int_distribution<>(0, max_c)(rng);\n    }\n\n    double current_loss = evaluate_loss(current_pos);\n    double best_loss = current_loss;\n    vector<int> best_pos = current_pos;\n\n    double temp = 100.0;\n    double cooling_rate = 0.995;\n    auto start_time = chrono::steady_clock::now();\n    \n    // Run SA for up to 2.0 seconds\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 2.0) break;\n        \n        // Propose move\n        int k = uniform_int_distribution<>(0, M - 1)(rng);\n        int dim = uniform_int_distribution<>(0, 1)(rng); // 0 for r, 1 for c\n        int delta = uniform_int_distribution<>(-1, 1)(rng);\n        if (delta == 0) delta = 1;\n        \n        int idx = 2 * k + dim;\n        int old_val = current_pos[idx];\n        int new_val = old_val + delta;\n        \n        int max_val = N - 1 - (dim == 0 ? shapes[k].max_r : shapes[k].max_c);\n        if (new_val < 0 || new_val > max_val) continue;\n        \n        current_pos[idx] = new_val;\n        double new_loss = evaluate_loss(current_pos);\n        \n        double diff = new_loss - current_loss;\n        \n        if (diff < 0 || exp(-diff / temp) > uniform_real_distribution<>(0.0, 1.0)(rng)) {\n            current_loss = new_loss;\n            if (new_loss < best_loss) {\n                best_loss = new_loss;\n                best_pos = current_pos;\n            }\n        } else {\n            current_pos[idx] = old_val; // Revert\n        }\n        \n        temp *= cooling_rate;\n        if (temp < 1e-3) break;\n    }\n\n    // 3. Generate Prediction\n    vector<pair<int, int>> s_cand;\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        int r = best_pos[2 * k];\n        int c = best_pos[2 * k + 1];\n        for (auto& cell : shapes[k].cells) {\n            int rr = r + cell.first;\n            int cc = c + cell.second;\n            if (rr >= 0 && rr < N && cc >= 0 && cc < N) {\n                grid[rr][cc]++;\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                s_cand.push_back({i, j});\n            }\n        }\n    }\n\n    // 4. Verify Rest (Drill all cells not in s_cand)\n    // This ensures we don't miss any oil (False Negatives).\n    // False Positives in s_cand are risked but unlikely if loss is low.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 0) {\n                query_drill(i, j);\n                int v = read_drill();\n                if (v > 0) {\n                    s_cand.push_back({i, j});\n                    grid[i][j] = v;\n                }\n            }\n        }\n    }\n\n    // 5. Guess\n    // Sort s_cand for consistency\n    sort(s_cand.begin(), s_cand.end());\n    // Remove duplicates just in case (logic shouldn't produce any)\n    s_cand.erase(unique(s_cand.begin(), s_cand.end()), s_cand.end());\n    \n    guess(s_cand);\n    int res = read_guess();\n    if (res == 1) return 0;\n    \n    // If wrong, we could try to recover, but for this solution we exit.\n    // In a contest, one might fallback to drilling everything if guess fails.\n    // But we already drilled s_rest. The only error source is s_cand false positives.\n    // To fix, we would need to drill s_cand cells to check if v=0.\n    // Given time limit, we stop.\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global constants\nconst int W = 1000;\n\n// Problem data\nint D, N;\nvector<vector<int>> a; // a[d][k]\n\n// Grid dimensions\nint R, C;\n\n// State: H[d][r], W[d][c]\n// Using vector of vectors\nvector<vector<int>> H;\nvector<vector<int>> W_vec; // Renamed to W_vec to avoid conflict with constant W\n\n// Mapping from k to (r, c)\npair<int, int> get_rc(int k) {\n    return {k / C, k % C};\n}\n\n// Calculate total cost\nlong long calculate_cost() {\n    long long total_cost = 0;\n    \n    // Area costs\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                total_cost += 100LL * (a[d][k] - area);\n            }\n        }\n    }\n    \n    // Partition costs\n    for (int d = 1; d < D; ++d) {\n        // Horizontal lines\n        int y_prev = 0;\n        int y_curr = 0;\n        for (int r = 0; r < R; ++r) {\n            y_prev += H[d-1][r];\n            y_curr += H[d][r];\n            total_cost += (long long)W * abs(y_prev - y_curr);\n        }\n        // Vertical lines\n        int x_prev = 0;\n        int x_curr = 0;\n        for (int c = 0; c < C; ++c) {\n            x_prev += W_vec[d-1][c];\n            x_curr += W_vec[d][c];\n            total_cost += (long long)W * abs(x_prev - x_curr);\n        }\n    }\n    \n    return total_cost;\n}\n\n// Calculate delta cost for a change in H[d][r] or W_vec[d][c]\n// This is more efficient for SA\nlong long calculate_delta_cost(int d, int type, int idx, int delta) {\n    // type 0: H, 1: W_vec\n    long long delta_cost = 0;\n    \n    // Area cost change for day d\n    if (type == 0) { // H[d][idx] changes by delta\n        int r = idx;\n        int old_h = H[d][r];\n        int new_h = old_h + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kr == r) {\n                long long old_area = (long long)old_h * W_vec[d][kc];\n                long long new_area = (long long)new_h * W_vec[d][kc];\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    } else { // W_vec[d][idx] changes by delta\n        int c = idx;\n        int old_w = W_vec[d][c];\n        int new_w = old_w + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kc == c) {\n                long long old_area = (long long)H[d][kr] * old_w;\n                long long new_area = (long long)H[d][kr] * new_w;\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    }\n    \n    // Partition cost change\n    // Affected days: d (with d-1) and d+1 (with d)\n    // If d=0, only d+1. But L_0=0, so partition cost starts from d=1.\n    // Partition cost between d-1 and d depends on cumulative sums at d-1 and d.\n    // Changing H[d][idx] changes cumulative sums for r >= idx on day d.\n    \n    auto update_partition = [&](int day_idx, int type_p, int idx_p, int delta_p) {\n        // day_idx is the day being modified (d)\n        // We need to compare with day_idx-1 and day_idx+1\n        long long cost_change = 0;\n        \n        // Compare with day_idx - 1\n        if (day_idx > 0) {\n            int sum_prev = 0;\n            int sum_curr = 0;\n            // We only need to sum from idx_p to end because before idx_p sums are same\n            // But wait, cumulative sum at r depends on H[0]...H[r].\n            // If H[idx] changes, all cumulative sums Y_r for r > idx change.\n            // Y_idx also changes.\n            // So for all r from idx to R-1, Y_r changes by delta_p.\n            // Cost adds W * |delta_p| for each such line.\n            // Number of lines affected: R - idx_p.\n            // Wait, lines are at Y_1, ..., Y_R.\n            // Y_r = sum(H[0]...H[r-1]).\n            // If H[idx] changes, Y_r changes for r > idx.\n            // So lines Y_{idx+1} ... Y_R change.\n            // Count = R - idx.\n            // But Y_R is at W (fixed sum), so Y_R doesn't change?\n            // We enforce sum H = W. So if H[idx] += delta, some H[other] -= delta.\n            // So Y_R remains W.\n            // So lines affected are those between idx and the 'other' index.\n            // This makes delta calculation complex if we swap.\n            // Let's stick to full cost recalc for partition if needed, or simplify.\n            // Given N is small, full partition cost recalc for affected days is fast.\n            // Affected days: d-1 (boundary d-1|d) and d (boundary d|d+1).\n            // Just recalc partition cost for these two boundaries.\n        }\n        return cost_change;\n    };\n\n    // Simpler approach: Recalculate partition cost for boundaries involving day d.\n    // Boundaries: (d-1, d) and (d, d+1).\n    // Store previous partition cost for these boundaries to subtract.\n    // But implementing this cleanly is verbose.\n    // Given the speed of O(N) area calc, O(R+C) partition calc is also fast.\n    // Let's just calculate the delta for partition explicitly.\n    \n    // Partition cost contribution of day d with d-1:\n    // Sum_r W * |Y_{d,r} - Y_{d-1,r}|\n    // If H[d][idx] changes by delta, Y_{d,r} changes by delta for r > idx.\n    // (Assuming we adjust another H[d][other] to keep sum constant).\n    // If we do swap move (H[idx]+=1, H[other]-=1), then Y_r changes by 1 for r in (min, max].\n    // This is getting complicated for delta.\n    // Given 3 seconds, we can afford O(R+C) per step.\n    // Let's implement a function that recalculates partition cost for day d boundaries.\n    \n    return delta_cost; // Placeholder, will implement full delta in SA loop or use full cost for safety if fast enough\n}\n\n// Function to calculate partition cost between day d1 and d2\nlong long calc_partition_between(int d1, int d2) {\n    long long cost = 0;\n    int y1 = 0, y2 = 0;\n    for (int r = 0; r < R; ++r) {\n        y1 += H[d1][r];\n        y2 += H[d2][r];\n        cost += (long long)W * abs(y1 - y2);\n    }\n    int x1 = 0, x2 = 0;\n    for (int c = 0; c < C; ++c) {\n        x1 += W_vec[d1][c];\n        x2 += W_vec[d2][c];\n        cost += (long long)W * abs(x1 - x2);\n    }\n    return cost;\n}\n\n// Global current cost\nlong long current_cost = 0;\n\nvoid update_cost_after_change(int d, const vector<int>& old_H, const vector<int>& old_W) {\n    // Recompute area cost for day d\n    // Recompute partition cost for (d-1, d) and (d, d+1)\n    // This is O(N + R + C).\n    \n    // We need to subtract old contributions and add new.\n    // To do this cleanly, we need to store per-day costs.\n    // Let's store vector<long long> area_cost(D), partition_cost(D) (cost between d-1 and d)\n    // partition_cost[0] = 0.\n    // Total = sum(area) + sum(partition).\n}\n\n// Let's use a simpler SA structure where we just recompute necessary parts.\n// Since D is small, we can store per-day area cost and per-boundary partition cost.\nvector<long long> day_area_cost;\nvector<long long> boundary_part_cost; // size D, boundary_part_cost[d] is cost between d-1 and d. [0] is 0.\n\nvoid init_costs() {\n    day_area_cost.assign(D, 0);\n    boundary_part_cost.assign(D, 0);\n    \n    for (int d = 0; d < D; ++d) {\n        long long cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                cost += 100LL * (a[d][k] - area);\n            }\n        }\n        day_area_cost[d] = cost;\n    }\n    \n    for (int d = 1; d < D; ++d) {\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n    }\n    \n    current_cost = 0;\n    for (long long c : day_area_cost) current_cost += c;\n    for (long long c : boundary_part_cost) current_cost += c;\n}\n\nvoid apply_move_and_update(int d, int type, int idx, int delta) {\n    // Apply move\n    if (type == 0) {\n        H[d][idx] += delta;\n    } else {\n        W_vec[d][idx] += delta;\n    }\n    \n    // Update day_area_cost[d]\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    // Update boundary_part_cost[d] (between d-1 and d)\n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    // Update boundary_part_cost[d+1] (between d and d+1)\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nvoid revert_move_and_update(int d, int type, int idx, int delta) {\n    // Revert\n    if (type == 0) {\n        H[d][idx] -= delta;\n    } else {\n        W_vec[d][idx] -= delta;\n    }\n    \n    // Recalculate costs (same as apply, effectively undoing the change in values)\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int W_in;\n    if (!(cin >> W_in >> D >> N)) return 0;\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    // Determine R, C\n    // Try to find R that minimizes initial area cost heuristic\n    int best_R = 1;\n    long long min_init_cost = -1;\n    \n    for (int r_try = 1; r_try <= N; ++r_try) {\n        int c_try = (N + r_try - 1) / r_try;\n        // Heuristic cost estimate\n        // Distribute W to rows/cols based on sqrt(area)\n        long long est_cost = 0;\n        // Just pick the one closest to square\n        if (min_init_cost == -1 || abs(r_try - c_try) < abs(best_R - (N + best_R - 1) / best_R)) {\n             best_R = r_try;\n        }\n    }\n    // Prefer square-ish\n    best_R = max(1, (int)round(sqrt(N)));\n    R = best_R;\n    C = (N + R - 1) / R;\n    \n    // Initialize H and W_vec\n    H.assign(D, vector<int>(R));\n    W_vec.assign(D, vector<int>(C));\n    \n    mt19937 rng(12345);\n    \n    for (int d = 0; d < D; ++d) {\n        // Calculate target \"weight\" for each row and col\n        vector<long long> row_weight(R, 0);\n        vector<long long> col_weight(C, 0);\n        \n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            // Use sqrt of area as weight\n            long long w = (long long)sqrt(a[d][k]) + 1;\n            row_weight[r] += w;\n            col_weight[c] += w;\n        }\n        \n        long long sum_rw = accumulate(row_weight.begin(), row_weight.end(), 0LL);\n        long long sum_cw = accumulate(col_weight.begin(), col_weight.end(), 0LL);\n        \n        // Distribute W\n        int rem_h = W;\n        for (int r = 0; r < R; ++r) {\n            int h = (sum_rw == 0) ? W/R : (int)((double)row_weight[r] / sum_rw * W);\n            H[d][r] = h;\n            rem_h -= h;\n        }\n        // Distribute remainder\n        int r_idx = 0;\n        while (rem_h > 0) {\n            H[d][r_idx % R]++;\n            rem_h--;\n            r_idx++;\n        }\n        // Ensure min 1\n        for(int r=0; r<R; ++r) if(H[d][r] < 1) H[d][r] = 1;\n        // Re-normalize sum to W (simple adjust)\n        int sum_h = accumulate(H[d].begin(), H[d].end(), 0);\n        if (sum_h != W) {\n            H[d][0] += (W - sum_h);\n        }\n        \n        int rem_w = W;\n        for (int c = 0; c < C; ++c) {\n            int w = (sum_cw == 0) ? W/C : (int)((double)col_weight[c] / sum_cw * W);\n            W_vec[d][c] = w;\n            rem_w -= w;\n        }\n        int c_idx = 0;\n        while (rem_w > 0) {\n            W_vec[d][c_idx % C]++;\n            rem_w--;\n            c_idx++;\n        }\n        for(int c=0; c<C; ++c) if(W_vec[d][c] < 1) W_vec[d][c] = 1;\n        int sum_w = accumulate(W_vec[d].begin(), W_vec[d].end(), 0);\n        if (sum_w != W) {\n            W_vec[d][0] += (W - sum_w);\n        }\n    }\n    \n    init_costs();\n    \n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double T = 10000.0;\n    double T_end = 1.0;\n    double alpha = 0.99995;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break; // Leave margin\n        \n        // Pick move\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        int type = uniform_int_distribution<int>(0, 1)(rng); // 0: H, 1: W\n        int dim = (type == 0) ? R : C;\n        int idx = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        // Pick another index to swap with to maintain sum\n        int idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        while (idx2 == idx) idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 1)(rng)) delta = -1;\n        \n        // Check validity (must be >= 1)\n        if (type == 0) {\n            if (H[d][idx] + delta < 1 || H[d][idx2] - delta < 1) continue;\n        } else {\n            if (W_vec[d][idx] + delta < 1 || W_vec[d][idx2] - delta < 1) continue;\n        }\n        \n        // Apply first change\n        if (type == 0) H[d][idx] += delta;\n        else W_vec[d][idx] += delta;\n        \n        // Calculate cost delta roughly? \n        // No, let's just apply both and calc cost.\n        if (type == 0) H[d][idx2] -= delta;\n        else W_vec[d][idx2] -= delta;\n        \n        // We need to calculate new cost efficiently.\n        // Since we changed two indices, we can just recompute day_area_cost[d] and boundaries.\n        // Store old values to revert if rejected.\n        int old_val1 = (type == 0) ? H[d][idx] - delta : W_vec[d][idx] - delta;\n        int old_val2 = (type == 0) ? H[d][idx2] + delta : W_vec[d][idx2] + delta;\n        \n        long long old_day_cost = day_area_cost[d];\n        long long old_bound1 = (d > 0) ? boundary_part_cost[d] : 0;\n        long long old_bound2 = (d < D-1) ? boundary_part_cost[d+1] : 0;\n        \n        // Recompute area cost\n        long long new_area_cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                new_area_cost += 100LL * (a[d][k] - area);\n            }\n        }\n        \n        long long new_bound1 = 0, new_bound2 = 0;\n        if (d > 0) new_bound1 = calc_partition_between(d-1, d);\n        if (d < D-1) new_bound2 = calc_partition_between(d, d+1);\n        \n        long long delta_E = (new_area_cost - old_day_cost) + (new_bound1 - old_bound1) + (new_bound2 - old_bound2);\n        \n        bool accept = false;\n        if (delta_E <= 0) accept = true;\n        else {\n            double p = exp(-delta_E / T);\n            if (uniform_real_distribution<double>(0, 1)(rng) < p) accept = true;\n        }\n        \n        if (accept) {\n            current_cost += delta_E;\n            day_area_cost[d] = new_area_cost;\n            if (d > 0) boundary_part_cost[d] = new_bound1;\n            if (d < D-1) boundary_part_cost[d+1] = new_bound2;\n        } else {\n            // Revert\n            if (type == 0) {\n                H[d][idx] = old_val1;\n                H[d][idx2] = old_val2;\n            } else {\n                W_vec[d][idx] = old_val1;\n                W_vec[d][idx2] = old_val2;\n            }\n        }\n        \n        T *= alpha;\n        iter++;\n    }\n    \n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            int i_start = 0;\n            for (int i = 0; i < r; ++i) i_start += H[d][i];\n            int i_end = i_start + H[d][r];\n            \n            int j_start = 0;\n            for (int j = 0; j < c; ++j) j_start += W_vec[d][j];\n            int j_end = j_start + W_vec[d][c];\n            \n            cout << i_start << \" \" << j_start << \" \" << i_end << \" \" << j_end << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\nusing ll = long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int STAMP_SIZE = 3;\nconst int POS_LIMIT = 7;\n\nll A[N][N];\nll S[M][STAMP_SIZE][STAMP_SIZE];\nll Grid[N][N];\nll GridMod[N][N];\nll CurrentScore = 0;\n\nstruct Op {\n    uint8_t m, p, q;\n};\n\nstruct FastRNG {\n    uint64_t state;\n    FastRNG(uint64_t seed) : state(seed) {}\n    uint64_t next() {\n        state ^= state << 13;\n        state ^= state >> 7;\n        state ^= state << 17;\n        return state;\n    }\n    int nextInt(int max) { return next() % max; }\n    double nextDouble() { return (next() >> 11) * (1.0 / (uint64_t(1) << 53)); }\n};\n\ninline ll get_mod(ll v) {\n    ll r = v % MOD;\n    return r < 0 ? r + MOD : r;\n}\n\ninline void recalc_score() {\n    CurrentScore = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            CurrentScore += GridMod[i][j];\n}\n\ninline ll calc_delta(int m, int p, int q, int delta) {\n    ll change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            ll new_val = Grid[r][c] + delta * S[m][i][j];\n            change += get_mod(new_val) - GridMod[r][c];\n        }\n    }\n    return change;\n}\n\ninline void apply_op(int m, int p, int q, int delta) {\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            Grid[r][c] += delta * S[m][i][j];\n            GridMod[r][c] = get_mod(Grid[r][c]);\n        }\n    }\n    recalc_score();\n}\n\nvoid init_grid() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Grid[i][j] = A[i][j];\n            GridMod[i][j] = get_mod(A[i][j]);\n        }\n    }\n    recalc_score();\n}\n\nll run_sa(uint64_t seed, double time_limit, vector<Op>& ops) {\n    FastRNG rng(seed);\n    init_grid();\n    ops.clear();\n    \n    // Greedy initialization\n    for (int step = 0; step < K; ++step) {\n        ll best_delta = 0;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < POS_LIMIT; ++p) {\n                for (int q = 0; q < POS_LIMIT; ++q) {\n                    ll d = calc_delta(m, p, q, 1);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_m = m; best_p = p; best_q = q;\n                    }\n                }\n            }\n        }\n        \n        if (best_delta <= 0) break;\n        apply_op(best_m, best_p, best_q, 1);\n        ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n    }\n    \n    ll best_score = CurrentScore;\n    vector<Op> best_ops = ops;\n    \n    auto start = chrono::steady_clock::now();\n    ll T_start = 1000000000LL;\n    int iter = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        double progress = elapsed / time_limit;\n        ll T = (ll)(T_start * exp(-progress * 6.0));\n        if (T < 100) T = 100;\n        \n        // Select move type\n        int move = rng.nextInt(100);\n        \n        if (ops.empty()) {\n            // Must add\n            int m = rng.nextInt(M);\n            int p = rng.nextInt(POS_LIMIT);\n            int q = rng.nextInt(POS_LIMIT);\n            ll delta = calc_delta(m, p, q, 1);\n            if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                apply_op(m, p, q, 1);\n                ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        } else if (ops.size() >= K) {\n            // Change or remove\n            if (move < 70) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        } else {\n            // Any move\n            if (move < 50) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else if (move < 80) {\n                // Add\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                ll delta = calc_delta(m, p, q, 1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(m, p, q, 1);\n                    ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        }\n        \n        if (CurrentScore > best_score) {\n            best_score = CurrentScore;\n            best_ops = ops;\n        }\n        iter++;\n    }\n    \n    ops = best_ops;\n    return best_score;\n}\n\n// Simple final refinement\nvoid final_refine(vector<Op>& ops, double time_limit) {\n    auto start = chrono::steady_clock::now();\n    init_grid();\n    for (const auto& op : ops) {\n        apply_op(op.m, op.p, op.q, 1);\n    }\n    \n    bool improved = true;\n    while (improved) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        improved = false;\n        ll best_delta = 0;\n        int best_type = -1, best_idx = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        // Try all changes (most impactful)\n        for (int idx = 0; idx < (int)ops.size() && !improved; ++idx) {\n            Op old = ops[idx];\n            for (int m = 0; m < M && !improved; ++m) {\n                for (int p = 0; p < POS_LIMIT && !improved; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        if (m == old.m && p == old.p && q == old.q) continue;\n                        ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 0;\n                            best_idx = idx;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try removes\n        for (int idx = 0; idx < (int)ops.size(); ++idx) {\n            Op old = ops[idx];\n            ll delta = calc_delta(old.m, old.p, old.q, -1);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_type = 1;\n                best_idx = idx;\n            }\n        }\n        \n        // Try adds\n        if (ops.size() < K) {\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < POS_LIMIT; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        ll delta = calc_delta(m, p, q, 1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 2;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (best_delta > 0) {\n            improved = true;\n            if (best_type == 0) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                apply_op(best_m, best_p, best_q, 1);\n                ops[best_idx] = {(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q};\n            } else if (best_type == 1) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                ops[best_idx] = ops.back();\n                ops.pop_back();\n            } else {\n                apply_op(best_m, best_p, best_q, 1);\n                ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, m_in, k_in;\n    cin >> n_in >> m_in >> k_in;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    for (int m = 0; m < M; ++m)\n        for (int i = 0; i < STAMP_SIZE; ++i)\n            for (int j = 0; j < STAMP_SIZE; ++j)\n                cin >> S[m][i][j];\n\n    vector<Op> best_ops;\n    ll best_score = 0;\n    \n    // Run 2 SA with different seeds, more time each\n    double sa_time = 0.85;\n    for (int run = 0; run < 2; ++run) {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + run * 1000000;\n        vector<Op> ops;\n        ll score = run_sa(seed, sa_time, ops);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n    \n    // Final refinement\n    final_refine(best_ops, 0.25);\n    \n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << (int)op.m << \" \" << (int)op.p << \" \" << (int)op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction helpers\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar dchar[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int id;\n    int r, c;\n    int holding; // -1 if empty, else container ID\n    bool is_large;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    Crane cranes[N];\n    vector<int> inputs[N]; // Queues of containers to arrive at each row\n    int input_idx[N]; // Next index to arrive\n    int next_dispatch[N]; // Next expected container ID for each dispatch gate\n    int total_dispatched;\n    int total_containers;\n    \n    State() {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = -1;\n            cranes[i].id = i;\n            cranes[i].r = i;\n            cranes[i].c = 0;\n            cranes[i].holding = -1;\n            cranes[i].is_large = (i == 0);\n            input_idx[i] = 0;\n            next_dispatch[i] = i * N;\n            total_dispatched = 0;\n            total_containers = N * N;\n        }\n    }\n};\n\nclass Solver {\n    State state;\n    vector<string> ans;\n    int turn;\n\npublic:\n    Solver(const vector<vector<int>>& A) {\n        ans.resize(N);\n        turn = 0;\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                state.inputs[i].push_back(A[i][j]);\n            }\n        }\n    }\n\n    void receive_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.input_idx[i] < N) {\n                bool has_container = (state.grid[i][0] != -1);\n                bool crane_holding = false;\n                int crane_at_sq = -1;\n                for(int k=0; k<N; ++k) {\n                    if(state.cranes[k].r == i && state.cranes[k].c == 0) {\n                        crane_at_sq = k;\n                        break;\n                    }\n                }\n                if(crane_at_sq != -1 && state.cranes[crane_at_sq].holding != -1) {\n                    crane_holding = true;\n                }\n\n                if(!has_container && !crane_holding) {\n                    state.grid[i][0] = state.inputs[i][state.input_idx[i]];\n                    state.input_idx[i]++;\n                }\n            }\n        }\n    }\n\n    void dispatch_containers() {\n        for(int i=0; i<N; ++i) {\n            if(state.grid[i][N-1] != -1) {\n                int cid = state.grid[i][N-1];\n                state.grid[i][N-1] = -1;\n                state.total_dispatched++;\n                if(cid == state.next_dispatch[i]) {\n                    state.next_dispatch[i]++;\n                }\n            }\n        }\n    }\n\n    bool is_valid_move(int crane_idx, int nr, int nc, const vector<pair<int,int>>& planned_next) {\n        if(nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n        \n        // Check collision with other cranes' next positions (already planned)\n        for(int k=0; k<crane_idx; ++k) {\n            if(planned_next[k].first == nr && planned_next[k].second == nc) return false; // Vertex collision\n            // Swap collision\n            if(planned_next[k].first == state.cranes[crane_idx].r && planned_next[k].second == state.cranes[crane_idx].c) {\n                if(nr == state.cranes[k].r && nc == state.cranes[k].c) return false;\n            }\n        }\n        // Check collision with future cranes' current positions (treat as static obstacles)\n        for(int k=crane_idx+1; k<N; ++k) {\n            if(state.cranes[k].r == nr && state.cranes[k].c == nc) return false;\n        }\n        \n        return true;\n    }\n\n    bool is_valid_cell_for_carrying(int crane_idx, int r, int c) {\n        if(state.cranes[crane_idx].holding == -1) return true;\n        if(state.cranes[crane_idx].is_large) return true;\n        // Small crane carrying\n        if(state.grid[r][c] != -1) return false;\n        return true;\n    }\n\n    void solve() {\n        while(turn < MAX_TURNS && state.total_dispatched < state.total_containers) {\n            turn++;\n            receive_containers();\n            \n            vector<char> moves(N, '.');\n            vector<pair<int,int>> planned_next(N);\n            for(int i=0; i<N; ++i) planned_next[i] = {state.cranes[i].r, state.cranes[i].c};\n\n            for(int i=0; i<N; ++i) {\n                Crane &cr = state.cranes[i];\n                long long best_score = -1e18;\n                int nr = cr.r, nc = cr.c;\n                char move_char = '.';\n\n                auto try_move = [&](int tr, int tc, char ch) {\n                    if(!is_valid_move(i, tr, tc, planned_next)) return;\n                    if(!is_valid_cell_for_carrying(i, tr, tc)) return;\n                    \n                    long long score = 0;\n                    \n                    if(cr.holding != -1) {\n                        int target_row = cr.holding / N;\n                        int target_col = N - 1;\n                        \n                        // Distance to target gate\n                        int dist = abs(tr - target_row) + abs(tc - target_col);\n                        score -= dist;\n                        \n                        // Priority for correct next dispatch\n                        if(cr.holding == state.next_dispatch[target_row]) {\n                            score += 5000;\n                        }\n\n                        // Discourage entering Dispatch Column (N-1) unless at target row\n                        // This prevents congestion on the right edge\n                        if(tc == N-1 && tr != target_row) {\n                            score -= 1000; \n                        }\n                        \n                        // Action Q (Place)\n                        if(ch == 'Q') { // 'Q' is handled separately in logic flow usually, but here we simulate outcome\n                             // If we are effectively placing (logic handled outside), but here we evaluate move to (tr,tc)\n                             // Actually, Q happens at current pos.\n                        }\n                    } else {\n                        // Empty\n                        // Priority: Pick up next_dispatch container\n                        int min_dist_input = 10000;\n                        for(int r=0; r<N; ++r) {\n                            if(state.input_idx[r] < N && state.grid[r][0] != -1) {\n                                int cid = state.grid[r][0];\n                                int d = abs(tr - r) + abs(tc - 0);\n                                // Bonus if this container is needed next\n                                if(cid == state.next_dispatch[r]) d -= 50; \n                                if(d < min_dist_input) min_dist_input = d;\n                            }\n                        }\n                        score -= min_dist_input;\n                        \n                        // Priority: Move towards buffers with containers needing transport\n                        if(cr.is_large) {\n                            for(int r=0; r<N; ++r) {\n                                for(int c=1; c<N-1; ++c) {\n                                    if(state.grid[r][c] != -1) {\n                                        int cid = state.grid[r][c];\n                                        if(cid == state.next_dispatch[r/N]) { // Wait, cid/N is target row\n                                            int d = abs(tr - r) + abs(tc - c);\n                                            score -= d; // Attract\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    // Evaluate Action P (Pick up)\n                    if(ch == '.') {\n                        if(cr.holding == -1 && state.grid[cr.r][cr.c] != -1) {\n                            int cid = state.grid[cr.r][cr.c];\n                            int t_row = cid / N;\n                            long long pick_score = score;\n                            if(cid == state.next_dispatch[t_row]) pick_score += 10000;\n                            else pick_score += 1000;\n                            \n                            if(pick_score > best_score) {\n                                best_score = pick_score;\n                                nr = cr.r; nc = cr.c;\n                                move_char = 'P';\n                            }\n                        }\n                        // Evaluate Action Q (Place)\n                        if(cr.holding != -1 && state.grid[cr.r][cr.c] == -1) {\n                            int t_row = cr.holding / N;\n                            long long place_score = score;\n                            \n                            if(cr.r == t_row && cr.c == N-1) {\n                                // Correct Gate\n                                if(cr.holding == state.next_dispatch[t_row]) place_score += 20000;\n                                else place_score += 5000; // Wrong order but correct gate\n                            } else if(cr.c == N-1) {\n                                // Wrong Gate\n                                // M2 penalty is 10^4, M3 is 10^6. Dispatching is better than holding forever.\n                                place_score += 2000; \n                            } else {\n                                // Buffer\n                                place_score -= 500;\n                            }\n                            \n                            if(place_score > best_score) {\n                                best_score = place_score;\n                                nr = cr.r; nc = cr.c;\n                                move_char = 'Q';\n                            }\n                        }\n                    }\n                    \n                    // Evaluate Move\n                    // Only if move_char is still '.' or score is better than current best (which might be P/Q)\n                    // Note: P/Q keeps crane at (cr.r, cr.c). Move changes to (tr, tc).\n                    // We need to compare Move score vs P/Q score.\n                    // But P/Q score was added to `score` (which included movement penalty to tr,tc? No).\n                    // Wait, `score` calculation above assumed moving to (tr, tc).\n                    // P/Q happens at (cr.r, cr.c).\n                    // So we should recalculate base score for stay (cr.r, cr.c) for P/Q comparison.\n                    // To simplify:\n                    // 1. Calculate best Move score.\n                    // 2. Calculate P/Q score at current pos.\n                    // 3. Compare.\n                    \n                    // Let's refactor slightly inside the loop to separate Move vs Action\n                };\n                \n                // Reset for proper logic separation\n                best_score = -1e18;\n                move_char = '.';\n                nr = cr.r; nc = cr.c;\n\n                // 1. Evaluate Actions at Current Position (P, Q, .)\n                // Base score for staying\n                long long base_score = 0;\n                if(cr.holding != -1) {\n                    int t_row = cr.holding / N;\n                    base_score -= (abs(cr.r - t_row) + abs(cr.c - (N-1)));\n                    if(cr.holding == state.next_dispatch[t_row]) base_score += 5000;\n                } else {\n                    // Empty logic roughly\n                }\n\n                // Check P\n                if(cr.holding == -1 && state.grid[cr.r][cr.c] != -1) {\n                    int cid = state.grid[cr.r][cr.c];\n                    int t_row = cid / N;\n                    long long s = base_score;\n                    if(cid == state.next_dispatch[t_row]) s += 10000;\n                    else s += 2000;\n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = 'P';\n                    }\n                }\n                // Check Q\n                if(cr.holding != -1 && state.grid[cr.r][cr.c] == -1) {\n                    int t_row = cr.holding / N;\n                    long long s = base_score;\n                    if(cr.r == t_row && cr.c == N-1) {\n                        if(cr.holding == state.next_dispatch[t_row]) s += 20000;\n                        else s += 5000;\n                    } else if(cr.c == N-1) {\n                        s += 3000; // Dispatch wrong gate is okay\n                    } else {\n                        s -= 1000; // Buffer\n                    }\n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = 'Q';\n                    }\n                }\n                \n                // 2. Evaluate Moves (U, D, L, R)\n                for(int d=0; d<4; ++d) {\n                    int tr = cr.r + dr[d];\n                    int tc = cr.c + dc[d];\n                    if(!is_valid_move(i, tr, tc, planned_next)) continue;\n                    if(!is_valid_cell_for_carrying(i, tr, tc)) continue;\n                    \n                    long long s = 0;\n                    if(cr.holding != -1) {\n                        int t_row = cr.holding / N;\n                        int dist = abs(tr - t_row) + abs(tc - (N-1));\n                        s -= dist;\n                        if(cr.holding == state.next_dispatch[t_row]) s += 5000;\n                        if(tc == N-1 && tr != t_row) s -= 2000; // Strongly discourage entering dispatch lane early\n                    } else {\n                        // Empty: go to inputs\n                        int min_d = 1000;\n                        for(int r=0; r<N; ++r) {\n                            if(state.input_idx[r] < N && state.grid[r][0] != -1) {\n                                int d_val = abs(tr - r) + abs(tc - 0);\n                                if(state.grid[r][0] == state.next_dispatch[r]) d_val -= 50;\n                                if(d_val < min_d) min_d = d_val;\n                            }\n                        }\n                        s -= min_d;\n                    }\n                    \n                    if(s > best_score) {\n                        best_score = s;\n                        move_char = dchar[d];\n                        nr = tr; nc = tc;\n                    }\n                }\n                \n                // Apply\n                moves[i] = move_char;\n                if(move_char == 'P' || move_char == 'Q' || move_char == '.') {\n                    planned_next[i] = {cr.r, cr.c};\n                } else {\n                    planned_next[i] = {nr, nc};\n                }\n            }\n\n            // Execute\n            for(int i=0; i<N; ++i) {\n                ans[i] += moves[i];\n                Crane &cr = state.cranes[i];\n                char m = moves[i];\n                if(m == 'P') {\n                    cr.holding = state.grid[cr.r][cr.c];\n                    state.grid[cr.r][cr.c] = -1;\n                } else if(m == 'Q') {\n                    state.grid[cr.r][cr.c] = cr.holding;\n                    cr.holding = -1;\n                } else if(m == 'U') cr.r--;\n                else if(m == 'D') cr.r++;\n                else if(m == 'L') cr.c--;\n                else if(m == 'R') cr.c++;\n            }\n\n            dispatch_containers();\n        }\n        \n        // Pad\n        size_t max_len = 0;\n        for(const auto& s : ans) max_len = max(max_len, s.size());\n        if(max_len == 0) max_len = 1;\n        for(int i=0; i<N; ++i) {\n            while(ans[i].size() < max_len) ans[i] += '.';\n        }\n    }\n\n    void print_ans() {\n        for(int i=0; i<N; ++i) {\n            cout << ans[i] << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.print_ans();\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <string>\n#include <cstdlib>\n\nusing namespace std;\n\n// Structure to represent grid coordinates\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Coord& o) const { return !(*this == o); }\n};\n\n// Manhattan distance between two coordinates\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint N;\nint h[25][25];\nvector<Coord> sources;\nvector<Coord> sinks;\n\n// Flow targets for each source cell: list of {sink_coord, amount}\nstruct FlowTarget {\n    Coord sink;\n    int amount;\n};\nvector<FlowTarget> source_flows[25][25];\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\n    // Read input and identify sources (h > 0) and sinks (h < 0)\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    // Working copy of heights to track remaining supply/demand\n    int cur_h[25][25];\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            cur_h[i][j] = h[i][j];\n    \n    // Indices of active sources and sinks\n    vector<int> src_idx(sources.size());\n    iota(src_idx.begin(), src_idx.end(), 0);\n    vector<int> snk_idx(sinks.size());\n    iota(snk_idx.begin(), snk_idx.end(), 0);\n\n    // Greedy Flow Calculation\n    // Repeatedly pick the pair (source, sink) with minimum distance and transfer soil.\n    // This approximates the Minimum Cost Flow / Earth Mover's Distance.\n    while (!src_idx.empty() && !snk_idx.empty()) {\n        int s_choice = -1;\n        int k_choice = -1;\n        int min_d = 1e9;\n\n        // Find the pair with minimum Manhattan distance\n        for (int s : src_idx) {\n            for (int k : snk_idx) {\n                int d = dist(sources[s], sinks[k]);\n                if (d < min_d) {\n                    min_d = d;\n                    s_choice = s;\n                    k_choice = k;\n                }\n            }\n        }\n        \n        if (s_choice == -1) break;\n\n        Coord u = sources[s_choice];\n        Coord v = sinks[k_choice];\n        // Transfer as much as possible\n        int amount = min(cur_h[u.r][u.c], -cur_h[v.r][v.c]);\n        \n        source_flows[u.r][u.c].push_back({v, amount});\n        \n        cur_h[u.r][u.c] -= amount;\n        cur_h[v.r][v.c] += amount;\n        \n        // Remove exhausted source or sink from active lists\n        if (cur_h[u.r][u.c] == 0) {\n            for(int i=0; i<src_idx.size(); ++i) {\n                if(src_idx[i] == s_choice) {\n                    src_idx[i] = src_idx.back();\n                    src_idx.pop_back();\n                    break;\n                }\n            }\n        }\n        if (cur_h[v.r][v.c] == 0) {\n            for(int i=0; i<snk_idx.size(); ++i) {\n                if(snk_idx[i] == k_choice) {\n                    snk_idx[i] = snk_idx.back();\n                    snk_idx.pop_back();\n                    break;\n                }\n            }\n        }\n    }\n\n    vector<string> ops;\n    Coord cur = {0, 0}; // Truck starts at (0,0)\n\n    // List of sources that have soil to transport\n    vector<Coord> active_sources;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!source_flows[i][j].empty()) {\n                active_sources.push_back({i, j});\n            }\n        }\n    }\n\n    // Order sources using Nearest Neighbor heuristic to minimize empty travel\n    vector<bool> visited_source(active_sources.size(), false);\n    int sources_remaining = active_sources.size();\n\n    while (sources_remaining > 0) {\n        int best_idx = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < active_sources.size(); ++i) {\n            if (!visited_source[i]) {\n                int d = dist(cur, active_sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n        }\n\n        if (best_idx == -1) break;\n\n        Coord u = active_sources[best_idx];\n        visited_source[best_idx] = true;\n        sources_remaining--;\n\n        // Move truck to source u\n        while (cur != u) {\n            if (cur.r < u.r) { cur.r++; ops.push_back(\"D\"); }\n            else if (cur.r > u.r) { cur.r--; ops.push_back(\"U\"); }\n            else if (cur.c < u.c) { cur.c++; ops.push_back(\"R\"); }\n            else if (cur.c > u.c) { cur.c--; ops.push_back(\"L\"); }\n        }\n\n        // Calculate total load to pick up at u\n        int total_load = 0;\n        for (auto& flow : source_flows[u.r][u.c]) {\n            total_load += flow.amount;\n        }\n\n        // Load soil\n        ops.push_back(\"+\" + to_string(total_load));\n\n        // Visit assigned sinks for this source\n        // Order sinks using Nearest Neighbor to minimize loaded travel\n        vector<FlowTarget> targets = source_flows[u.r][u.c];\n        vector<bool> visited_target(targets.size(), false);\n        int targets_remaining = targets.size();\n\n        while (targets_remaining > 0) {\n            int best_t = -1;\n            int min_td = 1e9;\n            for (int i = 0; i < targets.size(); ++i) {\n                if (!visited_target[i]) {\n                    int d = dist(cur, targets[i].sink);\n                    if (d < min_td) {\n                        min_td = d;\n                        best_t = i;\n                    }\n                }\n            }\n            \n            Coord v = targets[best_t].sink;\n            // Move truck to sink v\n            while (cur != v) {\n                if (cur.r < v.r) { cur.r++; ops.push_back(\"D\"); }\n                else if (cur.r > v.r) { cur.r--; ops.push_back(\"U\"); }\n                else if (cur.c < v.c) { cur.c++; ops.push_back(\"R\"); }\n                else if (cur.c > v.c) { cur.c--; ops.push_back(\"L\"); }\n            }\n\n            // Unload soil\n            int amt = targets[best_t].amount;\n            ops.push_back(\"-\" + to_string(amt));\n            \n            visited_target[best_t] = true;\n            targets_remaining--;\n        }\n    }\n\n    // Output the sequence of operations\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 <cmath>\n#include <random>\n#include <set>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n    \n    int seed_count = 2 * N * (N - 1); // 60 seeds\n    int grid_size = N * N; // 36 squares\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    \n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n    \n    mt19937 rng(42);\n    \n    // Track global max for each dimension\n    vector<int> global_max(M, 0);\n    for (int d = 0; d < M; d++) {\n        for (int i = 0; i < seed_count; i++) {\n            global_max[d] = max(global_max[d], X[i][d]);\n        }\n    }\n    \n    // Track best seeds from previous generation\n    vector<int> prev_best_seeds;\n    \n    for (int turn = 0; turn < T; turn++) {\n        // Calculate dimension statistics\n        vector<int> dim_max(M, 0);\n        vector<int> dim_second_max(M, 0);\n        \n        for (int d = 0; d < M; d++) {\n            vector<int> dim_values;\n            for (int i = 0; i < seed_count; i++) {\n                dim_values.push_back(X[i][d]);\n            }\n            sort(dim_values.begin(), dim_values.end(), greater<int>());\n            dim_max[d] = dim_values[0];\n            dim_second_max[d] = (dim_values.size() > 1) ? dim_values[1] : 0;\n        }\n        \n        // Calculate seed scores\n        vector<pair<double, int>> seed_score(seed_count);\n        for (int i = 0; i < seed_count; i++) {\n            double score = 0;\n            \n            // Factor 1: Total value\n            int total = 0;\n            for (int d = 0; d < M; d++) {\n                total += X[i][d];\n            }\n            score += total * 0.01;\n            \n            // Factor 2: Dimensional excellence\n            for (int d = 0; d < M; d++) {\n                if (dim_max[d] > 0) {\n                    double ratio = (double)X[i][d] / dim_max[d];\n                    // Quadratic bonus for being close to max\n                    score += ratio * ratio * 10.0;\n                    \n                    // Extra bonus for being THE best in dimension\n                    if (X[i][d] == dim_max[d]) {\n                        score += 15.0;\n                    }\n                    // Bonus for being second best\n                    else if (X[i][d] == dim_second_max[d]) {\n                        score += 5.0;\n                    }\n                }\n            }\n            \n            // Factor 3: Bonus for being in previous best seeds\n            if (turn > 0 && find(prev_best_seeds.begin(), prev_best_seeds.end(), i) != prev_best_seeds.end()) {\n                score += 3.0;\n            }\n            \n            // Factor 4: Penalize if too similar to already selected (diversity)\n            // (will be handled in selection phase)\n            \n            seed_score[i] = {score, i};\n        }\n        \n        // Sort by score\n        sort(seed_score.begin(), seed_score.end(), [](const auto& a, const auto& b) {\n            if (abs(a.first - b.first) > 0.01) return a.first > b.first;\n            return a.second < b.second;\n        });\n        \n        // Select seeds with diversity consideration\n        vector<int> selected;\n        vector<bool> selected_flag(seed_count, false);\n        vector<int> dim_covered(M, 0);\n        \n        // First: ensure we have the best seed for each dimension\n        for (int d = 0; d < M; d++) {\n            int best_seed = -1;\n            for (int i = 0; i < seed_count; i++) {\n                if (X[i][d] == dim_max[d]) {\n                    best_seed = i;\n                    break;\n                }\n            }\n            if (best_seed >= 0 && !selected_flag[best_seed] && selected.size() < grid_size) {\n                selected.push_back(best_seed);\n                selected_flag[best_seed] = true;\n                dim_covered[d]++;\n            }\n        }\n        \n        // Second: fill remaining slots with highest scored seeds\n        for (const auto& p : seed_score) {\n            if (selected.size() >= grid_size) break;\n            if (!selected_flag[p.second]) {\n                selected.push_back(p.second);\n                selected_flag[p.second] = true;\n            }\n        }\n        \n        // Calculate potential offspring value for each pair\n        // This measures how good the best possible child could be\n        auto calc_offspring_potential = [&](int i, int j) -> int {\n            int potential = 0;\n            for (int d = 0; d < M; d++) {\n                // Best case: child gets max of both parents for each dimension\n                potential += max(X[i][d], X[j][d]);\n            }\n            return potential;\n        };\n        \n        // Calculate compatibility (average offspring quality)\n        auto calc_compatibility = [&](int i, int j) -> double {\n            double comp = 0;\n            for (int d = 0; d < M; d++) {\n                // Expected value for each dimension (average of two parents)\n                comp += (X[i][d] + X[j][d]) / 2.0;\n            }\n            return comp;\n        };\n        \n        // Place seeds in grid\n        // Strategy: Place high-potential pairs adjacent to each other\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        vector<bool> placed(selected.size(), false);\n        \n        // Find the best pair to place first (center of grid)\n        int best_pair_i = 0, best_pair_j = 1;\n        int best_pair_potential = -1;\n        \n        for (int i = 0; i < selected.size(); i++) {\n            for (int j = i + 1; j < selected.size(); j++) {\n                int potential = calc_offspring_potential(selected[i], selected[j]);\n                if (potential > best_pair_potential) {\n                    best_pair_potential = potential;\n                    best_pair_i = i;\n                    best_pair_j = j;\n                }\n            }\n        }\n        \n        // Place best pair in center\n        int center_i = N / 2;\n        int center_j = N / 2;\n        A[center_i][center_j] = selected[best_pair_i];\n        placed[best_pair_i] = true;\n        \n        if (center_j + 1 < N) {\n            A[center_i][center_j + 1] = selected[best_pair_j];\n            placed[best_pair_j] = true;\n        }\n        \n        // Greedily place remaining seeds\n        for (int count = 2; count < grid_size; count++) {\n            int best_seed_idx = -1;\n            int best_pos_i = -1, best_pos_j = -1;\n            double best_score = -1e9;\n            \n            for (int si = 0; si < selected.size(); si++) {\n                if (placed[si]) continue;\n                int seed_id = selected[si];\n                \n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] != -1) continue;\n                        \n                        // Check adjacency\n                        bool has_neighbor = false;\n                        double neighbor_score = 0;\n                        int neighbor_count = 0;\n                        int max_neighbor_potential = 0;\n                        \n                        const int di[] = {-1, 1, 0, 0};\n                        const int dj[] = {0, 0, -1, 1};\n                        \n                        for (int dir = 0; dir < 4; dir++) {\n                            int ni = i + di[dir];\n                            int nj = j + dj[dir];\n                            if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1) {\n                                has_neighbor = true;\n                                neighbor_score += calc_compatibility(seed_id, A[ni][nj]);\n                                max_neighbor_potential = max(max_neighbor_potential, \n                                    calc_offspring_potential(seed_id, A[ni][nj]));\n                                neighbor_count++;\n                            }\n                        }\n                        \n                        if (has_neighbor) {\n                            double pos_score = neighbor_score / neighbor_count;\n                            \n                            // Bonus for positions with more available neighbors (center preference)\n                            int available_neighbors = 0;\n                            for (int dir = 0; dir < 4; dir++) {\n                                int ni = i + di[dir];\n                                int nj = j + dj[dir];\n                                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                                    available_neighbors++;\n                                }\n                            }\n                            pos_score += available_neighbors * 0.5;\n                            \n                            // Bonus for high potential offspring\n                            pos_score += max_neighbor_potential * 0.001;\n                            \n                            if (pos_score > best_score) {\n                                best_score = pos_score;\n                                best_seed_idx = si;\n                                best_pos_i = i;\n                                best_pos_j = j;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (best_seed_idx >= 0) {\n                A[best_pos_i][best_pos_j] = selected[best_seed_idx];\n                placed[best_seed_idx] = true;\n            } else {\n                // Fill any remaining empty spots\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] == -1) {\n                            for (int si = 0; si < selected.size(); si++) {\n                                if (!placed[si]) {\n                                    A[i][j] = selected[si];\n                                    placed[si] = true;\n                                    goto filled;\n                                }\n                            }\n                        }\n                    }\n                }\n                filled:;\n            }\n        }\n        \n        // Output the grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds and track best ones\n        vector<pair<int, int>> new_totals;\n        for (int i = 0; i < seed_count; i++) {\n            int total = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                total += X[i][j];\n                global_max[j] = max(global_max[j], X[i][j]);\n            }\n            new_totals.push_back({total, i});\n        }\n        \n        // Track top seeds for next turn\n        sort(new_totals.begin(), new_totals.end(), greater<pair<int,int>>());\n        prev_best_seeds.clear();\n        for (int i = 0; i < min(15, seed_count); i++) {\n            prev_best_seeds.push_back(new_totals[i].second);\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n    bool operator<(const Point& o) const {\n        if (x != o.x) return x < o.x;\n        return y < o.y;\n    }\n};\n\nint dist(Point a, Point b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> S(N), T(N);\n    for (int i = 0; i < N; i++) cin >> S[i];\n    for (int i = 0; i < N; i++) cin >> T[i];\n    \n    vector<Point> sources, targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (S[i][j] == '1') sources.push_back({i, j});\n            if (T[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n    \n    // Design arm: star topology with varying edge lengths\n    int V_prime = min(V, (int)sources.size() + 1);\n    if (V_prime < 2) V_prime = 2;\n    int num_fingertips = V_prime - 1;\n    \n    cout << V_prime << \"\\n\";\n    vector<int> edge_len(V_prime, 0);\n    for (int i = 1; i < V_prime; i++) {\n        edge_len[i] = (i - 1) % (N - 1) + 1;\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Find good initial root position (center of sources)\n    int sum_x = 0, sum_y = 0;\n    for (auto& p : sources) {\n        sum_x += p.x;\n        sum_y += p.y;\n    }\n    int root_x = sum_x / M;\n    int root_y = sum_y / M;\n    root_x = max(0, min(N - 1, root_x));\n    root_y = max(0, min(N - 1, root_y));\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Grid state tracking\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = (S[i][j] == '1' ? 1 : 0);\n        }\n    }\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            is_target[i][j] = (T[i][j] == '1' ? 1 : 0);\n        }\n    }\n    \n    // Fingertip state\n    vector<int> fp_dir(num_fingertips, 0);  // 0:R, 1:D, 2:L, 3:U\n    vector<bool> fp_holding(num_fingertips, false);\n    \n    auto get_fp_pos = [&](int fp_idx) -> Point {\n        int d = fp_dir[fp_idx];\n        return {root_x + DX[d] * edge_len[fp_idx + 1], \n                root_y + DY[d] * edge_len[fp_idx + 1]};\n    };\n    \n    auto in_bounds = [&](Point p) -> bool {\n        return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n    };\n    \n    auto can_pick = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 1;\n    };\n    \n    auto can_place = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 0;\n    };\n    \n    vector<string> commands;\n    int turns = 0;\n    int delivered = 0;\n    \n    // Create source-target matching (greedy by distance)\n    vector<bool> src_used(sources.size(), false);\n    vector<bool> tgt_used(targets.size(), false);\n    vector<pair<int, int>> pairs;\n    \n    for (int iter = 0; iter < M; iter++) {\n        int best_si = -1, best_ti = -1, best_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); i++) {\n            if (src_used[i]) continue;\n            for (int j = 0; j < (int)targets.size(); j++) {\n                if (tgt_used[j]) continue;\n                int d = dist(sources[i], targets[j]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_si = i;\n                    best_ti = j;\n                }\n            }\n        }\n        if (best_si >= 0) {\n            src_used[best_si] = true;\n            tgt_used[best_ti] = true;\n            pairs.push_back({best_si, best_ti});\n        }\n    }\n    \n    // Process pairs using multiple fingertips in parallel\n    int pair_idx = 0;\n    vector<int> fp_task(num_fingertips, -1);  // Which pair each fingertip is handling\n    \n    while ((pair_idx < (int)pairs.size() || \n           count(fp_task.begin(), fp_task.end(), -1) < num_fingertips) && \n           turns < 99000) {\n        \n        string cmd(V_prime * 2, '.');\n        bool action_taken = false;\n        \n        // Assign new tasks to idle fingertips\n        for (int fp = 0; fp < num_fingertips && pair_idx < (int)pairs.size(); fp++) {\n            if (fp_task[fp] == -1 && !fp_holding[fp]) {\n                fp_task[fp] = pair_idx++;\n            }\n        }\n        \n        // Process each fingertip\n        for (int fp = 0; fp < num_fingertips; fp++) {\n            if (fp_task[fp] == -1) continue;\n            \n            int si = pairs[fp_task[fp]].first;\n            int ti = pairs[fp_task[fp]].second;\n            Point src = sources[si];\n            Point tgt = targets[ti];\n            \n            if (!fp_holding[fp]) {\n                // Need to pick up from source\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == src && can_pick(src)) {\n                    // Pick up\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = true;\n                    grid[src.x][src.y] = 0;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach source\n                    int target_rx = src.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = src.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == src.x && ty == src.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            } else {\n                // Need to deliver to target\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == tgt && can_place(tgt) && is_target[tgt.x][tgt.y]) {\n                    // Place\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = false;\n                    grid[tgt.x][tgt.y] = 1;\n                    fp_task[fp] = -1;\n                    delivered++;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach target\n                    int target_rx = tgt.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = tgt.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == tgt.x && ty == tgt.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            }\n        }\n        \n        // If no fingertips active, try to activate more\n        if (!action_taken) {\n            bool found = false;\n            for (int fp = 0; fp < num_fingertips && !found; fp++) {\n                if (fp_task[fp] == -1 && pair_idx < (int)pairs.size()) {\n                    fp_task[fp] = pair_idx++;\n                    found = true;\n                }\n            }\n            if (!found) break;\n            continue;\n        }\n        \n        commands.push_back(cmd);\n        turns++;\n    }\n    \n    // Output all commands\n    for (const string& c : commands) {\n        cout << c << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\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\nstruct GridCell {\n    int m; // mackerels\n    int s; // sardines\n    int score() const { return m - s; }\n};\n\n// Global data\nint GW, GH;\nint CELL_SIZE;\nvector<vector<GridCell>> grid;\nvector<vector<bool>> selected;\nvector<Point> mackerels, sardines;\n\n// Directions: Up, Right, Down, Left\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {-1, 0, 1, 0};\n\n// Priority Queue Element for Growth\nstruct PQElement {\n    int r, c;\n    int score;\n    bool operator<(const PQElement& other) const {\n        return score < other.score; // Max heap\n    }\n};\n\n// Initialize grid with given cell size\nvoid initGrid(int cell_size) {\n    CELL_SIZE = cell_size;\n    GW = MAX_COORD / CELL_SIZE + 1;\n    GH = MAX_COORD / CELL_SIZE + 1;\n    \n    grid.assign(GH, vector<GridCell>(GW, {0, 0}));\n    selected.assign(GH, vector<bool>(GW, false));\n    \n    for (const auto& p : mackerels) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].m++;\n        }\n    }\n    for (const auto& p : sardines) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].s++;\n        }\n    }\n}\n\n// Build polygon from selected cells\nvector<Point> buildPolygonFromCells() {\n    struct Edge {\n        int x1, y1, x2, y2;\n    };\n    \n    vector<Edge> edges;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                int x1 = c * CELL_SIZE;\n                int y1 = r * CELL_SIZE;\n                int x2 = (c + 1) * CELL_SIZE;\n                int y2 = (r + 1) * CELL_SIZE;\n                \n                if (r == 0 || !selected[r-1][c]) {\n                    edges.push_back({x1, y1, x2, y1});\n                }\n                if (r == GH - 1 || !selected[r+1][c]) {\n                    edges.push_back({x1, y2, x2, y2});\n                }\n                if (c == 0 || !selected[r][c-1]) {\n                    edges.push_back({x1, y1, x1, y2});\n                }\n                if (c == GW - 1 || !selected[r][c+1]) {\n                    edges.push_back({x2, y1, x2, y2});\n                }\n            }\n        }\n    }\n    \n    if (edges.empty()) return {};\n    \n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    for (const auto& e : edges) {\n        adj[{e.x1, e.y1}].push_back({e.x2, e.y2});\n        adj[{e.x2, e.y2}].push_back({e.x1, e.y1});\n    }\n    \n    Point start = {edges[0].x1, edges[0].y1};\n    for (const auto& e : edges) {\n        Point p1 = {e.x1, e.y1};\n        Point p2 = {e.x2, e.y2};\n        if (p1.y < start.y || (p1.y == start.y && p1.x < start.x)) {\n            start = p1;\n        }\n        if (p2.y < start.y || (p2.y == start.y && p2.x < start.x)) {\n            start = p2;\n        }\n    }\n    \n    vector<Point> poly;\n    Point current = start;\n    Point prev = {-1000000, -1000000};\n    \n    for (int iter = 0; iter < (int)edges.size() * 2 + 10; ++iter) {\n        poly.push_back(current);\n        \n        auto it = adj.find({current.x, current.y});\n        if (it == adj.end()) break;\n        \n        Point next = {-1, -1};\n        double best_cross = 1e18;\n        \n        for (const auto& neighbor : it->second) {\n            Point np = {neighbor.first, neighbor.second};\n            if (np.x == prev.x && np.y == prev.y) continue;\n            \n            long long dx1 = current.x - prev.x;\n            long long dy1 = current.y - prev.y;\n            long long dx2 = np.x - current.x;\n            long long dy2 = np.y - current.y;\n            long long cross = dx1 * dy2 - dy1 * dx2;\n            \n            if (next.x == -1 || cross < best_cross) {\n                next = np;\n                best_cross = cross;\n            }\n        }\n        \n        if (next.x == -1) break;\n        \n        if (next.x == start.x && next.y == start.y && poly.size() > 3) {\n            break;\n        }\n        \n        prev = current;\n        current = next;\n    }\n    \n    if (poly.size() > 1 && poly.front().x == poly.back().x && poly.front().y == poly.back().y) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Simplify polygon\nvector<Point> simplifyPolygon(const vector<Point>& poly) {\n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> result;\n    result.push_back(poly[0]);\n    \n    for (size_t i = 1; i < poly.size() - 1; ++i) {\n        Point p1 = result.back();\n        Point p2 = poly[i];\n        Point p3 = poly[i + 1];\n        \n        bool collinear = (p1.x == p2.x && p2.x == p3.x) || (p1.y == p2.y && p2.y == p3.y);\n        \n        if (!collinear) {\n            result.push_back(p2);\n        }\n    }\n    \n    result.push_back(poly.back());\n    \n    vector<Point> final_result;\n    for (const auto& p : result) {\n        if (final_result.empty() || final_result.back() != p) {\n            final_result.push_back(p);\n        }\n    }\n    \n    return final_result;\n}\n\n// Check if point is inside polygon\nbool isInside(const vector<Point>& poly, int px, int py) {\n    if (poly.size() < 3) return false;\n    \n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        \n        if (xi == xj && px == xi && py >= min(yi, yj) && py <= max(yi, yj)) return true;\n        if (yi == yj && py == yi && px >= min(xi, xj) && px <= max(xi, xj)) return true;\n\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score\nlong long calculateScore(const vector<Point>& poly) {\n    if (poly.size() < 4) return 0;\n    \n    long long a = 0, b = 0;\n    for (const auto& p : mackerels) {\n        if (isInside(poly, p.x, p.y)) a++;\n    }\n    for (const auto& p : sardines) {\n        if (isInside(poly, p.x, p.y)) b++;\n    }\n    return max(0LL, a - b + 1);\n}\n\n// Validate polygon\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4 || poly.size() > MAX_VERTICES) return false;\n    \n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        \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        if (p1.x < 0 || p1.x > MAX_COORD || p1.y < 0 || p1.y > MAX_COORD) return false;\n    }\n    \n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    \n    return perim <= MAX_PERIMETER;\n}\n\n// Grow region from starting cell\nvector<Point> growRegion(int start_r, int start_c, int cell_size) {\n    initGrid(cell_size);\n    \n    for (int r = 0; r < GH; ++r)\n        for (int c = 0; c < GW; ++c)\n            selected[r][c] = false;\n    \n    if (start_r < 0 || start_r >= GH || start_c < 0 || start_c >= GW) {\n        return {};\n    }\n    \n    selected[start_r][start_c] = true;\n    \n    priority_queue<PQElement> pq;\n    vector<vector<bool>> in_pq(GH, vector<bool>(GW, false));\n    \n    for (int i = 0; i < 4; ++i) {\n        int nr = start_r + DY[i];\n        int nc = start_c + DX[i];\n        if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc]) {\n            in_pq[nr][nc] = true;\n            pq.push({nr, nc, grid[nr][nc].score()});\n        }\n    }\n    \n    long long current_perimeter = 4LL * CELL_SIZE;\n    \n    while (!pq.empty()) {\n        PQElement top = pq.top();\n        pq.pop();\n        \n        int r = top.r, c = top.c;\n        if (selected[r][c]) continue;\n        \n        int shared = 0;\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                shared++;\n            }\n        }\n        long long new_perimeter = current_perimeter + 4LL * CELL_SIZE - 2LL * shared * CELL_SIZE;\n        \n        if (new_perimeter > MAX_PERIMETER - 500) continue;\n        \n        selected[r][c] = true;\n        current_perimeter = new_perimeter;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc] && !in_pq[nr][nc]) {\n                in_pq[nr][nc] = true;\n                pq.push({nr, nc, grid[nr][nc].score()});\n            }\n        }\n    }\n    \n    vector<Point> poly = buildPolygonFromCells();\n    poly = simplifyPolygon(poly);\n    \n    return poly;\n}\n\n// Local search optimization\nvector<Point> localSearch(vector<Point> poly, int iterations) {\n    if (poly.size() < 4) return poly;\n    \n    long long best_score = calculateScore(poly);\n    vector<Point> best_poly = poly;\n    \n    // Try removing vertices (simplifying)\n    for (int iter = 0; iter < iterations && poly.size() > 4; ++iter) {\n        bool improved = false;\n        for (size_t i = 1; i < poly.size() - 1; ++i) {\n            Point p1 = poly[i - 1];\n            Point p2 = poly[i];\n            Point p3 = poly[(i + 1) % poly.size()];\n            \n            // Check if removing p2 keeps edges orthogonal\n            bool can_remove = false;\n            if (p1.x == p2.x && p2.x == p3.x) can_remove = true;\n            if (p1.y == p2.y && p2.y == p3.y) can_remove = true;\n            \n            if (can_remove) {\n                vector<Point> new_poly = poly;\n                new_poly.erase(new_poly.begin() + i);\n                \n                if (validatePolygon(new_poly)) {\n                    long long new_score = calculateScore(new_poly);\n                    if (new_score >= best_score) {\n                        poly = new_poly;\n                        best_score = new_score;\n                        if (new_score > best_score) {\n                            best_poly = poly;\n                        }\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n        if (!improved) break;\n    }\n    \n    return best_poly;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int 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    vector<Point> best_poly;\n    long long best_score = 0;\n    \n    // Try multiple cell sizes\n    vector<int> cell_sizes = {200, 300, 400, 500, 600, 800, 1000};\n    \n    for (int cell_size : cell_sizes) {\n        initGrid(cell_size);\n        \n        // Find top starting cells\n        vector<pair<int, pair<int, int>>> candidates;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                int sc = grid[r][c].score();\n                if (sc > 0 || grid[r][c].m > 0) {\n                    candidates.push_back({sc, {r, c}});\n                }\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<pair<int, pair<int, int>>>());\n        \n        // Try top candidates\n        int max_starts = min((int)candidates.size(), 10);\n        for (int i = 0; i < max_starts; ++i) {\n            int r = candidates[i].second.first;\n            int c = candidates[i].second.second;\n            \n            vector<Point> poly = growRegion(r, c, cell_size);\n            \n            if (validatePolygon(poly)) {\n                long long score = calculateScore(poly);\n                if (score > best_score) {\n                    best_score = score;\n                    best_poly = poly;\n                }\n            }\n            \n            // Apply local search\n            if (!poly.empty()) {\n                vector<Point> optimized = localSearch(poly, 50);\n                if (validatePolygon(optimized)) {\n                    long long opt_score = calculateScore(optimized);\n                    if (opt_score > best_score) {\n                        best_score = opt_score;\n                        best_poly = optimized;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback if no valid polygon found\n    if (best_poly.size() < 4) {\n        // Find best single cell\n        initGrid(500);\n        int best_r = 0, best_c = 0, best_cell_score = -1e9;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                if (grid[r][c].score() > best_cell_score) {\n                    best_cell_score = grid[r][c].score();\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        best_poly = {\n            {best_c * 500, best_r * 500},\n            {(best_c + 1) * 500, best_r * 500},\n            {(best_c + 1) * 500, (best_r + 1) * 500},\n            {best_c * 500, (best_r + 1) * 500}\n        };\n    }\n    \n    // Final validation\n    if (!validatePolygon(best_poly)) {\n        best_poly = {{0, 0}, {500, 0}, {500, 500}, {0, 500}};\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>\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n    double aspect;\n    int area;\n};\n\nstruct Placement {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n};\n\nint N;\nvector<Rectangle> rects;\nvector<Placement> placements;\nvector<pair<int, int>> pos;\nvector<pair<int, int>> dim;\n\nvoid clear_state() {\n    placements.clear();\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n}\n\nvoid add_placement(int rect_id, int rotation, char direction, int base) {\n    placements.push_back({rect_id, rotation, direction, base});\n}\n\npair<int, int> simulate_fast() {\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n    int max_x = 0, max_y = 0;\n    \n    for (size_t idx = 0; idx < placements.size(); idx++) {\n        const auto& p = placements[idx];\n        int w = rects[p.rect_id].w_obs;\n        int h = rects[p.rect_id].h_obs;\n        \n        if (p.rotation == 1) swap(w, h);\n        dim[p.rect_id] = {w, h};\n        \n        int x = 0, y = 0;\n        \n        if (p.direction == 'U') {\n            if (p.base == -1) {\n                x = 0;\n            } else {\n                x = pos[p.base].first + dim[p.base].first;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            if (p.base == -1) {\n                y = 0;\n            } else {\n                y = pos[p.base].second + dim[p.base].second;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        pos[p.rect_id] = {x, y};\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\nvector<int> get_candidate_bases(int rect_idx, int max_candidates, bool prefer_corner = true) {\n    vector<int> candidates;\n    candidates.push_back(-1);\n    \n    if (rect_idx == 0) return candidates;\n    \n    vector<pair<long long, int>> scored_bases;\n    for (int i = 0; i < rect_idx && i < N; i++) {\n        if (pos[i].first >= 0) {\n            long long score;\n            if (prefer_corner) {\n                score = (long long)pos[i].first + pos[i].second;\n            } else {\n                // Prefer rectangles with larger dimensions for better anchoring\n                score = -(long long)dim[i].first * dim[i].second;\n            }\n            scored_bases.push_back({score, i});\n        }\n    }\n    \n    sort(scored_bases.begin(), scored_bases.end());\n    \n    for (int i = 0; i < min((int)scored_bases.size(), max_candidates - 1); i++) {\n        candidates.push_back(scored_bases[i].second);\n    }\n    \n    return candidates;\n}\n\nint evaluate_placement() {\n    auto dims = simulate_fast();\n    long long score = (long long)dims.first + dims.second;\n    // Penalize non-square aspect ratio\n    long long diff = abs(dims.first - dims.second);\n    score += diff / 5;\n    return (int)score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto get_elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    rects.resize(N);\n    long long total_area = 0;\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n        rects[i].aspect = (double)rects[i].w_obs / rects[i].h_obs;\n        rects[i].area = rects[i].w_obs * rects[i].h_obs;\n        total_area += rects[i].area;\n    }\n    \n    vector<Placement> best_placements;\n    long long best_score = LLONG_MAX;\n    int best_turn = -1;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const double TIME_LIMIT = 2.6;\n    \n    // Three phases\n    int phase1_end = (int)(T * 0.5);  // Exploration with different strategies\n    int phase2_end = (int)(T * 0.8);  // Intensive local search\n    // phase3: exploitation (resubmit best)\n    \n    for (int turn = 0; turn < T; turn++) {\n        if (get_elapsed() > TIME_LIMIT) {\n            break;\n        }\n        \n        clear_state();\n        \n        double time_remaining = TIME_LIMIT - get_elapsed();\n        \n        // Phase 3: Exploitation\n        if (turn >= phase2_end) {\n            if (!best_placements.empty()) {\n                placements = best_placements;\n                cout << \"# Turn \" << turn << \" (exploit) best=\" << best_score << \"\\n\";\n                cout << N << \"\\n\";\n                for (const auto& p : placements) {\n                    cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n                }\n                cout.flush();\n                \n                int W_meas, H_meas;\n                cin >> W_meas >> H_meas;\n            }\n            continue;\n        }\n        \n        // Phase 1: Try different strategies\n        int strategy = (turn < phase1_end) ? (turn % 4) : 2;\n        \n        // Adaptive parameters\n        int max_bases = (strategy < 2) ? 10 : 6;\n        int sa_iters = (strategy >= 2) ? 30 : 15;\n        bool prefer_corner = (strategy % 2 == 0);\n        \n        // Greedy construction\n        for (int i = 0; i < N; i++) {\n            int best_rot = 0;\n            char best_dir = 'U';\n            int best_base = -1;\n            int best_local = INT_MAX;\n            \n            vector<int> bases = get_candidate_bases(i, max_bases, prefer_corner);\n            \n            for (int rot = 0; rot < 2; rot++) {\n                for (char dir : {'U', 'L'}) {\n                    for (int base : bases) {\n                        add_placement(i, rot, dir, base);\n                        int score = evaluate_placement();\n                        \n                        if (score < best_local) {\n                            best_local = score;\n                            best_rot = rot;\n                            best_dir = dir;\n                            best_base = base;\n                        }\n                        \n                        placements.pop_back();\n                    }\n                }\n            }\n            \n            add_placement(i, best_rot, best_dir, best_base);\n        }\n        \n        // Simulated annealing (more aggressive in phase 2)\n        if (strategy >= 2 && time_remaining > 0.02) {\n            double temperature = 500.0;\n            const double cooling_rate = 0.92;\n            int actual_sa_iters = min(sa_iters, (int)(time_remaining * 50));\n            \n            int current_score = evaluate_placement();\n            \n            for (int sa_iter = 0; sa_iter < actual_sa_iters; sa_iter++) {\n                temperature *= cooling_rate;\n                \n                // Pick random rectangle\n                int i = uniform_int_distribution<>(0, N-1)(rng);\n                int orig_rot = placements[i].rotation;\n                char orig_dir = placements[i].direction;\n                int orig_base = placements[i].base;\n                \n                // Random modification\n                int move_type = uniform_int_distribution<>(0, 2)(rng);\n                \n                if (move_type == 0) {\n                    placements[i].rotation = 1 - orig_rot;\n                } else if (move_type == 1) {\n                    placements[i].direction = (orig_dir == 'U') ? 'L' : 'U';\n                } else {\n                    vector<int> test_bases = get_candidate_bases(i, 5, prefer_corner);\n                    if (!test_bases.empty()) {\n                        placements[i].base = test_bases[uniform_int_distribution<>(0, (int)test_bases.size()-1)(rng)];\n                    }\n                }\n                \n                int new_score = evaluate_placement();\n                double delta = new_score - current_score;\n                \n                if (delta < 0 || exp(-delta / max(temperature, 1.0)) > uniform_real_distribution<>(0, 1)(rng)) {\n                    current_score = new_score;\n                    if (delta >= 0) {\n                        placements[i].rotation = orig_rot;\n                        placements[i].direction = orig_dir;\n                        placements[i].base = orig_base;\n                    }\n                } else {\n                    placements[i].rotation = orig_rot;\n                    placements[i].direction = orig_dir;\n                    placements[i].base = orig_base;\n                }\n            }\n        }\n        \n        auto final_dims = simulate_fast();\n        int estimated_score = (int)((long long)final_dims.first + final_dims.second);\n        \n        cout << \"# Turn \" << turn << \" strat=\" << strategy << \" est=\" << estimated_score \n             << \" time=\" << get_elapsed() << \"\\n\";\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n        }\n        cout.flush();\n        \n        int W_meas, H_meas;\n        cin >> W_meas >> H_meas;\n        long long measured_score = (long long)W_meas + H_meas;\n        \n        if (measured_score < best_score) {\n            best_score = measured_score;\n            best_placements = placements;\n            best_turn = turn;\n            cout << \"# Best: \" << measured_score << \" turn \" << turn << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\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\n    // Skip coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Start with all vertices as roots (always valid, height = 0 for all)\n    vector<bool> is_root(N, true);\n    vector<int> dist(N, 0);\n    \n    // Fast BFS - only computes distances, returns false if any dist > H\n    auto compute_distances = [&]() -> bool {\n        fill(dist.begin(), dist.end(), -1);\n        queue<int> q;\n        \n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) {\n                dist[i] = 0;\n                q.push(i);\n            }\n        }\n        \n        int max_d = 0;\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            if (dist[u] > max_d) {\n                max_d = dist[u];\n                if (max_d > H) return false;\n            }\n            \n            for (int v : adj[u]) {\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        \n        // Check all reachable\n        for (int i = 0; i < N; ++i) {\n            if (dist[i] == -1) return false;\n        }\n        \n        return true;\n    };\n    \n    // Calculate score\n    auto calc_score = [&]() -> long long {\n        long long score = 1; // Base score\n        for (int i = 0; i < N; ++i) {\n            score += (long long)(dist[i] + 1) * A[i];\n        }\n        return score;\n    };\n    \n    // Initial score\n    compute_distances();\n    long long current_score = calc_score();\n    long long best_score = current_score;\n    vector<bool> best_roots = is_root;\n    vector<int> best_dist = dist;\n    \n    // Random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Phase 1: Aggressive greedy removal\n    // Try to remove each root, keep if valid\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) roots.push_back(i);\n        }\n        \n        // Shuffle for randomness\n        shuffle(roots.begin(), roots.end(), rng);\n        \n        for (int u : roots) {\n            is_root[u] = false;\n            if (compute_distances()) {\n                long long new_score = calc_score();\n                if (new_score >= current_score) {\n                    current_score = new_score;\n                    changed = true;\n                } else {\n                    is_root[u] = true; // Revert - score decreased\n                }\n            } else {\n                is_root[u] = true; // Revert - invalid\n            }\n        }\n    }\n    \n    // Save best after greedy\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_roots = is_root;\n        best_dist = dist;\n    }\n    \n    // Phase 2: Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.85; // Leave time for output\n    \n    double T = 500.0;\n    vector<int> next_dist(N);\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        if (elapsed > time_limit) break;\n        \n        // Cooling schedule - exponential based on time remaining\n        double remaining = time_limit - elapsed;\n        T = max(0.01, 500.0 * pow(remaining / time_limit, 2));\n        \n        // Decide move type\n        int move_type = rng() % 3;\n        bool accepted = false;\n        \n        if (move_type == 0 || move_type == 1) {\n            // Remove a root (2/3 of moves)\n            vector<int> roots;\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n            }\n            \n            if (roots.size() > 1) { // Need at least 1 root\n                int idx = rng() % roots.size();\n                int u = roots[idx];\n                \n                is_root[u] = false;\n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        accepted = true;\n                        \n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                    }\n                } else {\n                    is_root[u] = true;\n                }\n            }\n        } else {\n            // Swap root status (1/3 of moves)\n            vector<int> roots, non_roots;\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n                else non_roots.push_back(i);\n            }\n            \n            if (!roots.empty() && !non_roots.empty() && roots.size() > 1) {\n                int u = roots[rng() % roots.size()];\n                int w = non_roots[rng() % non_roots.size()];\n                \n                is_root[u] = false;\n                is_root[w] = true;\n                \n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        accepted = true;\n                        \n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                        is_root[w] = false;\n                    }\n                } else {\n                    is_root[u] = true;\n                    is_root[w] = false;\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Final greedy refinement on best solution\n    is_root = best_roots;\n    dist = best_dist;\n    current_score = best_score;\n    \n    // Try removing each root one more time\n    vector<int> roots;\n    for (int i = 0; i < N; ++i) {\n        if (is_root[i]) roots.push_back(i);\n    }\n    \n    shuffle(roots.begin(), roots.end(), rng);\n    for (int u : roots) {\n        is_root[u] = false;\n        if (compute_distances()) {\n            long long new_score = calc_score();\n            if (new_score >= current_score) {\n                current_score = new_score;\n                best_score = current_score;\n                best_roots = is_root;\n                best_dist = dist;\n            } else {\n                is_root[u] = true;\n            }\n        } else {\n            is_root[u] = true;\n        }\n    }\n    \n    // Reconstruct parent pointers\n    vector<int> P(N);\n    for (int v = 0; v < N; ++v) {\n        if (best_roots[v]) {\n            P[v] = -1;\n        } else {\n            int d = best_dist[v];\n            int parent = -1;\n            for (int u : adj[v]) {\n                if (best_dist[u] == d - 1) {\n                    parent = u;\n                    break;\n                }\n            }\n            P[v] = parent;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cassert>\n\nusing namespace std;\n\nstruct Piece {\n    int r, c;\n    char type; // 'x' = Oni, 'o' = Fukunokami, '.' = empty\n};\n\nstruct Operation {\n    char dir;\n    int idx;\n};\n\nint N = 20;\nvector<string> board;\nvector<pair<int, int>> oni_positions;\nvector<pair<int, int>> fuku_positions;\n\n// Check if direction is safe for removing Oni at (r, c)\n// dir: 0=up, 1=down, 2=left, 3=right\nbool is_safe_direction(int r, int c, int dir, const vector<string>& bd) {\n    if (dir == 0) { // up\n        for (int i = 0; i < r; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 1) { // down\n        for (int i = r + 1; i < N; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 2) { // left\n        for (int j = 0; j < c; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    } else { // right\n        for (int j = c + 1; j < N; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    }\n}\n\n// Calculate cost to remove Oni at (r, c) in given direction\nint get_cost(int r, int c, int dir) {\n    if (dir == 0) return 2 * (r + 1); // up then down\n    if (dir == 1) return 2 * (N - r); // down then up\n    if (dir == 2) return 2 * (c + 1); // left then right\n    return 2 * (N - c); // right then left\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n    }\n    \n    // Find all Oni and Fukunokami positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == 'x') {\n                oni_positions.push_back({i, j});\n            } else if (board[i][j] == 'o') {\n                fuku_positions.push_back({i, j});\n            }\n        }\n    }\n    \n    vector<Operation> ops;\n    vector<string> current_board = board;\n    \n    // Process each Oni\n    // Sort by minimum cost to remove (greedy approach)\n    struct OniInfo {\n        int r, c, best_dir, cost;\n    };\n    \n    vector<OniInfo> oni_list;\n    for (auto& p : oni_positions) {\n        int best_dir = -1;\n        int min_cost = 1e9;\n        for (int dir = 0; dir < 4; dir++) {\n            if (is_safe_direction(p.first, p.second, dir, current_board)) {\n                int cost = get_cost(p.first, p.second, dir);\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_dir = dir;\n                }\n            }\n        }\n        oni_list.push_back({p.first, p.second, best_dir, min_cost});\n    }\n    \n    // Sort by cost (remove cheapest first)\n    sort(oni_list.begin(), oni_list.end(), [](const OniInfo& a, const OniInfo& b) {\n        return a.cost < b.cost;\n    });\n    \n    // Remove each Oni\n    for (auto& oni : oni_list) {\n        int r = oni.r, c = oni.c;\n        int dir = oni.best_dir;\n        \n        if (dir == 0) { // up\n            // Shift column c upward (r+1) times\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'U', c});\n                // Update board\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n            // Shift column c downward (r+1) times to restore\n            for (int k = 0; k <= r; k++) {\n                ops.push_back({'D', c});\n                // Update board\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n        } else if (dir == 1) { // down\n            // Shift column c downward (N-r) times\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'D', c});\n                for (int i = N - 1; i > 0; i--) {\n                    current_board[i][c] = current_board[i - 1][c];\n                }\n                current_board[0][c] = '.';\n            }\n            // Shift column c upward (N-r) times to restore\n            for (int k = 0; k < N - r; k++) {\n                ops.push_back({'U', c});\n                for (int i = 0; i < N - 1; i++) {\n                    current_board[i][c] = current_board[i + 1][c];\n                }\n                current_board[N - 1][c] = '.';\n            }\n        } else if (dir == 2) { // left\n            // Shift row r leftward (c+1) times\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n            // Shift row r rightward (c+1) times to restore\n            for (int k = 0; k <= c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n        } else { // right\n            // Shift row r rightward (N-c) times\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'R', r});\n                for (int j = N - 1; j > 0; j--) {\n                    current_board[r][j] = current_board[r][j - 1];\n                }\n                current_board[r][0] = '.';\n            }\n            // Shift row r leftward (N-c) times to restore\n            for (int k = 0; k < N - c; k++) {\n                ops.push_back({'L', r});\n                for (int j = 0; j < N - 1; j++) {\n                    current_board[r][j] = current_board[r][j + 1];\n                }\n                current_board[r][N - 1] = '.';\n            }\n        }\n    }\n    \n    // Output operations\n    for (auto& op : ops) {\n        cout << op.dir << \" \" << op.idx << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    long long L;\n    cin >> N >> L;\n    \n    vector<long long> T(N);\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n    \n    // Use fixed seed for reproducibility, or time-based for variety\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Create weighted candidate distribution based on target frequencies\n    vector<int> weighted_candidates;\n    for (int i = 0; i < N; i++) {\n        // Higher target = more likely to be chosen as next cleaner\n        int weight = max(1, (int)(T[i] / 500 + 1));\n        for (int j = 0; j < weight; j++) {\n            weighted_candidates.push_back(i);\n        }\n    }\n    \n    // Initialize a and b arrays\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; i++) {\n        a[i] = weighted_candidates[rng() % weighted_candidates.size()];\n        b[i] = weighted_candidates[rng() % weighted_candidates.size()];\n    }\n    \n    // Simulation function\n    auto simulate = [&]() -> vector<long long> {\n        vector<long long> count(N, 0);\n        int current = 0;\n        \n        for (long long week = 0; week < L; week++) {\n            count[current]++;\n            // t = count[current] is the number of times current has cleaned\n            // If t is odd (1st, 3rd, 5th...), use a[current]\n            // If t is even (2nd, 4th, 6th...), use b[current]\n            if (count[current] % 2 == 1) {\n                current = a[current];\n            } else {\n                current = b[current];\n            }\n        }\n        \n        return count;\n    };\n    \n    // Error calculation\n    auto calcError = [&](const vector<long long>& actual) -> long long {\n        long long error = 0;\n        for (int i = 0; i < N; i++) {\n            error += abs(actual[i] - T[i]);\n        }\n        return error;\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_error = 1e18;\n    vector<int> best_a = a, best_b = b;\n    \n    // Main optimization loop\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Stop with buffer time for output\n        if (elapsed > 1950) break;\n        \n        // Evaluate current solution\n        vector<long long> actual = simulate();\n        long long error = calcError(actual);\n        \n        // Track best solution\n        if (error < best_error) {\n            best_error = error;\n            best_a = a;\n            best_b = b;\n        }\n        \n        // Local search: modify one parameter\n        int i = rng() % N;\n        int choice = rng() % 2;  // 0 = modify a[i], 1 = modify b[i]\n        int old_val = (choice == 0) ? a[i] : b[i];\n        \n        // Try new value from weighted candidates\n        int new_val = weighted_candidates[rng() % weighted_candidates.size()];\n        \n        if (choice == 0) {\n            a[i] = new_val;\n        } else {\n            b[i] = new_val;\n        }\n        \n        // Evaluate new solution\n        vector<long long> new_actual = simulate();\n        long long new_error = calcError(new_actual);\n        \n        // Simulated annealing acceptance criterion\n        if (new_error < error) {\n            // Always accept improvements\n        } else {\n            // Accept worse solutions with decreasing probability over time\n            double progress = (double)elapsed / 2000.0;\n            double temperature = 1000.0 * (1.0 - progress);\n            temperature = max(1.0, temperature);\n            \n            double acceptance_prob = exp(-(double)(new_error - error) / temperature);\n            \n            if ((double)rng() / rng.max() > acceptance_prob) {\n                // Revert change\n                if (choice == 0) {\n                    a[i] = old_val;\n                } else {\n                    b[i] = old_val;\n                }\n            }\n        }\n    }\n    \n    // Output best solution found\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 <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <chrono>\n#include <random>\n#include <iomanip>\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 weight;\n    double confidence; // 1.0 for query edges, <1.0 for estimated\n    bool fromQuery;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(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        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\n// Hilbert curve distance for better spatial locality\nint hilbertDist(int x, int y, int order = 14) {\n    int d = 0;\n    for (int s = 1 << (order - 1); s > 0; s >>= 1) {\n        int rx = (x & s) > 0;\n        int ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (rx == 0) {\n            if (ry == 1) {\n                x = (1 << order) - 1 - x;\n                y = (1 << order) - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// Minimum possible distance between two rectangles\nint minRectDist(const City& a, const City& b) {\n    int dx = 0, dy = 0;\n    if (a.rx < b.lx) dx = b.lx - a.rx;\n    else if (b.rx < a.lx) dx = a.lx - b.rx;\n    \n    if (a.ry < b.ly) dy = b.ly - a.ry;\n    else if (b.ry < a.ly) dy = a.ly - b.ry;\n    \n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Estimated distance using centers (more optimistic)\nint centerDist(const City& a, const City& b) {\n    double dx = a.cx - b.cx;\n    double dy = a.cy - b.cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\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, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    \n    vector<int> G(M);\n    for (int i = 0; i < M; i++) {\n        cin >> G[i];\n    }\n    \n    vector<City> cities(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 Hilbert curve distance for better spatial locality\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int ha = hilbertDist((int)cities[a].cx, (int)cities[a].cy);\n        int hb = hilbertDist((int)cities[b].cx, (int)cities[b].cy);\n        return ha < hb;\n    });\n    \n    // Assign cities to groups based on spatial ordering\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n    \n    // Track all known edges globally\n    map<pair<int,int>, Edge> knownEdges;\n    vector<vector<pair<int,int>>> groupEdges(M);\n    \n    int queriesUsed = 0;\n    \n    // Calculate query priority for each group\n    // Larger groups and groups with higher uncertainty get more queries\n    vector<pair<double, int>> groupPriority(M);\n    for (int i = 0; i < M; i++) {\n        int size = groups[i].size();\n        if (size < 2) {\n            groupPriority[i] = {0.0, i};\n            continue;\n        }\n        // Priority based on: number of edges needed * uncertainty\n        double uncertainty = 0;\n        for (int j = 0; j < size && j < 10; j++) {\n            for (int k = j + 1; k < size && k < 10; k++) {\n                int minD = minRectDist(cities[groups[i][j]], cities[groups[i][k]]);\n                int cenD = centerDist(cities[groups[i][j]], cities[groups[i][k]]);\n                uncertainty += (cenD - minD + 1);\n            }\n        }\n        // More edges needed = higher priority\n        groupPriority[i] = {(size - 1) * (1.0 + uncertainty / 100.0), i};\n    }\n    sort(groupPriority.begin(), groupPriority.end(), greater<pair<double,int>>());\n    \n    // Query each group strategically\n    for (auto& [priority, gi] : groupPriority) {\n        // Time check - leave margin for output\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        if (elapsed > 1850 || queriesUsed >= Q) break;\n        \n        int groupSize = groups[gi].size();\n        if (groupSize < 2) continue;\n        \n        // Calculate how many queries we can use for this group\n        int edgesNeeded = groupSize - 1;\n        int maxQueriesForGroup = min((Q - queriesUsed), (edgesNeeded + L - 2) / (L - 1));\n        \n        // Ensure we cover all cities in the group\n        vector<bool> covered(groupSize, false);\n        int queriesForThisGroup = 0;\n        \n        // First pass: ensure all cities are covered\n        for (int start = 0; start < groupSize && queriesForThisGroup < maxQueriesForGroup && queriesUsed < Q; ) {\n            int remaining = groupSize - start;\n            int chunkSize = min(L, remaining);\n            \n            if (chunkSize < 2) {\n                // Connect remaining city to previous\n                if (start > 0 && start < groupSize) {\n                    int u = groups[gi][start - 1];\n                    int v = groups[gi][start];\n                    if (u > v) swap(u, v);\n                    if (knownEdges.find({u, v}) == knownEdges.end()) {\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 0.5, false};\n                    }\n                }\n                break;\n            }\n            \n            // Make query\n            cout << \"?\" << \" \" << chunkSize;\n            for (int i = 0; i < chunkSize; i++) {\n                cout << \" \" << groups[gi][start + i];\n                covered[start + i] = true;\n            }\n            cout << endl;\n            cout.flush();\n            \n            queriesUsed++;\n            queriesForThisGroup++;\n            \n            // Read MST edges from response\n            for (int i = 0; i < chunkSize - 1; i++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                \n                // Mark as high confidence query edge\n                knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n            }\n            \n            // Move forward, overlap by 1 to ensure connectivity\n            start += chunkSize - 1;\n        }\n        \n        // Second pass: cover any missed cities with small queries\n        for (int i = 0; i < groupSize && queriesUsed < Q; i++) {\n            if (!covered[i]) {\n                // Find nearest covered city to query with\n                int bestJ = -1;\n                int bestDist = 1e9;\n                for (int j = 0; j < groupSize; j++) {\n                    if (covered[j] && j != i) {\n                        int d = centerDist(cities[groups[gi][i]], cities[groups[gi][j]]);\n                        if (d < bestDist) {\n                            bestDist = d;\n                            bestJ = j;\n                        }\n                    }\n                }\n                \n                if (bestJ >= 0) {\n                    int chunkSize = 2;\n                    if (queriesUsed < Q - 1) {\n                        // Try to add one more city if possible\n                        for (int k = 0; k < groupSize && chunkSize < L; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                chunkSize++;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    cout << \"?\" << \" \" << chunkSize << \" \" << groups[gi][i];\n                    int count = 1;\n                    if (count < chunkSize) {\n                        cout << \" \" << groups[gi][bestJ];\n                        count++;\n                        for (int k = 0; k < groupSize && count < chunkSize; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                cout << \" \" << groups[gi][k];\n                                count++;\n                            }\n                        }\n                    }\n                    cout << endl;\n                    cout.flush();\n                    \n                    queriesUsed++;\n                    \n                    for (int e = 0; e < chunkSize - 1; e++) {\n                        int u, v;\n                        cin >> u >> v;\n                        if (u > v) swap(u, v);\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n                    }\n                    covered[i] = true;\n                }\n            }\n        }\n    }\n    \n    // Build complete MST for each group using all available edges\n    for (int g = 0; g < M; g++) {\n        int groupSize = groups[g].size();\n        if (groupSize < 2) continue;\n        \n        vector<Edge> allEdges;\n        set<pair<int,int>> added;\n        \n        // Add all known edges for cities in this group\n        for (auto& [key, edge] : knownEdges) {\n            bool inGroup = false;\n            for (int city : groups[g]) {\n                if (city == edge.u || city == edge.v) {\n                    inGroup = true;\n                    break;\n                }\n            }\n            if (!inGroup) continue;\n            \n            // Check both endpoints are in this group\n            bool uIn = false, vIn = false;\n            for (int city : groups[g]) {\n                if (city == edge.u) uIn = true;\n                if (city == edge.v) vIn = true;\n            }\n            if (!uIn || !vIn) continue;\n            \n            if (added.find({edge.u, edge.v}) == added.end()) {\n                allEdges.push_back(edge);\n                added.insert({edge.u, edge.v});\n            }\n        }\n        \n        // Add estimated edges for missing connections\n        for (int i = 0; i < groupSize; i++) {\n            for (int j = i + 1; j < groupSize; j++) {\n                int u = groups[g][i];\n                int v = groups[g][j];\n                if (u > v) swap(u, v);\n                \n                if (added.find({u, v}) == added.end()) {\n                    int minD = minRectDist(cities[u], cities[v]);\n                    int cenD = centerDist(cities[u], cities[v]);\n                    // Use weighted average of min and center distance\n                    int estD = (minD + cenD) / 2;\n                    allEdges.push_back({u, v, estD, 0.3, false});\n                    added.insert({u, v});\n                }\n            }\n        }\n        \n        // Build MST - prefer query edges (high confidence), then by weight\n        sort(allEdges.begin(), allEdges.end(), [&](const Edge& a, const Edge& b) {\n            if (a.fromQuery != b.fromQuery) return a.fromQuery > b.fromQuery;\n            if (abs(a.confidence - b.confidence) > 0.1) return a.confidence > b.confidence;\n            return a.weight < b.weight;\n        });\n        \n        vector<pair<int,int>> mstEdges;\n        DSU dsu(N);\n        \n        for (auto& e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                mstEdges.push_back({e.u, e.v});\n                if ((int)mstEdges.size() == groupSize - 1) break;\n            }\n        }\n        \n        // Fallback: if MST is incomplete, add any remaining edges\n        if ((int)mstEdges.size() < groupSize - 1) {\n            DSU dsu2(N);\n            for (auto& e : mstEdges) {\n                dsu2.unite(e.first, e.second);\n            }\n            for (auto& e : allEdges) {\n                if (dsu2.unite(e.u, e.v)) {\n                    mstEdges.push_back({e.u, e.v});\n                    if ((int)mstEdges.size() == groupSize - 1) break;\n                }\n            }\n        }\n        \n        groupEdges[g] = mstEdges;\n    }\n    \n    // Output final answer\n    cout << \"!\" << endl;\n    cout.flush();\n    \n    for (int g = 0; g < M; g++) {\n        // Output cities in group\n        for (int i = 0; i < (int)groups[g].size(); i++) {\n            if (i > 0) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : groupEdges[g]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint cur_i, cur_j;\nvector<pair<int, int>> targets;\nset<pair<int, int>> blocks;\n\n// Direction arrays at global scope\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && blocks.find({i, j}) == blocks.end();\n}\n\npair<int, int> getSlideEnd(int i, int j, int di, int dj) {\n    while (true) {\n        int ni = i + di, nj = j + dj;\n        if (!isValid(ni, nj)) break;\n        i = ni;\n        j = nj;\n    }\n    return {i, j};\n}\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nvoid solve() {\n    cin >> N >> M;\n    cin >> cur_i >> cur_j;\n    for (int k = 0; k < M; k++) {\n        int i, j;\n        cin >> i >> j;\n        targets.push_back({i, j});\n    }\n    \n    vector<pair<char, char>> allActions;\n    \n    for (int t = 0; t < M; t++) {\n        int ti = targets[t].first;\n        int tj = targets[t].second;\n        vector<pair<char, char>> targetActions;\n        \n        // Simple BFS to find path to target\n        queue<tuple<int, int, vector<pair<char, char>>>> q;\n        vector<pair<char, char>> emptyPath;\n        q.push({cur_i, cur_j, emptyPath});\n        \n        set<pair<int, int>> visited;\n        visited.insert({cur_i, cur_j});\n        bool found = false;\n        \n        int maxDepth = 200;\n        \n        while (!q.empty() && !found) {\n            auto [pi, pj, path] = q.front();\n            q.pop();\n            \n            if ((int)path.size() > maxDepth) continue;\n            \n            if (pi == ti && pj == tj) {\n                targetActions = path;\n                found = true;\n                break;\n            }\n            \n            // Try moves\n            for (int d = 0; d < 4; d++) {\n                int ni = pi + DI[d], nj = pj + DJ[d];\n                \n                if (isValid(ni, nj) && !visited.count({ni, nj})) {\n                    visited.insert({ni, nj});\n                    auto newPath = path;\n                    newPath.emplace_back('M', DIR_CHAR[d]);\n                    q.push({ni, nj, newPath});\n                }\n                \n                // Try slides\n                auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                if ((si != pi || sj != pj) && !visited.count({si, sj})) {\n                    visited.insert({si, sj});\n                    auto newPath = path;\n                    newPath.emplace_back('S', DIR_CHAR[d]);\n                    q.push({si, sj, newPath});\n                }\n            }\n        }\n        \n        // Fallback: greedy approach if BFS fails\n        if (!found) {\n            int pi = cur_i, pj = cur_j;\n            \n            while (pi != ti || pj != tj) {\n                bool moved = false;\n                \n                // Try slides first\n                for (int d = 0; d < 4; d++) {\n                    auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                    \n                    if (si == ti && sj == tj) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                    \n                    int oldDist = manhattan(pi, pj, ti, tj);\n                    int newDist = manhattan(si, sj, ti, tj);\n                    \n                    if (newDist < oldDist && (si != pi || sj != pj)) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                }\n                \n                if (!moved) {\n                    // Use move\n                    if (pi < ti) {\n                        targetActions.emplace_back('M', 'D');\n                        pi++;\n                    } else if (pi > ti) {\n                        targetActions.emplace_back('M', 'U');\n                        pi--;\n                    } else if (pj < tj) {\n                        targetActions.emplace_back('M', 'R');\n                        pj++;\n                    } else if (pj > tj) {\n                        targetActions.emplace_back('M', 'L');\n                        pj--;\n                    }\n                }\n                \n                if ((int)targetActions.size() > maxDepth) break;\n            }\n        }\n        \n        // Execute actions and update blocks\n        for (auto& action : targetActions) {\n            char act = action.first;\n            char dir = action.second;\n            \n            if (act == 'M') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        cur_i += DI[d];\n                        cur_j += DJ[d];\n                        break;\n                    }\n                }\n            } else if (act == 'S') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        tie(cur_i, cur_j) = getSlideEnd(cur_i, cur_j, DI[d], DJ[d]);\n                        break;\n                    }\n                }\n            } else if (act == 'A') {\n                int bi = cur_i, bj = cur_j;\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        bi += DI[d];\n                        bj += DJ[d];\n                        break;\n                    }\n                }\n                if (blocks.count({bi, bj})) blocks.erase({bi, bj});\n                else blocks.insert({bi, bj});\n            }\n            allActions.emplace_back(act, dir);\n        }\n    }\n    \n    for (auto& action : allActions) {\n        cout << action.first << \" \" << action.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\n// Check if two rectangles overlap (have positive area intersection)\nbool rectangles_overlap(const Rect& a, const Rect& b) {\n    int x_overlap = max(0, min(a.x2, b.x2) - max(a.x1, b.x1));\n    int y_overlap = max(0, min(a.y2, b.y2) - max(a.y1, b.y1));\n    return x_overlap > 0 && y_overlap > 0;\n}\n\n// Validate all rectangles are non-overlapping\nbool validate_rectangles(const vector<Rect>& rects) {\n    int n = rects.size();\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            if (rectangles_overlap(rects[i], rects[j])) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Validate all rectangles are within bounds\nbool validate_bounds(const vector<Rect>& rects) {\n    for (int i = 0; i < (int)rects.size(); i++) {\n        if (rects[i].x1 < 0 || rects[i].y1 < 0 || \n            rects[i].x2 > 10000 || rects[i].y2 > 10000 ||\n            rects[i].x1 >= rects[i].x2 || rects[i].y1 >= rects[i].y2) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Recursive space partitioning - GUARANTEES no overlaps by construction\nvoid partition(vector<int>& indices, const vector<Company>& companies, \n               Rect region, vector<Rect>& result) {\n    if (indices.empty()) return;\n    \n    if (indices.size() == 1) {\n        int idx = indices[0];\n        result[companies[idx].id] = region;\n        return;\n    }\n    \n    // Calculate total area needed for this region\n    long long total_area = 0;\n    int min_x = 10001, max_x = -1, min_y = 10001, max_y = -1;\n    for (int idx : indices) {\n        total_area += companies[idx].r;\n        min_x = min(min_x, companies[idx].x);\n        max_x = max(max_x, companies[idx].x);\n        min_y = min(min_y, companies[idx].y);\n        max_y = max(max_y, companies[idx].y);\n    }\n    \n    // Determine split direction based on point distribution\n    bool split_vertical = (max_x - min_x) >= (max_y - min_y);\n    \n    // Sort indices for splitting\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        if (split_vertical) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        } else {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        }\n    });\n    \n    // Find split point that balances area\n    long long left_area = 0;\n    int split_idx = 1;\n    long long best_diff = LLONG_MAX;\n    \n    for (int i = 0; i < (int)indices.size() - 1; i++) {\n        left_area += companies[indices[i]].r;\n        long long diff = abs(2 * left_area - total_area);\n        if (diff < best_diff) {\n            best_diff = diff;\n            split_idx = i + 1;\n        }\n    }\n    \n    long long left_sum = 0;\n    for (int i = 0; i < split_idx; i++) {\n        left_sum += companies[indices[i]].r;\n    }\n    \n    vector<int> left_indices(indices.begin(), indices.begin() + split_idx);\n    vector<int> right_indices(indices.begin() + split_idx, indices.end());\n    \n    Rect left_region = region, right_region = region;\n    \n    if (split_vertical) {\n        // Vertical split - ensure split line doesn't cut through any point\n        // Find safe split position between left and right point sets\n        int left_max_x = -1, right_min_x = 10001;\n        for (int idx : left_indices) {\n            left_max_x = max(left_max_x, companies[idx].x);\n        }\n        for (int idx : right_indices) {\n            right_min_x = min(right_min_x, companies[idx].x);\n        }\n        \n        // Calculate ideal split based on area ratio\n        int ideal_split = region.x1 + (int)((left_sum * (region.x2 - region.x1) + total_area/2) / total_area);\n        \n        // Find safe split position\n        int split_x;\n        if (left_max_x < right_min_x) {\n            // There's a gap between point sets - split in the gap\n            split_x = max(region.x1 + 1, min(region.x2 - 1, (left_max_x + right_min_x + 1) / 2));\n        } else {\n            // Points overlap in x - use ideal split but ensure it's valid\n            split_x = max(region.x1 + 1, min(region.x2 - 1, ideal_split));\n        }\n        \n        // Ensure both regions have positive area\n        if (split_x <= region.x1) split_x = region.x1 + 1;\n        if (split_x >= region.x2) split_x = region.x2 - 1;\n        split_x = max(region.x1 + 1, min(region.x2 - 1, split_x));\n        \n        left_region.x2 = split_x;\n        right_region.x1 = split_x;\n    } else {\n        // Horizontal split\n        int left_max_y = -1, right_min_y = 10001;\n        for (int idx : left_indices) {\n            left_max_y = max(left_max_y, companies[idx].y);\n        }\n        for (int idx : right_indices) {\n            right_min_y = min(right_min_y, companies[idx].y);\n        }\n        \n        int ideal_split = region.y1 + (int)((left_sum * (region.y2 - region.y1) + total_area/2) / total_area);\n        \n        int split_y;\n        if (left_max_y < right_min_y) {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, (left_max_y + right_min_y + 1) / 2));\n        } else {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, ideal_split));\n        }\n        \n        if (split_y <= region.y1) split_y = region.y1 + 1;\n        if (split_y >= region.y2) split_y = region.y2 - 1;\n        split_y = max(region.y1 + 1, min(region.y2 - 1, split_y));\n        \n        left_region.y2 = split_y;\n        right_region.y1 = split_y;\n    }\n    \n    // Ensure both regions have positive area\n    if (left_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x1 + 1;\n            right_region.x1 = region.x1 + 1;\n        } else {\n            left_region.y2 = region.y1 + 1;\n            right_region.y1 = region.y1 + 1;\n        }\n    }\n    if (right_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x2 - 1;\n            right_region.x1 = region.x2 - 1;\n        } else {\n            left_region.y2 = region.y2 - 1;\n            right_region.y1 = region.y2 - 1;\n        }\n    }\n    \n    partition(left_indices, companies, left_region, result);\n    partition(right_indices, companies, right_region, result);\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    long long total_r = 0;\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        total_r += companies[i].r;\n    }\n    \n    // Create order based on spatial locality\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    \n    // Sort by x + y for better spatial coherence\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        return companies[i].x + companies[i].y < companies[j].x + companies[j].y;\n    });\n    \n    // Initial partitioning - NO post-adjustment\n    vector<Rect> rects(n);\n    Rect full_region = {0, 0, 10000, 10000};\n    partition(order, companies, full_region, rects);\n    \n    // VALIDATE before output\n    #ifdef DEBUG\n    if (!validate_rectangles(rects)) {\n        cerr << \"ERROR: Overlaps detected!\" << endl;\n    }\n    if (!validate_bounds(rects)) {\n        cerr << \"ERROR: Bounds violated!\" << endl;\n    }\n    #endif\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        cout << rects[i].x1 << \" \" << rects[i].y1 << \" \" \n             << rects[i].x2 << \" \" << rects[i].y2 << \"\\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\nusing namespace std;\n\nconst int H = 50;\nconst int W = 50;\nvector<vector<int>> tile_id;\nvector<vector<int>> score_val;\nint max_tile = 0;\n\nvector<char> visited_tiles;\nmt19937 rng;\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\n\n// Evaluation with 2-step lookahead (proven effective)\ninline int evaluate_cell(int r, int c) {\n    int tid = tile_id[r][c];\n    if (visited_tiles[tid]) return -1000000;\n    \n    int base_score = score_val[r][c];\n    int future_score = 0;\n    int available_exits = 0;\n    \n    for (int i = 0; i < 4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n            int ntid = tile_id[nr][nc];\n            if (!visited_tiles[ntid]) {\n                available_exits++;\n                future_score += score_val[nr][nc];\n                \n                // Second level lookahead\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j];\n                    int nnc = nc + dc[j];\n                    if (nnr >= 0 && nnr < H && nnc >= 0 && nnc < W) {\n                        int nntid = tile_id[nnr][nnc];\n                        if (!visited_tiles[nntid]) {\n                            future_score += score_val[nnr][nnc] / 4;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (available_exits == 0) return -500000;\n    \n    return base_score * 10 + future_score / 2 + available_exits * 500;\n}\n\n// Path extension with weighted selection (proven effective)\ninline void extend_path(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    while (true) {\n        struct Cand {\n            int r, c, eval;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    cands[count++] = {nr, nc, evaluate_cell(nr, nc)};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort by evaluation (descending) - simple bubble sort for small array\n        for (int i = 0; i < count - 1; ++i) {\n            for (int j = i + 1; j < count; ++j) {\n                if (cands[j].eval > cands[i].eval) {\n                    swap(cands[i], cands[j]);\n                }\n            }\n        }\n        \n        // Weighted selection from top candidates\n        int top_k = (count < 3) ? count : 3;\n        double weights[3];\n        double total_weight = 0;\n        for (int i = 0; i < top_k; ++i) {\n            weights[i] = pow(0.6, (double)i);\n            total_weight += weights[i];\n        }\n        \n        uniform_real_distribution<double> dist(0.0, total_weight);\n        double roll = dist(rng);\n        double cum = 0;\n        int idx = 0;\n        for (int i = 0; i < top_k; ++i) {\n            cum += weights[i];\n            if (roll <= cum) {\n                idx = i;\n                break;\n            }\n        }\n        \n        int nr = cands[idx].r;\n        int nc = cands[idx].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    tile_id.assign(H, vector<int>(W));\n    max_tile = 0;\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> tile_id[i][j];\n            if (tile_id[i][j] > max_tile) max_tile = tile_id[i][j];\n        }\n    }\n    \n    score_val.assign(H, vector<int>(W));\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> score_val[i][j];\n        }\n    }\n    \n    visited_tiles.assign(max_tile + 1, 0);\n    \n    // Simple time-based seed\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time\n        ).count();\n    };\n    \n    // Single initial solution (maximize optimization time)\n    vector<pair<int, int>> current_path;\n    current_path.reserve(2500);\n    current_path.push_back({si, sj});\n    visited_tiles[tile_id[si][sj]] = 1;\n    long long current_score = score_val[si][sj];\n    \n    extend_path(current_path, current_score);\n    \n    vector<pair<int, int>> best_path = current_path;\n    long long best_score = current_score;\n    \n    // Main SA loop - simple and fast\n    double temperature = 500.0;\n    int no_improve = 0;\n    int iteration = 0;\n    \n    while (get_elapsed_ms() < 1950) {\n        iteration++;\n        \n        // Simple exponential cooling\n        temperature *= 0.9995;\n        if (temperature < 1.0) temperature = 1.0;\n        \n        // Backup state (minimal copying)\n        vector<pair<int, int>> path_backup = current_path;\n        long long score_backup = current_score;\n        vector<char> visited_backup = visited_tiles;\n        \n        // Simple cut point selection\n        int cut_idx = (int)(rng() % current_path.size());\n        \n        // Rollback visited tiles after cut point\n        int path_len = (int)current_path.size();\n        for (int i = path_len - 1; i > cut_idx; --i) {\n            int r = current_path[i].first;\n            int c = current_path[i].second;\n            visited_tiles[tile_id[r][c]] = 0;\n        }\n        current_path.resize(cut_idx + 1);\n        \n        // Recalculate prefix score\n        long long temp_score = 0;\n        for (const auto& p : current_path) {\n            temp_score += score_val[p.first][p.second];\n        }\n        \n        // Extend path from cut point\n        extend_path(current_path, temp_score);\n        \n        // SA acceptance criterion\n        bool accept = false;\n        if (temp_score >= current_score) {\n            accept = true;\n        } else {\n            double diff = (double)(temp_score - current_score);\n            double prob = exp(diff / temperature);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = temp_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n                no_improve = 0;\n            }\n        } else {\n            // Revert to backup state\n            for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 0;\n            }\n            current_path = path_backup;\n            current_score = score_backup;\n            visited_tiles = visited_backup;\n            no_improve++;\n        }\n        \n        // Restart if stuck (simple heuristic)\n        if (no_improve > 300 && get_elapsed_ms() < 1600) {\n            fill(visited_tiles.begin(), visited_tiles.end(), 0);\n            current_path.clear();\n            current_path.push_back({si, sj});\n            visited_tiles[tile_id[si][sj]] = 1;\n            current_score = score_val[si][sj];\n            extend_path(current_path, current_score);\n            no_improve = 0;\n            temperature = 500.0;\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n            }\n        }\n    }\n    \n    // Construct output string\n    string res;\n    if (best_path.size() > 1) {\n        res.reserve(best_path.size() - 1);\n        for (size_t i = 1; i < best_path.size(); ++i) {\n            int dr_val = best_path[i].first - best_path[i-1].first;\n            int dc_val = best_path[i].second - best_path[i-1].second;\n            if (dr_val == -1) res += 'U';\n            else if (dr_val == 1) res += 'D';\n            else if (dc_val == -1) res += 'L';\n            else if (dc_val == 1) res += 'R';\n        }\n    }\n    cout << res << endl;\n    \n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Solver {\n    double h[N][N-1];  // horizontal edges: h[i][j] = edge from (i,j) to (i,j+1)\n    double v[N-1][N];  // vertical edges: v[i][j] = edge from (i,j) to (i+1,j)\n    int h_cnt[N][N-1];\n    int v_cnt[N-1][N];\n    \n    Solver() {\n        for(int i = 0; i < N; i++) {\n            for(int j = 0; j < N-1; j++) {\n                h[i][j] = 5000.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for(int i = 0; i < N-1; i++) {\n            for(int j = 0; j < N; j++) {\n                v[i][j] = 5000.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n    \n    // Get edge weight with bounds checking\n    double get_weight(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v[i-1][j] : 1e9;\n        if(dir == 'D') return (i < N-1) ? v[i][j] : 1e9;\n        if(dir == 'L') return (j > 0) ? h[i][j-1] : 1e9;\n        if(dir == 'R') return (j < N-1) ? h[i][j] : 1e9;\n        return 1e9;\n    }\n    \n    // Get visit count for an edge\n    int get_count(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v_cnt[i-1][j] : 0;\n        if(dir == 'D') return (i < N-1) ? v_cnt[i][j] : 0;\n        if(dir == 'L') return (j > 0) ? h_cnt[i][j-1] : 0;\n        if(dir == 'R') return (j < N-1) ? h_cnt[i][j] : 0;\n        return 0;\n    }\n    \n    pair<string, double> dijkstra(int si, int sj, int ti, int tj, double temp) {\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<char>> move(N, vector<char>(N, 0));\n        \n        dist[si][sj] = 0;\n        pq.push({0.0, si, sj});\n        \n        const char dirs[] = {'U', 'D', 'L', 'R'};\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while(!pq.empty()) {\n            auto [d, i, j] = pq.top();\n            pq.pop();\n            \n            if(d > dist[i][j] + 1e-9) continue;\n            if(i == ti && j == tj) break;\n            \n            for(int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                \n                if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double w = get_weight(i, j, dirs[dir]);\n                if(w >= 1e9) continue;\n                \n                // Exploration bonus: prefer less-visited edges\n                int cnt = get_count(i, j, dirs[dir]);\n                double bonus = temp / (cnt + 1);\n                double new_dist = d + w + bonus;\n                \n                if(new_dist < dist[ni][nj]) {\n                    dist[ni][nj] = new_dist;\n                    prev[ni][nj] = {i, j};\n                    move[ni][nj] = dirs[dir];\n                    pq.push({new_dist, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path;\n        int ci = ti, cj = tj;\n        while(ci != si || cj != sj) {\n            path += move[ci][cj];\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        \n        return {path, dist[ti][tj]};\n    }\n    \n    void update(const string& path, int si, int sj, int observed, int query_num) {\n        if(path.empty()) return;\n        \n        // Calculate estimated cost and track vertices\n        double estimated = 0;\n        int ci = si, cj = sj;\n        vector<tuple<int, int, char>> edges;\n        \n        for(char c : path) {\n            double w = get_weight(ci, cj, c);\n            estimated += w;\n            edges.push_back({ci, cj, c});\n            \n            if(c == 'U') ci--;\n            else if(c == 'D') ci++;\n            else if(c == 'L') cj--;\n            else if(c == 'R') cj++;\n        }\n        \n        if(estimated < 1) estimated = 1;\n        double ratio = (double)observed / estimated;\n        \n        // Learning rate decreases over time\n        double lr = 0.30 * pow(0.992, query_num);\n        lr = max(lr, 0.01);\n        \n        // Update edges on path\n        for(auto& [i, j, c] : edges) {\n            if(c == 'U') {\n                v[i-1][j] = (1-lr) * v[i-1][j] + lr * v[i-1][j] * ratio;\n                v_cnt[i-1][j]++;\n            } else if(c == 'D') {\n                v[i][j] = (1-lr) * v[i][j] + lr * v[i][j] * ratio;\n                v_cnt[i][j]++;\n            } else if(c == 'L') {\n                h[i][j-1] = (1-lr) * h[i][j-1] + lr * h[i][j-1] * ratio;\n                h_cnt[i][j-1]++;\n            } else if(c == 'R') {\n                h[i][j] = (1-lr) * h[i][j] + lr * h[i][j] * ratio;\n                h_cnt[i][j]++;\n            }\n        }\n        \n        // Smoothing: propagate information to same row/column\n        smooth(query_num);\n    }\n    \n    void smooth(int query_num) {\n        double smooth_lr = 0.05 * pow(0.995, query_num);\n        \n        // Smooth horizontal edges within each row\n        for(int i = 0; i < N; i++) {\n            double row_avg = 0;\n            int row_cnt = 0;\n            for(int j = 0; j < N-1; j++) {\n                if(h_cnt[i][j] > 0) {\n                    row_avg += h[i][j];\n                    row_cnt++;\n                }\n            }\n            if(row_cnt > 0) {\n                row_avg /= row_cnt;\n                for(int j = 0; j < N-1; j++) {\n                    if(h_cnt[i][j] > 0) {\n                        h[i][j] = (1-smooth_lr) * h[i][j] + smooth_lr * row_avg;\n                    }\n                }\n            }\n        }\n        \n        // Smooth vertical edges within each column\n        for(int j = 0; j < N; j++) {\n            double col_avg = 0;\n            int col_cnt = 0;\n            for(int i = 0; i < N-1; i++) {\n                if(v_cnt[i][j] > 0) {\n                    col_avg += v[i][j];\n                    col_cnt++;\n                }\n            }\n            if(col_cnt > 0) {\n                col_avg /= col_cnt;\n                for(int i = 0; i < N-1; i++) {\n                    if(v_cnt[i][j] > 0) {\n                        v[i][j] = (1-smooth_lr) * v[i][j] + smooth_lr * col_avg;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    mt19937 rng(42);\n    Solver solver;\n    \n    for(int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Exploration temperature decreases over time\n        // Higher early for exploration, lower later for exploitation\n        double temp = 300.0 * pow(0.994, k);\n        \n        auto [path, est_cost] = solver.dijkstra(si, sj, ti, tj, temp);\n        \n        cout << path << \"\\n\";\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        solver.update(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> S[i];\n    }\n    \n    vector<string> best_grid(N, string(N, '.'));\n    int best_matched = 0;\n    int best_empty = N * N;\n    \n    auto getScore = [&](int matched, int empty_cells) -> double {\n        if (matched < M) {\n            return 1e8 * (double)matched / M;\n        } else {\n            return 1e8 * (2.0 * N * N) / (2.0 * N * N - empty_cells);\n        }\n    };\n    \n    auto checkString = [&](const vector<string>& grid, const string& s) -> bool {\n        int k = (int)s.size();\n        int n = (int)grid.size();\n        if (k > n) return false;\n        \n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                bool match = true;\n                for (int p = 0; p < k; ++p) {\n                    if (grid[i][(j + p) % n] != s[p]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) return true;\n            }\n        }\n        \n        for (int j = 0; j < n; ++j) {\n            for (int i = 0; i < n; ++i) {\n                bool match = true;\n                for (int p = 0; p < k; ++p) {\n                    if (grid[(i + p) % n][j] != s[p]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) return true;\n            }\n        }\n        \n        return false;\n    };\n    \n    auto solve = [&](int seed) -> pair<vector<string>, int> {\n        mt19937 rng(seed);\n        vector<string> grid(N, string(N, '.'));\n        vector<int> indices(M);\n        for (int i = 0; i < M; ++i) indices[i] = i;\n        \n        shuffle(indices.begin(), indices.end(), rng);\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            return S[a].size() > S[b].size();\n        });\n        \n        vector<bool> placed(M, false);\n        \n        for (int idx : indices) {\n            const string& s = S[idx];\n            int k = (int)s.size();\n            int best_orient = -1;\n            int best_i = -1, best_j = -1;\n            int best_score = -1;\n            \n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    int dot_count = 0;\n                    bool ok = true;\n                    for (int p = 0; p < k; ++p) {\n                        int col = (j + p) % N;\n                        if (grid[i][col] != '.' && grid[i][col] != s[p]) {\n                            ok = false;\n                            break;\n                        }\n                        if (grid[i][col] == '.') dot_count++;\n                    }\n                    if (ok) {\n                        int score = dot_count * 1000 + (rng() % 100);\n                        if (score > best_score) {\n                            best_score = score;\n                            best_orient = 0;\n                            best_i = i;\n                            best_j = j;\n                        }\n                    }\n                }\n            }\n            \n            for (int j = 0; j < N; ++j) {\n                for (int i = 0; i < N; ++i) {\n                    int dot_count = 0;\n                    bool ok = true;\n                    for (int p = 0; p < k; ++p) {\n                        int row = (i + p) % N;\n                        if (grid[row][j] != '.' && grid[row][j] != s[p]) {\n                            ok = false;\n                            break;\n                        }\n                        if (grid[row][j] == '.') dot_count++;\n                    }\n                    if (ok) {\n                        int score = dot_count * 1000 + (rng() % 100);\n                        if (score > best_score) {\n                            best_score = score;\n                            best_orient = 1;\n                            best_i = i;\n                            best_j = j;\n                        }\n                    }\n                }\n            }\n            \n            if (best_score >= 0) {\n                placed[idx] = true;\n                for (int p = 0; p < k; ++p) {\n                    int r, c;\n                    if (best_orient == 0) {\n                        r = best_i;\n                        c = (best_j + p) % N;\n                    } else {\n                        r = (best_i + p) % N;\n                        c = best_j;\n                    }\n                    if (grid[r][c] == '.') {\n                        grid[r][c] = s[p];\n                    }\n                }\n            }\n        }\n        \n        vector<int> cnt(256, 0);\n        for (int i = 0; i < M; ++i) {\n            if (!placed[i]) {\n                for (char c : S[i]) cnt[(unsigned char)c]++;\n            }\n        }\n        \n        char fill_char = 'A';\n        int max_cnt = 0;\n        for (char c : string(\"ABCDEFGH\")) {\n            if (cnt[(unsigned char)c] > max_cnt) {\n                max_cnt = cnt[(unsigned char)c];\n                fill_char = c;\n            }\n        }\n        \n        if (max_cnt == 0) {\n            fill_char = 'A';\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == '.') grid[i][j] = fill_char;\n            }\n        }\n        \n        int matched = 0;\n        for (int i = 0; i < M; ++i) {\n            if (checkString(grid, S[i])) matched++;\n        }\n        \n        return {grid, matched};\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    int time_limit_ms = 2800;\n    int trial = 0;\n    \n    while (true) {\n        auto check_time = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(check_time - start_time).count();\n        if (elapsed > time_limit_ms) break;\n        \n        auto [grid, matched] = solve(trial * 12345 + 67890);\n        \n        int empty_cells = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == '.') empty_cells++;\n            }\n        }\n        \n        double score = getScore(matched, empty_cells);\n        double best_score = getScore(best_matched, best_empty);\n        \n        if (score > best_score || (matched > best_matched && score == best_score)) {\n            best_matched = matched;\n            best_empty = empty_cells;\n            best_grid = grid;\n        }\n        \n        if (matched == M && empty_cells == 0) break;\n        \n        trial++;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << best_grid[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <map>\n#include <functional>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\n\nint flatten(int r, int c) {\n    return r * N + c;\n}\n\nPoint unflatten(int idx) {\n    return {idx / N, idx % N};\n}\n\nint get_cost(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N || grid[r][c] == '#') return 1e9;\n    return grid[r][c] - '0';\n}\n\n// Get all road squares\nvector<Point> getAllRoads() {\n    vector<Point> roads;\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    return roads;\n}\n\n// Check if road square (tr, tc) is visible from (sr, sc)\nbool isVisible(int sr, int sc, int tr, int tc) {\n    if (grid[sr][sc] == '#' || grid[tr][tc] == '#') return false;\n    \n    if (sr == tr) {\n        int min_c = min(sc, tc), max_c = max(sc, tc);\n        for (int c = min_c; c <= max_c; ++c) {\n            if (grid[sr][c] == '#') return false;\n        }\n        return true;\n    }\n    if (sc == tc) {\n        int min_r = min(sr, tr), max_r = max(sr, tr);\n        for (int r = min_r; r <= max_r; ++r) {\n            if (grid[r][sc] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\n// Get all visible road squares from a point\nvector<int> getVisibleFrom(int r, int c, const vector<Point>& all_roads) {\n    vector<int> visible;\n    if (grid[r][c] == '#') return visible;\n    \n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        if (isVisible(r, c, all_roads[i].r, all_roads[i].c)) {\n            visible.push_back(i);\n        }\n    }\n    return visible;\n}\n\n// Reconstruct path from parents\nstring reconstruct_path(int start_node, int end_node, const vector<int>& parent) {\n    if (start_node == end_node) return \"\";\n    vector<int> path;\n    int curr = end_node;\n    while (curr != start_node) {\n        if (curr == -1) return \"\";\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    \n    string res = \"\";\n    int curr_r = start_node / N;\n    int curr_c = start_node % N;\n    \n    for (int node : path) {\n        int nr = node / N;\n        int nc = node % N;\n        if (nr < curr_r) res += 'U';\n        else if (nr > curr_r) res += 'D';\n        else if (nc < curr_c) res += 'L';\n        else if (nc > curr_c) res += 'R';\n        curr_r = nr;\n        curr_c = nc;\n    }\n    return res;\n}\n\n// Dijkstra from a point, returns distances and parents\npair<vector<long long>, vector<int>> dijkstra(int sr, int sc) {\n    int start_node = flatten(sr, sc);\n    vector<long long> d(N * N, -1);\n    vector<int> p(N * N, -1);\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n\n    d[start_node] = 0;\n    pq.push({0, start_node});\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        auto [dist_val, u] = pq.top();\n        pq.pop();\n\n        if (d[u] != -1 && dist_val > d[u]) continue;\n\n        Point pu = unflatten(u);\n        for (int k = 0; k < 4; ++k) {\n            int nr = pu.r + dr[k];\n            int nc = pu.c + dc[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int v = flatten(nr, nc);\n                long long new_dist = dist_val + get_cost(nr, nc);\n                if (d[v] == -1 || new_dist < d[v]) {\n                    d[v] = new_dist;\n                    p[v] = u;\n                    pq.push({new_dist, v});\n                }\n            }\n        }\n    }\n    return {d, p};\n}\n\n// Calculate tour cost\nlong long calc_tour_cost(const vector<int>& tour, const vector<vector<long long>>& dist_mat) {\n    long long cost = 0;\n    int K = (int)tour.size();\n    for (int i = 0; i < K; ++i) {\n        int u = tour[i];\n        int v = tour[(i + 1) % K];\n        if (dist_mat[u][v] == -1) return 1e18;\n        cost += dist_mat[u][v];\n    }\n    return cost;\n}\n\n// 2-opt optimization\nvoid two_opt(vector<int>& tour, const vector<vector<long long>>& dist_mat) {\n    int K = (int)tour.size();\n    if (K < 3) return;\n    \n    bool improved = true;\n    int iter = 0;\n    while (improved && iter < 1000) {\n        improved = false;\n        iter++;\n        for (int i = 0; i < K - 1; ++i) {\n            for (int j = i + 1; j < K; ++j) {\n                if (i + 1 >= j) continue;\n                \n                int u = tour[i];\n                int v = tour[i+1];\n                int x = tour[j];\n                int y = tour[(j+1)%K];\n                \n                if (dist_mat[u][x] == -1 || dist_mat[v][y] == -1) continue;\n                if (dist_mat[u][v] == -1 || dist_mat[x][y] == -1) continue;\n\n                long long old_cost = dist_mat[u][v] + dist_mat[x][y];\n                long long new_cost = dist_mat[u][x] + dist_mat[v][y];\n                \n                if (new_cost < old_cost) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\n// Check coverage of a set of checkpoints\nint countCovered(const vector<Point>& checkpoints, const vector<vector<int>>& visibility, int total_roads) {\n    set<int> covered;\n    for (auto& cp : checkpoints) {\n        // Find index of this checkpoint\n        // (simplified - we'll track indices instead)\n    }\n    return (int)covered.size();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Get all road squares\n    vector<Point> all_roads = getAllRoads();\n    int total_roads = (int)all_roads.size();\n    \n    Point start_p = {si, sj};\n    \n    // Precompute visibility for all road squares\n    vector<vector<int>> visibility(all_roads.size());\n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        visibility[i] = getVisibleFrom(all_roads[i].r, all_roads[i].c, all_roads);\n    }\n    \n    // Create road index map\n    map<Point, int> road_index;\n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        road_index[all_roads[i]] = i;\n    }\n\n    // Greedy checkpoint selection to cover all roads\n    vector<int> selected_indices;\n    vector<bool> covered(total_roads, false);\n    int covered_count = 0;\n    \n    // Start with the starting point\n    int start_road_idx = road_index[start_p];\n    selected_indices.push_back(start_road_idx);\n    for (int idx : visibility[start_road_idx]) {\n        if (!covered[idx]) {\n            covered[idx] = true;\n            covered_count++;\n        }\n    }\n\n    // Greedily add points until all roads are covered\n    while (covered_count < total_roads) {\n        int best_point = -1;\n        double best_score = -1;\n        \n        // Try all road squares as potential checkpoints\n        for (int i = 0; i < (int)all_roads.size(); ++i) {\n            // Check if already selected\n            bool already_selected = false;\n            for (int idx : selected_indices) {\n                if (idx == i) {\n                    already_selected = true;\n                    break;\n                }\n            }\n            if (already_selected) continue;\n            \n            // Count new coverage\n            int new_covered = 0;\n            for (int idx : visibility[i]) {\n                if (!covered[idx]) {\n                    new_covered++;\n                }\n            }\n            \n            if (new_covered > 0) {\n                double score = (double)new_covered;\n                if (score > best_score) {\n                    best_score = score;\n                    best_point = i;\n                }\n            }\n        }\n        \n        if (best_point == -1) {\n            // No more points can cover remaining roads\n            break;\n        }\n        \n        selected_indices.push_back(best_point);\n        for (int idx : visibility[best_point]) {\n            if (!covered[idx]) {\n                covered[idx] = true;\n                covered_count++;\n            }\n        }\n    }\n\n    // Convert to points\n    vector<Point> selected_points;\n    for (int idx : selected_indices) {\n        selected_points.push_back(all_roads[idx]);\n    }\n\n    int K = (int)selected_points.size();\n    int start_idx = 0; // Start point is always first\n    \n    // All-Pairs Shortest Paths\n    vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n    vector<vector<int>> all_parents(K);\n\n    for (int i = 0; i < K; ++i) {\n        auto [d, p] = dijkstra(selected_points[i].r, selected_points[i].c);\n        all_parents[i] = p;\n        for (int j = 0; j < K; ++j) {\n            int t_node = flatten(selected_points[j].r, selected_points[j].c);\n            dist_mat[i][j] = d[t_node];\n        }\n    }\n\n    // TSP with multiple restarts\n    vector<int> best_tour;\n    long long best_cost = 1e18;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (int restart = 0; restart < 20; ++restart) {\n        vector<int> tour;\n        vector<bool> visited(K, false);\n        int curr = start_idx;\n        tour.push_back(curr);\n        visited[curr] = true;\n        \n        // Nearest Neighbor with randomization\n        for (int i = 0; i < K - 1; ++i) {\n            vector<pair<long long, int>> candidates;\n            for (int j = 0; j < K; ++j) {\n                if (!visited[j] && dist_mat[curr][j] != -1) {\n                    candidates.push_back({dist_mat[curr][j], j});\n                }\n            }\n            if (candidates.empty()) break;\n            \n            sort(candidates.begin(), candidates.end());\n            int pick_idx = 0;\n            if (restart > 0 && (int)candidates.size() > 1) {\n                pick_idx = (int)(rng() % min((size_t)candidates.size(), (size_t)5));\n            }\n            int next = candidates[pick_idx].second;\n            \n            tour.push_back(next);\n            visited[next] = true;\n            curr = next;\n        }\n        \n        // Optimize tour\n        two_opt(tour, dist_mat);\n        \n        long long cost = calc_tour_cost(tour, dist_mat);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_tour = tour;\n        }\n    }\n\n    // Try to prune checkpoints\n    // Attempt to remove each non-start checkpoint and check if coverage is maintained\n    vector<bool> in_tour(K, false);\n    for (int idx : best_tour) {\n        in_tour[idx] = true;\n    }\n    \n    vector<int> pruned_tour = best_tour;\n    bool pruned = true;\n    while (pruned && (int)pruned_tour.size() > 2) {\n        pruned = false;\n        for (size_t i = 0; i < pruned_tour.size(); ++i) {\n            if (pruned_tour[i] == start_idx) continue; // Keep start point\n            \n            // Try removing this checkpoint\n            vector<int> test_tour;\n            for (size_t j = 0; j < pruned_tour.size(); ++j) {\n                if (j != i) test_tour.push_back(pruned_tour[j]);\n            }\n            \n            // Check if tour is valid\n            long long test_cost = calc_tour_cost(test_tour, dist_mat);\n            if (test_cost < best_cost) {\n                // Check coverage\n                vector<bool> test_covered(total_roads, false);\n                int test_count = 0;\n                for (int idx : test_tour) {\n                    for (int vis : visibility[idx]) {\n                        if (!test_covered[vis]) {\n                            test_covered[vis] = true;\n                            test_count++;\n                        }\n                    }\n                }\n                \n                if (test_count == total_roads) {\n                    pruned_tour = test_tour;\n                    best_cost = test_cost;\n                    pruned = true;\n                    // Rebuild in_tour\n                    fill(in_tour.begin(), in_tour.end(), false);\n                    for (int idx : pruned_tour) {\n                        in_tour[idx] = true;\n                    }\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Final 2-opt on pruned tour\n    two_opt(pruned_tour, dist_mat);\n\n    // Reconstruct Full Path\n    string final_path = \"\";\n    for (size_t i = 0; i < pruned_tour.size(); ++i) {\n        int u = pruned_tour[i];\n        int v = pruned_tour[(i + 1) % pruned_tour.size()];\n        string segment = reconstruct_path(flatten(selected_points[u].r, selected_points[u].c), \n                                          flatten(selected_points[v].r, selected_points[v].c), \n                                          all_parents[u]);\n        final_path += segment;\n    }\n\n    cout << final_path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <iomanip>\n#include <queue>\n\nusing namespace std;\n\nconst int MAX_N = 1005;\nconst int MAX_DAY = 2000;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int in_degree = 0;\n    vector<int> dependents;\n    vector<int> dependencies;\n    int priority = 0;\n    int status = -1;\n    int assigned_member = -1;\n    int start_day = 0;\n    int difficulty = 0;\n    int critical_path_length = 0;\n    int depth = 0;\n};\n\nstruct Member {\n    int id;\n    vector<int> s;\n    vector<int> s_sum;\n    vector<int> s_count;\n    int busy_until = 0;\n    int current_task = -1;\n    int start_day = 0;\n    int tasks_completed = 0;\n    bool has_active_task = false;\n    double total_work = 0;\n    int total_error = 0;\n    int total_predicted = 0;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, K, R;\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    vector<Task> tasks(N + 1);\n    int max_task_difficulty = 0;\n    int total_difficulty = 0;\n    vector<int> max_skill_requirement(K, 0);\n    vector<int> avg_skill_requirement(K, 0);\n    \n    for (int i = 1; i <= N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        int task_sum = 0;\n        for (int j = 0; j < K; ++j) {\n            cin >> tasks[i].d[j];\n            task_sum += tasks[i].d[j];\n            max_skill_requirement[j] = max(max_skill_requirement[j], tasks[i].d[j]);\n            avg_skill_requirement[j] += tasks[i].d[j];\n        }\n        tasks[i].difficulty = task_sum;\n        total_difficulty += task_sum;\n        max_task_difficulty = max(max_task_difficulty, task_sum);\n    }\n    \n    for (int j = 0; j < K; ++j) {\n        avg_skill_requirement[j] /= N;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        tasks[v].in_degree++;\n        tasks[u].dependents.push_back(v);\n        tasks[v].dependencies.push_back(u);\n    }\n\n    // Compute depth (longest path from root)\n    queue<int> q;\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            tasks[i].depth = 0;\n            q.push(i);\n        }\n    }\n    \n    vector<int> topo_order;\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        topo_order.push_back(u);\n        for (int v : tasks[u].dependents) {\n            tasks[v].depth = max(tasks[v].depth, tasks[u].depth + 1);\n            tasks[v].in_degree--;\n            if (tasks[v].in_degree == 0) {\n                q.push(v);\n            }\n        }\n    }\n\n    // Compute critical path length (longest path to end)\n    vector<int> longest_path(N + 1, 0);\n    for (int i = N; i >= 1; --i) {\n        int u = topo_order[i-1];\n        longest_path[u] = tasks[u].difficulty;\n        for (int v : tasks[u].dependents) {\n            longest_path[u] = max(longest_path[u], tasks[u].difficulty + longest_path[v]);\n        }\n        tasks[u].critical_path_length = longest_path[u];\n    }\n\n    // Compute priority (number of reachable tasks)\n    vector<bitset<MAX_N>> reach(N + 1);\n    for (int i = N; i >= 1; --i) {\n        int u = topo_order[i-1];\n        reach[u][u] = 1;\n        for (int v : tasks[u].dependents) {\n            reach[u] |= reach[v];\n        }\n        tasks[u].priority = (int)reach[u].count();\n    }\n\n    // Reset in_degree for actual scheduling\n    for (int i = 1; i <= N; ++i) {\n        tasks[i].in_degree = (int)tasks[i].dependencies.size();\n    }\n\n    vector<Member> members(M + 1);\n    for (int j = 1; j <= M; ++j) {\n        members[j].id = j;\n        members[j].s.assign(K, 0);\n        members[j].s_sum.assign(K, 0);\n        members[j].s_count.assign(K, 0);\n        members[j].busy_until = 0;\n        members[j].has_active_task = false;\n    }\n\n    vector<int> ready_tasks;\n    ready_tasks.reserve(N);\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            ready_tasks.push_back(i);\n        }\n    }\n\n    int current_day = 0;\n    const double ALPHA_BASE = 0.8;\n    int completed_count = 0;\n    int active_member_count = 0;\n    int remaining_tasks = N;\n    \n    // Track prediction accuracy for buffer adjustment\n    vector<double> prediction_errors;\n    prediction_errors.reserve(200);\n    double avg_error_ratio = 1.0;\n\n    while (true) {\n        current_day++;\n        \n        // Very conservative stop day - we want to finish early anyway\n        int dynamic_stop_day = MAX_DAY - 150;\n        bool can_assign = (current_day <= dynamic_stop_day);\n        \n        vector<pair<int, int>> assignments;\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int j = 1; j <= M; ++j) {\n            if (!members[j].has_active_task) {\n                free_members.push_back(j);\n            }\n        }\n\n        if (can_assign && !free_members.empty() && !ready_tasks.empty()) {\n            vector<int> candidates;\n            candidates.reserve(ready_tasks.size());\n            for (int t_idx : ready_tasks) {\n                if (tasks[t_idx].status == -1) {\n                    candidates.push_back(t_idx);\n                }\n            }\n            \n            // Sort by critical path (most important first), then by depth\n            sort(candidates.begin(), candidates.end(), [&](int a, int b) {\n                if (tasks[a].critical_path_length != tasks[b].critical_path_length)\n                    return tasks[a].critical_path_length > tasks[b].critical_path_length;\n                if (tasks[a].priority != tasks[b].priority)\n                    return tasks[a].priority > tasks[b].priority;\n                return tasks[a].depth < tasks[b].depth; // Prefer earlier depth first\n            });\n\n            for (int t_idx : candidates) {\n                if (tasks[t_idx].status != -1) continue;\n                if (free_members.empty()) break;\n\n                int best_m = -1;\n                int min_t = 2000000000;\n                double best_score = 1e18;\n                \n                for (int m_idx : free_members) {\n                    int w = 0;\n                    double skill_coverage = 0;\n                    \n                    for (int k = 0; k < K; ++k) {\n                        int deficit = max(0, tasks[t_idx].d[k] - members[m_idx].s[k]);\n                        w += deficit;\n                        if (tasks[t_idx].d[k] > 0) {\n                            skill_coverage += min(1.0, (double)members[m_idx].s[k] / tasks[t_idx].d[k]);\n                        }\n                    }\n                    skill_coverage /= K;\n                    \n                    // Very aggressive buffer reduction based on experience\n                    int buffer = 5;\n                    if (members[m_idx].tasks_completed >= 3) buffer = 3;\n                    if (members[m_idx].tasks_completed >= 8) buffer = 2;\n                    if (members[m_idx].tasks_completed >= 15) buffer = 1;\n                    if (members[m_idx].tasks_completed >= 25) buffer = 0;\n                    \n                    // Adjust buffer based on prediction accuracy\n                    if (!prediction_errors.empty()) {\n                        buffer = max(0, buffer + (int)(avg_error_ratio * 2));\n                    }\n                    \n                    int t_est = max(1, w + buffer);\n                    \n                    // Ensure task completes before limit\n                    if (current_day + t_est - 1 >= MAX_DAY - 5) continue;\n                    \n                    // Score: minimize time, balance load, maximize skill match\n                    double load_ratio = (members[m_idx].tasks_completed == 0) ? 0 : \n                                       members[m_idx].total_work / members[m_idx].tasks_completed;\n                    double score = t_est * 1000 + load_ratio * 10 - skill_coverage * 100;\n                    \n                    if (t_est < min_t || (t_est == min_t && score < best_score)) {\n                        min_t = t_est;\n                        best_m = m_idx;\n                        best_score = score;\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_idx});\n                    tasks[t_idx].status = 0;\n                    tasks[t_idx].assigned_member = best_m;\n                    tasks[t_idx].start_day = current_day;\n                    \n                    members[best_m].busy_until = current_day + min_t - 1;\n                    members[best_m].current_task = t_idx;\n                    members[best_m].start_day = current_day;\n                    members[best_m].has_active_task = true;\n                    members[best_m].total_work += min_t;\n                    active_member_count++;\n                    \n                    for (auto it = free_members.begin(); it != free_members.end(); ++it) {\n                        if (*it == best_m) {\n                            free_members.erase(it);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << \"\\n\";\n        \n        // Output skill predictions\n        if (current_day % 200 == 1) {\n            for (int j = 1; j <= M; ++j) {\n                if (members[j].tasks_completed > 0) {\n                    cout << \"#s \" << j;\n                    for (int k = 0; k < K; ++k) {\n                        cout << \" \" << members[j].s[k];\n                    }\n                    cout << \"\\n\";\n                }\n            }\n        }\n        cout.flush();\n\n        // Read completion info\n        int n_fin;\n        cin >> n_fin;\n        if (n_fin == -1) {\n            break;\n        }\n\n        vector<int> finished_members(n_fin);\n        for (int i = 0; i < n_fin; ++i) {\n            cin >> finished_members[i];\n        }\n\n        for (int m_idx : finished_members) {\n            int t_idx = members[m_idx].current_task;\n            if (t_idx == -1) continue;\n\n            int duration = current_day - members[m_idx].start_day + 1;\n            int t_obs = duration;\n            \n            // Calculate predicted duration for error tracking\n            int w_pred = 0;\n            vector<int> active_dims;\n            active_dims.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                    w_pred += tasks[t_idx].d[k] - members[m_idx].s[k];\n                    active_dims.push_back(k);\n                }\n            }\n            int t_pred = (w_pred == 0) ? 1 : w_pred;\n            members[m_idx].total_predicted += t_pred;\n            \n            // Track prediction error\n            if (t_pred > 0) {\n                double error_ratio = (double)t_obs / t_pred;\n                prediction_errors.push_back(error_ratio);\n                if (prediction_errors.size() > 50) {\n                    prediction_errors.erase(prediction_errors.begin());\n                }\n                double sum_errors = 0;\n                for (double e : prediction_errors) sum_errors += e;\n                avg_error_ratio = sum_errors / prediction_errors.size();\n            }\n            \n            // Skill Update - More aggressive early learning\n            double error = (double)t_obs - t_pred;\n            members[m_idx].total_error += abs((int)error);\n            \n            if (!active_dims.empty()) {\n                // Much more aggressive learning early on\n                double alpha = ALPHA_BASE;\n                int exp = members[m_idx].tasks_completed;\n                \n                if (exp < 3) alpha = 1.0;       // Very aggressive first 3 tasks\n                else if (exp < 8) alpha = 0.7;  // Aggressive next 5\n                else if (exp < 15) alpha = 0.5; // Moderate\n                else if (exp < 30) alpha = 0.3; // Conservative\n                else alpha = 0.2;                // Very conservative\n                \n                alpha = max(0.15, min(1.0, alpha));\n                \n                double update_per_dim = alpha * error / active_dims.size();\n                \n                for (int k : active_dims) {\n                    double new_s = members[m_idx].s[k] - update_per_dim;\n                    new_s = max(0.0, new_s);\n                    // Cap at max observed requirement + margin\n                    new_s = min((double)max_skill_requirement[k] + 20, new_s);\n                    \n                    // Incremental average for skill estimation\n                    members[m_idx].s_count[k]++;\n                    members[m_idx].s_sum[k] += (int)round(new_s);\n                    members[m_idx].s[k] = (int)round(new_s);\n                }\n            }\n\n            tasks[t_idx].status = 1;\n            completed_count++;\n            remaining_tasks--;\n            members[m_idx].current_task = -1;\n            members[m_idx].has_active_task = false;\n            members[m_idx].tasks_completed++;\n            active_member_count--;\n\n            // Update Dependencies\n            for (int v : tasks[t_idx].dependents) {\n                tasks[v].in_degree--;\n                if (tasks[v].in_degree == 0) {\n                    ready_tasks.push_back(v);\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n};\n\ninline int manhattan(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nconst Point CENTER = {400, 400};\nvector<Order> orders(1000);\nPoint pickups[1000], deliveries[1000];\n\n// Path: sequence of 100 nodes (50 pickups + 50 deliveries)\n// Each node: (order_id, type) where type 0=pickup, 1=delivery\nstruct Node {\n    int order_id;\n    int type; // 0=pickup, 1=delivery\n};\n\nvector<Node> path;\nbool selected[1000];\n\nint calc_cost(const vector<Node>& p) {\n    int cost = 0;\n    Point prev = CENTER;\n    for (const auto& node : p) {\n        Point curr = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cost += manhattan(prev, curr);\n        prev = curr;\n    }\n    cost += manhattan(prev, CENTER);\n    return cost;\n}\n\n// Validate path: each selected order has pickup before delivery\nbool validate_path(const vector<Node>& p, const bool* sel) {\n    int pickup_pos[1000];\n    fill(pickup_pos, pickup_pos + 1000, -1);\n    \n    for (int i = 0; i < 100; ++i) {\n        if (p[i].type == 0) {\n            pickup_pos[p[i].order_id] = i;\n        } else {\n            if (pickup_pos[p[i].order_id] == -1) return false;\n            if (pickup_pos[p[i].order_id] >= i) return false;\n        }\n    }\n    \n    // Check all selected orders are in path\n    for (int i = 0; i < 1000; ++i) {\n        if (sel[i]) {\n            if (pickup_pos[i] == -1) return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read input\n    for (int i = 0; i < 1000; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        pickups[i] = {orders[i].ax, orders[i].ay};\n        deliveries[i] = {orders[i].cx, orders[i].cy};\n    }\n    \n    mt19937 rng(1337);\n    \n    // Initial selection: pick 50 orders with smallest round-trip cost\n    vector<pair<int, int>> scores;\n    scores.reserve(1000);\n    for (int i = 0; i < 1000; ++i) {\n        int score = manhattan(CENTER, pickups[i]) + \n                    manhattan(pickups[i], deliveries[i]) + \n                    manhattan(deliveries[i], CENTER);\n        scores.push_back({score, i});\n    }\n    sort(scores.begin(), scores.end());\n    \n    fill(selected, selected + 1000, false);\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected[scores[i].second] = true;\n        selected_orders.push_back(scores[i].second);\n    }\n    \n    // Initial path: sort by angle from center, pickup then delivery for each\n    vector<pair<double, int>> angled;\n    angled.reserve(50);\n    for (int oid : selected_orders) {\n        int mx = (pickups[oid].x + deliveries[oid].x) / 2;\n        int my = (pickups[oid].y + deliveries[oid].y) / 2;\n        double angle = atan2(my - 400, mx - 400);\n        angled.push_back({angle, oid});\n    }\n    sort(angled.begin(), angled.end());\n    \n    path.clear();\n    path.reserve(100);\n    for (const auto& p : angled) {\n        path.push_back({p.second, 0}); // pickup\n        path.push_back({p.second, 1}); // delivery\n    }\n    \n    int best_cost = calc_cost(path);\n    vector<Node> best_path = path;\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.90;\n    \n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    uniform_int_distribution<int> dist_idx(0, 98);\n    \n    double temp = 5000.0;\n    int iter = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        temp *= 0.99995;\n        if (temp < 0.5) temp = 0.5;\n        \n        // Operation: swap two nodes while maintaining constraints\n        int i = dist_idx(rng);\n        int j = dist_idx(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        \n        // Ensure j > i\n        if (j <= i) { j = i + 1; if (j >= 100) { i = 98; j = 99; } }\n        \n        Node ni = path[i];\n        Node nj = path[j];\n        \n        // Find positions of complementary nodes\n        int ni_comp = -1, nj_comp = -1;\n        for (int k = 0; k < 100; ++k) {\n            if (k == i || k == j) continue;\n            if (path[k].order_id == ni.order_id) ni_comp = k;\n            if (path[k].order_id == nj.order_id) nj_comp = k;\n        }\n        \n        // Check if swap is valid\n        bool valid = true;\n        \n        // After swap: ni goes to position j, nj goes to position i\n        // For ni: if it's pickup (0), need comp (delivery) to be after j\n        //         if it's delivery (1), need comp (pickup) to be before j\n        if (ni.type == 0) { // pickup moving to j\n            if (ni_comp != -1 && ni_comp < j) valid = false;\n        } else { // delivery moving to j\n            if (ni_comp != -1 && ni_comp > j) valid = false;\n        }\n        \n        if (valid && nj.type == 0) { // pickup moving to i\n            if (nj_comp != -1 && nj_comp < i) valid = false;\n        } else if (valid) { // delivery moving to i\n            if (nj_comp != -1 && nj_comp > i) valid = false;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate delta cost (only affected edges)\n        auto get_point = [&](int idx, const vector<Node>& p) -> Point {\n            if (idx < 0 || idx >= 100) return CENTER;\n            if (p[idx].type == 0) return pickups[p[idx].order_id];\n            return deliveries[p[idx].order_id];\n        };\n        \n        int delta = 0;\n        \n        // Edges affected: (i-1,i), (i,i+1), (j-1,j), (j,j+1)\n        // But need to handle adjacency carefully\n        \n        vector<int> affected;\n        if (i > 0) affected.push_back(i - 1);\n        affected.push_back(i);\n        if (i < 99) affected.push_back(i + 1);\n        if (j > 0 && j - 1 != i) affected.push_back(j - 1);\n        if (j < 99 && j != i + 1) affected.push_back(j);\n        if (j < 99) affected.push_back(j + 1);\n        \n        // Remove duplicates and sort\n        sort(affected.begin(), affected.end());\n        affected.erase(unique(affected.begin(), affected.end()), affected.end());\n        \n        // Calculate old cost for affected edges\n        int old_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, path);\n                Point p2 = get_point(k + 1, path);\n                old_cost += manhattan(p1, p2);\n            }\n        }\n        \n        // Create new path (just for these positions)\n        vector<Node> new_path = path;\n        swap(new_path[i], new_path[j]);\n        \n        // Calculate new cost for affected edges\n        int new_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, new_path);\n                Point p2 = get_point(k + 1, new_path);\n                new_cost += manhattan(p1, p2);\n            }\n        }\n        \n        delta = new_cost - old_cost;\n        \n        if (delta < 0 || dist_01(rng) < exp(-delta / temp)) {\n            swap(path[i], path[j]);\n            int cur_cost = calc_cost(path);\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_path = path;\n            }\n        }\n        \n        iter++;\n        if (iter % 10000 == 0) {\n            // Occasionally try a different initialization\n            if (dist_01(rng) < 0.1) {\n                // Shuffle and rebuild\n                shuffle(selected_orders.begin(), selected_orders.end(), rng);\n                path.clear();\n                for (int oid : selected_orders) {\n                    path.push_back({oid, 0});\n                    path.push_back({oid, 1});\n                }\n                int c = calc_cost(path);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_path = path;\n                }\n            }\n        }\n    }\n    \n    // Final validation\n    if (!validate_path(best_path, selected)) {\n        // Rebuild path from selected orders\n        path.clear();\n        for (int i = 0; i < 1000; ++i) {\n            if (selected[i]) {\n                path.push_back({i, 0});\n                path.push_back({i, 1});\n            }\n        }\n        best_path = path;\n        best_cost = calc_cost(best_path);\n    }\n    \n    // Output\n    cout << 50;\n    for (int i = 0; i < 1000; ++i) {\n        if (selected[i]) cout << \" \" << (i + 1);\n    }\n    cout << \"\\n\";\n    \n    cout << 102;\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    for (const auto& node : best_path) {\n        Point p = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Disjoint Set Union with path compression and union by rank\nstruct DSU {\n    vector<int> parent, rank_, size_;\n    int components;\n    \n    DSU(int n) : parent(n), rank_(n, 0), size_(n, 1), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    \n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        size_[x] += size_[y];\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        components--;\n        return true;\n    }\n    \n    int getSize(int x) {\n        return size_[find(x)];\n    }\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    // Read vertex coordinates\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    // Read edge endpoints and precompute expected distances\n    vector<pair<int, int>> edges(M);\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n        int u = edges[i].first, v = edges[i].second;\n        double dist = hypot(coords[u].first - coords[v].first, \n                           coords[u].second - coords[v].second);\n        d[i] = (int)round(dist);\n    }\n    \n    DSU dsu(N);\n    \n    // Process each edge online\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first, v = edges[i].second;\n        int remaining = M - 1 - i;  // Edges after this one (including current = remaining + 1)\n        int needed = dsu.components - 1;  // Minimum edges needed for connectivity\n        \n        bool connects = (dsu.find(u) != dsu.find(v));\n        bool accept = false;\n        \n        if (connects) {\n            // Edge quality ratio (actual length / minimum possible length)\n            double ratio = (double)l / max(1, d[i]);\n            \n            // Connectivity urgency: how critical is it to accept connecting edges?\n            // Use remaining + 1 to include current edge in available count\n            int available = remaining + 1;\n            double urgency = (double)needed / max(1, available);\n            \n            // Progress through the edge stream (0.0 to 1.0)\n            double progress = (double)i / (M - 1);\n            \n            // Base threshold: expected value is 2.0, max is 3.0\n            // We want to accept edges with ratio <= threshold\n            double threshold = 2.3;\n            \n            // Phase 1: Early phase (first 30%) - be selective but not too aggressive\n            if (progress < 0.3) {\n                threshold = 2.0 + urgency * 0.5;\n            }\n            // Phase 2: Middle phase (30-60%) - moderate selectivity\n            else if (progress < 0.6) {\n                threshold = 2.2 + urgency * 0.6;\n            }\n            // Phase 3: Late phase (60-80%) - prioritize connectivity\n            else if (progress < 0.8) {\n                threshold = 2.5 + urgency * 0.5;\n            }\n            // Phase 4: Critical phase (80%+) - very aggressive on connectivity\n            else {\n                threshold = 2.8 + urgency * 0.2;\n            }\n            \n            // Safety mechanism 1: Large buffer when running low on edges\n            // With M=1995 and N=400, we need 399 edges minimum\n            // But many edges will be redundant, so we need significant buffer\n            int safety_margin = 80;\n            if (available <= needed + safety_margin) {\n                threshold = 3.0;  // Accept any connecting edge\n            }\n            \n            // Safety mechanism 2: Critical zone - must accept all connecting edges\n            if (available <= needed + 30) {\n                accept = true;\n            }\n            // Safety mechanism 3: Very urgent - almost always accept\n            else if (urgency > 0.6) {\n                threshold = 3.0;\n            }\n            // Safety mechanism 4: Moderate urgency\n            else if (urgency > 0.4) {\n                threshold = max(threshold, 2.7);\n            }\n            \n            // Apply threshold if not already forced to accept\n            if (!accept && ratio <= threshold) {\n                accept = true;\n            }\n            \n            // Component size bonus: prefer edges connecting larger components\n            // This helps reduce components faster\n            if (!accept && connects) {\n                int combined_size = dsu.getSize(u) + dsu.getSize(v);\n                if (combined_size > N / 2 && ratio <= threshold + 0.3) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept && connects) {\n            dsu.unite(u, v);\n            cout << 1 << \"\\n\";\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        cout.flush();  // Ensure output is sent immediately\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nclass Solver {\nprivate:\n    int N, M;\n    vector<Position> petPos;\n    vector<int> petType;\n    vector<Position> humanPos;\n    vector<vector<bool>> impassable;\n    vector<vector<bool>> humanTarget;\n    \n    bool isValid(int x, int y) const {\n        return x >= 1 && x <= GRID_SIZE && y >= 1 && y <= GRID_SIZE;\n    }\n    \n    bool isPassable(int x, int y) const {\n        if (!isValid(x, y)) return false;\n        return !impassable[x-1][y-1];\n    }\n    \n    bool hasPetAdjacent(int x, int y) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (const auto& pet : petPos) {\n                    if (pet.x == nx && pet.y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    bool hasHumanAdjacent(int x, int y, int excludeIdx = -1) const {\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny)) {\n                for (int i = 0; i < M; i++) {\n                    if (i == excludeIdx) continue;\n                    if (humanPos[i].x == nx && humanPos[i].y == ny) {\n                        return true;\n                    }\n                }\n            }\n        }\n        return false;\n    }\n    \n    vector<vector<bool>> computeReachable(const Position& start) const {\n        vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        queue<Position> q;\n        \n        if (isPassable(start.x, start.y)) {\n            visited[start.x-1][start.y-1] = true;\n            q.push(start);\n        }\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        \n        while (!q.empty()) {\n            Position cur = q.front();\n            q.pop();\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = cur.x + dx[d], ny = cur.y + dy[d];\n                if (isPassable(nx, ny) && !visited[nx-1][ny-1]) {\n                    visited[nx-1][ny-1] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        \n        return visited;\n    }\n    \n    int countPetsInRegion(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (const auto& pet : petPos) {\n            if (region[pet.x-1][pet.y-1]) {\n                count++;\n            }\n        }\n        return count;\n    }\n    \n    int countReachable(const vector<vector<bool>>& region) const {\n        int count = 0;\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (region[i][j]) count++;\n            }\n        }\n        return count;\n    }\n    \n    // Calculate minimum distance from position to any pet\n    int minPetDistance(int x, int y) const {\n        int minDist = 1000;\n        for (const auto& pet : petPos) {\n            int dist = abs(pet.x - x) + abs(pet.y - y);\n            minDist = min(minDist, dist);\n        }\n        return minDist;\n    }\n    \n    // Check if blocking this square would help create a partition\n    double evaluateBlockScore(int x, int y, int humanIdx) const {\n        double score = 0;\n        \n        // Base score for blocking\n        score += 100;\n        \n        // Bonus for being far from pets (safer)\n        int petDist = minPetDistance(x, y);\n        score += petDist * 5;\n        \n        // Bonus for continuing existing walls\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int wallCount = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (isValid(nx, ny) && impassable[nx-1][ny-1]) {\n                wallCount++;\n            }\n        }\n        score += wallCount * 20;\n        \n        // Prefer edges and corners for better partitioning\n        if (x == 1 || x == GRID_SIZE || y == 1 || y == GRID_SIZE) {\n            score += 15;\n        }\n        if ((x == 1 || x == GRID_SIZE) && (y == 1 || y == GRID_SIZE)) {\n            score += 10;\n        }\n        \n        // Penalize if too close to this human (want to expand)\n        int humanDist = abs(x - humanPos[humanIdx].x) + abs(y - humanPos[humanIdx].y);\n        if (humanDist < 3) {\n            score -= (3 - humanDist) * 10;\n        }\n        \n        return score;\n    }\n    \n    // Evaluate move score\n    double evaluateMoveScore(int newX, int newY, int humanIdx) const {\n        double score = 0;\n        \n        // Count potential blocking opportunities from new position\n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        int blockOptions = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = newX + dx[d], ny = newY + dy[d];\n            if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !hasPetAdjacent(nx, ny)) {\n                blockOptions++;\n            }\n        }\n        score += blockOptions * 30;\n        \n        // Distance from pets\n        int petDist = minPetDistance(newX, newY);\n        score += petDist * 3;\n        \n        // Spread humans out\n        for (int i = 0; i < M; i++) {\n            if (i == humanIdx) continue;\n            int dist = abs(newX - humanPos[i].x) + abs(newY - humanPos[i].y);\n            if (dist < 5) {\n                score -= (5 - dist) * 5;\n            }\n        }\n        \n        return score;\n    }\n    \npublic:\n    void readInput() {\n        cin >> N;\n        petPos.resize(N);\n        petType.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petPos[i].x >> petPos[i].y >> petType[i];\n        }\n        \n        cin >> M;\n        humanPos.resize(M);\n        for (int i = 0; i < M; i++) {\n            cin >> humanPos[i].x >> humanPos[i].y;\n        }\n        \n        impassable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        humanTarget.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    }\n    \n    void readPetMoves() {\n        for (int i = 0; i < N; i++) {\n            string move;\n            cin >> move;\n            if (move != \".\") {\n                int x = petPos[i].x, y = petPos[i].y;\n                for (char c : move) {\n                    int nx = x, ny = y;\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    \n                    if (isValid(nx, ny) && isPassable(nx, ny)) {\n                        x = nx;\n                        y = ny;\n                    }\n                }\n                petPos[i] = {x, y};\n            }\n        }\n    }\n    \n    string decideActions(int turn) {\n        string actions(M, '.');\n        \n        // Track which squares will be blocked this turn (to avoid conflicts)\n        vector<vector<bool>> willBlock(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n        \n        int dx[] = {-1, 1, 0, 0};\n        int dy[] = {0, 0, -1, 1};\n        char blockChars[] = {'u', 'd', 'l', 'r'};\n        char moveChars[] = {'U', 'D', 'L', 'R'};\n        \n        // First pass: identify best blocking opportunities\n        vector<pair<double, int>> humanScores(M);\n        for (int i = 0; i < M; i++) {\n            int x = humanPos[i].x, y = humanPos[i].y;\n            double bestScore = -1e18;\n            int bestD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1]) {\n                    if (!hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                        double score = evaluateBlockScore(nx, ny, i);\n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestD = d;\n                        }\n                    }\n                }\n            }\n            \n            humanScores[i] = {bestScore, bestD};\n        }\n        \n        // Second pass: execute actions (prioritize high-score humans)\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return humanScores[a].first > humanScores[b].first;\n        });\n        \n        for (int idx : order) {\n            int i = idx;\n            int x = humanPos[i].x, y = humanPos[i].y;\n            int bestD = humanScores[i].second;\n            \n            if (bestD >= 0) {\n                int nx = x + dx[bestD], ny = y + dy[bestD];\n                // Double check it's still available\n                if (isValid(nx, ny) && !impassable[nx-1][ny-1] && !willBlock[nx-1][ny-1] &&\n                    !hasPetAdjacent(nx, ny) && !hasHumanAdjacent(nx, ny, i)) {\n                    actions[i] = blockChars[bestD];\n                    impassable[nx-1][ny-1] = true;\n                    willBlock[nx-1][ny-1] = true;\n                    continue;\n                }\n            }\n            \n            // Try to move to better position\n            double bestMoveScore = -1e18;\n            int bestMoveD = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (isValid(nx, ny) && isPassable(nx, ny)) {\n                    // Check if this square won't be blocked by others\n                    bool willBeBlocked = false;\n                    for (int j = 0; j < M; j++) {\n                        if (j == i) continue;\n                        int jd = humanScores[j].second;\n                        if (jd >= 0) {\n                            int tx = humanPos[j].x + dx[jd], ty = humanPos[j].y + dy[jd];\n                            if (tx == nx && ty == ny) {\n                                willBeBlocked = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (!willBeBlocked) {\n                        double score = evaluateMoveScore(nx, ny, i);\n                        if (score > bestMoveScore) {\n                            bestMoveScore = score;\n                            bestMoveD = d;\n                        }\n                    }\n                }\n            }\n            \n            if (bestMoveD >= 0 && bestMoveScore > 0) {\n                actions[i] = moveChars[bestMoveD];\n                humanPos[i].x += dx[bestMoveD];\n                humanPos[i].y += dy[bestMoveD];\n            }\n        }\n        \n        return actions;\n    }\n    \n    void solve() {\n        readInput();\n        \n        for (int turn = 0; turn < MAX_TURNS; turn++) {\n            string actions = decideActions(turn);\n            cout << actions << endl;\n            \n            if (turn < MAX_TURNS - 1) {\n                readPetMoves();\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}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <functional>\n#include <queue>\n#include <set>\n\nusing namespace std;\n\nconst int GRID_SIZE = 20;\nconst int MAX_STEPS = 200;\n\nstruct Problem {\n    int si, sj, ti, tj;\n    double p;\n    vector<string> h;\n    vector<string> v;\n};\n\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dirChar[4] = {'U', 'D', 'L', 'R'};\nconst int oppositeDir[4] = {1, 0, 3, 2}; // U<->D, L<->R\n\ninline bool canMove(const Problem& prob, int i, int j, int dir) {\n    int ni = i + di[dir];\n    int nj = j + dj[dir];\n    \n    if (ni < 0 || ni >= GRID_SIZE || nj < 0 || nj >= GRID_SIZE) return false;\n    \n    if (dir == 0) {\n        if (prob.v[ni][j] == '1') return false;\n    } else if (dir == 1) {\n        if (prob.v[i][j] == '1') return false;\n    } else if (dir == 2) {\n        if (prob.h[i][nj] == '1') return false;\n    } else {\n        if (prob.h[i][j] == '1') return false;\n    }\n    return true;\n}\n\nbool pathReachesTarget(const Problem& prob, const string& path) {\n    int i = prob.si, j = prob.sj;\n    \n    for (char c : path) {\n        if (i == prob.ti && j == prob.tj) return true;\n        \n        int dir;\n        if (c == 'U') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        \n        if (canMove(prob, i, j, dir)) {\n            i += di[dir];\n            j += dj[dir];\n        }\n    }\n    \n    return (i == prob.ti && j == prob.tj);\n}\n\ndouble evaluatePathDP(const Problem& prob, const string& path) {\n    int L = path.size();\n    \n    vector<vector<double>> prob_grid(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    prob_grid[prob.si][prob.sj] = 1.0;\n    \n    double expectedScore = 0.0;\n    double arrivedProb = 0.0;\n    \n    for (int t = 0; t < L; t++) {\n        int dir;\n        if (path[t] == 'U') dir = 0;\n        else if (path[t] == 'D') dir = 1;\n        else if (path[t] == 'L') dir = 2;\n        else dir = 3;\n        \n        vector<vector<double>> next_prob(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n        \n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (prob_grid[i][j] < 1e-12) continue;\n                \n                if (i == prob.ti && j == prob.tj) {\n                    next_prob[i][j] += prob_grid[i][j];\n                    continue;\n                }\n                \n                next_prob[i][j] += prob.p * prob_grid[i][j];\n                \n                if (canMove(prob, i, j, dir)) {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    next_prob[ni][nj] += (1.0 - prob.p) * prob_grid[i][j];\n                } else {\n                    next_prob[i][j] += (1.0 - prob.p) * prob_grid[i][j];\n                }\n            }\n        }\n        \n        double newProb = next_prob[prob.ti][prob.tj] - arrivedProb;\n        if (newProb > 0) {\n            expectedScore += newProb * (401.0 - (t + 1));\n        }\n        arrivedProb = next_prob[prob.ti][prob.tj];\n        \n        prob_grid = next_prob;\n    }\n    \n    return expectedScore;\n}\n\nstring bfsPath(const Problem& prob, const vector<int>& dirOrder = {0, 1, 2, 3}) {\n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n    vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    queue<pair<int, int>> q;\n    \n    q.push({prob.si, prob.sj});\n    visited[prob.si][prob.sj] = true;\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == prob.ti && cj == prob.tj) break;\n        \n        for (int dir : dirOrder) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {ci, cj};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (!visited[prob.ti][prob.tj]) return \"\";\n    \n    string path = \"\";\n    int ci = prob.ti, cj = prob.tj;\n    while (ci != prob.si || cj != prob.sj) {\n        int dir = parentDir[ci][cj];\n        path += dirChar[dir];\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    return path;\n}\n\nstring bfsPathWeighted(const Problem& prob) {\n    // BFS with distance-based priority (Dijkstra-like)\n    vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, 1e18));\n    vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n    vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    \n    using State = pair<double, pair<int, int>>;\n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[prob.si][prob.sj] = 0;\n    pq.push({0, {prob.si, prob.sj}});\n    \n    while (!pq.empty()) {\n        auto [d, pos] = pq.top();\n        auto [ci, cj] = pos;\n        pq.pop();\n        \n        if (d > dist[ci][cj]) continue;\n        if (ci == prob.ti && cj == prob.tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                double weight = 1.0 + 0.01 * (abs(ni - prob.ti) + abs(nj - prob.tj));\n                \n                if (dist[ci][cj] + weight < dist[ni][nj]) {\n                    dist[ni][nj] = dist[ci][cj] + weight;\n                    parent[ni][nj] = {ci, cj};\n                    parentDir[ni][nj] = dir;\n                    pq.push({dist[ni][nj], {ni, nj}});\n                }\n            }\n        }\n    }\n    \n    if (dist[prob.ti][prob.tj] > 1e17) return \"\";\n    \n    string path = \"\";\n    int ci = prob.ti, cj = prob.tj;\n    while (ci != prob.si || cj != prob.sj) {\n        int dir = parentDir[ci][cj];\n        path += dirChar[dir];\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    return path;\n}\n\nstring dpPath(const Problem& prob, int pathLen) {\n    vector<vector<double>> V_cur(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    vector<vector<double>> V_next(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    \n    for (int k = 1; k <= pathLen; k++) {\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (i == prob.ti && j == prob.tj) {\n                    V_next[i][j] = 401.0 - (pathLen - k);\n                    continue;\n                }\n                \n                double bestVal = 0.0;\n                for (int dir = 0; dir < 4; dir++) {\n                    double val = prob.p * V_cur[i][j];\n                    \n                    if (canMove(prob, i, j, dir)) {\n                        val += (1.0 - prob.p) * V_cur[i + di[dir]][j + dj[dir]];\n                    } else {\n                        val += (1.0 - prob.p) * V_cur[i][j];\n                    }\n                    \n                    if (val > bestVal) bestVal = val;\n                }\n                V_next[i][j] = bestVal;\n            }\n        }\n        swap(V_cur, V_next);\n    }\n    \n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    \n    for (int k = pathLen; k > 0 && (ci != prob.ti || cj != prob.tj); k--) {\n        int bestDir = 1;\n        double bestVal = -1e18;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            double val = prob.p * V_cur[ci][cj];\n            if (canMove(prob, ci, cj, dir)) {\n                val += (1.0 - prob.p) * V_cur[ci + di[dir]][cj + dj[dir]];\n            } else {\n                val += (1.0 - prob.p) * V_cur[ci][cj];\n            }\n            \n            if (val > bestVal) {\n                bestVal = val;\n                bestDir = dir;\n            }\n        }\n        \n        path += dirChar[bestDir];\n        if (canMove(prob, ci, cj, bestDir)) {\n            ci += di[bestDir];\n            cj += dj[bestDir];\n        }\n    }\n    \n    // Smart padding: if at target, add moves that keep us there\n    while ((int)path.size() < pathLen) {\n        if (ci == prob.ti && cj == prob.tj) {\n            // Try to stay at target (any move that hits wall or forgets keeps us there)\n            // Prefer moves that would hit walls\n            bool found = false;\n            for (int dir = 0; dir < 4; dir++) {\n                if (!canMove(prob, ci, cj, dir)) {\n                    path += dirChar[dir];\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) path += 'R';\n        } else {\n            path += 'R';\n        }\n    }\n    \n    return path;\n}\n\nstring explorePath(const Problem& prob, int maxLen, mt19937& rng) {\n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    vector<vector<int>> visitCount(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n    \n    while ((int)path.size() < maxLen && (ci != prob.ti || cj != prob.tj)) {\n        visitCount[ci][cj]++;\n        \n        vector<pair<int, int>> candidates;\n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                int dist = abs(ni - prob.ti) + abs(nj - prob.tj);\n                int visits = visitCount[ni][nj];\n                candidates.push_back({dir, dist * 10 + visits});\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        sort(candidates.begin(), candidates.end(), \n             [](const pair<int,int>& a, const pair<int,int>& b) {\n                 return a.second < b.second;\n             });\n        \n        uniform_real_distribution<double> dist(0.0, 1.0);\n        int idx = (dist(rng) < 0.7) ? 0 : min((int)candidates.size() - 1, 1 + (int)(dist(rng) * (candidates.size() - 1)));\n        int bestDir = candidates[idx].first;\n        \n        path += dirChar[bestDir];\n        ci += di[bestDir];\n        cj += dj[bestDir];\n    }\n    \n    return path;\n}\n\n// Local search to improve path\nstring localSearch(const Problem& prob, string path, int iterations = 50) {\n    if (path.empty()) return path;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double bestScore = evaluatePathDP(prob, path);\n    string bestPath = path;\n    \n    uniform_int_distribution<int> posDist(0, max(0, (int)path.size() - 1));\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        string candidate = path;\n        int pos = posDist(rng);\n        int newDir = dirDist(rng);\n        candidate[pos] = dirChar[newDir];\n        \n        if (pathReachesTarget(prob, candidate)) {\n            double score = evaluatePathDP(prob, candidate);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = candidate;\n                path = candidate;\n            }\n        }\n    }\n    \n    return bestPath;\n}\n\nstring robustFallback(const Problem& prob) {\n    vector<vector<int>> orderings = {\n        {1, 3, 0, 2}, {3, 1, 2, 0}, {1, 3, 2, 0},\n        {3, 1, 0, 2}, {0, 1, 2, 3}, {1, 0, 3, 2},\n        {3, 0, 1, 2}, {1, 2, 3, 0}\n    };\n    \n    for (const auto& order : orderings) {\n        string path = bfsPath(prob, order);\n        if (!path.empty() && pathReachesTarget(prob, path)) {\n            return path;\n        }\n    }\n    \n    return \"\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Problem prob;\n    cin >> prob.si >> prob.sj >> prob.ti >> prob.tj >> prob.p;\n    \n    prob.h.resize(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; i++) cin >> prob.h[i];\n    \n    prob.v.resize(GRID_SIZE - 1);\n    for (int i = 0; i < GRID_SIZE - 1; i++) cin >> prob.v[i];\n    \n    string bestPath = \"\";\n    double bestScore = 0.0;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Strategy 1: BFS with multiple direction orderings\n    vector<vector<int>> bfsOrders = {\n        {1, 3, 0, 2}, {3, 1, 0, 2}, {1, 3, 2, 0},\n        {3, 1, 2, 0}, {0, 1, 2, 3}, {1, 0, 3, 2}\n    };\n    \n    for (const auto& order : bfsOrders) {\n        string bfs = bfsPath(prob, order);\n        if (!bfs.empty() && pathReachesTarget(prob, bfs)) {\n            // Test with different padding lengths\n            for (int totalLen = (int)bfs.size(); totalLen <= min(MAX_STEPS, (int)bfs.size() + 40); totalLen += 5) {\n                string padded = bfs;\n                int ci = prob.si, cj = prob.sj;\n                for (char c : bfs) {\n                    int dir = (c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3);\n                    if (canMove(prob, ci, cj, dir)) {\n                        ci += di[dir];\n                        cj += dj[dir];\n                    }\n                    if (ci == prob.ti && cj == prob.tj) break;\n                }\n                while ((int)padded.size() < totalLen) {\n                    if (ci == prob.ti && cj == prob.tj) {\n                        // Add moves that keep us at target\n                        bool found = false;\n                        for (int dir = 0; dir < 4; dir++) {\n                            if (!canMove(prob, ci, cj, dir)) {\n                                padded += dirChar[dir];\n                                found = true;\n                                break;\n                            }\n                        }\n                        if (!found) padded += 'R';\n                    } else {\n                        padded += 'R';\n                    }\n                }\n                \n                if ((int)padded.size() <= MAX_STEPS) {\n                    double score = evaluatePathDP(prob, padded);\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestPath = padded;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Strategy 2: Weighted BFS\n    string weighted = bfsPathWeighted(prob);\n    if (!weighted.empty() && pathReachesTarget(prob, weighted)) {\n        double score = evaluatePathDP(prob, weighted);\n        if (score > bestScore) {\n            bestScore = score;\n            bestPath = weighted;\n        }\n    }\n    \n    // Strategy 3: DP-based paths (more granular lengths)\n    for (int pathLen = 30; pathLen <= 180; pathLen += 10) {\n        string path = dpPath(prob, pathLen);\n        if (pathReachesTarget(prob, path) && (int)path.size() <= MAX_STEPS) {\n            double score = evaluatePathDP(prob, path);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = path;\n            }\n        }\n    }\n    \n    // Strategy 4: Exploration with randomness\n    for (int i = 0; i < 8; i++) {\n        string path = explorePath(prob, MAX_STEPS, rng);\n        if (pathReachesTarget(prob, path)) {\n            double score = evaluatePathDP(prob, path);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = path;\n            }\n        }\n    }\n    \n    // Strategy 5: Local search on best path\n    if (!bestPath.empty()) {\n        string improved = localSearch(prob, bestPath, 30);\n        double score = evaluatePathDP(prob, improved);\n        if (score > bestScore) {\n            bestScore = score;\n            bestPath = improved;\n        }\n    }\n    \n    // Strategy 6: Robust fallback\n    if (bestPath.empty() || !pathReachesTarget(prob, bestPath)) {\n        string fallback = robustFallback(prob);\n        if (!fallback.empty() && pathReachesTarget(prob, fallback)) {\n            double score = evaluatePathDP(prob, fallback);\n            if (score > bestScore || bestPath.empty()) {\n                bestScore = score;\n                bestPath = fallback;\n            }\n        }\n    }\n    \n    // Final validation\n    if (bestPath.empty() || !pathReachesTarget(prob, bestPath)) {\n        bestPath = robustFallback(prob);\n    }\n    \n    // Ensure valid output\n    if ((int)bestPath.size() > MAX_STEPS) {\n        bestPath = bestPath.substr(0, MAX_STEPS);\n    }\n    if (bestPath.empty()) {\n        bestPath = \"R\";\n    }\n    \n    cout << bestPath << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entering_direction] = exiting_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0: curve\n    {3, -1, -1, 0},  // 1: curve\n    {-1, -1, 3, 2},  // 2: curve\n    {-1, 2, 1, -1},  // 3: curve\n    {1, 0, 3, 2},    // 4: double curve\n    {3, 2, 1, 0},    // 5: double curve\n    {2, -1, 0, -1},  // 6: straight\n    {-1, 3, -1, 1},  // 7: straight\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint grid[N][N];\nint rot[N][N];\n\ninline int rotate_tile(int t, int r) {\n    if (t <= 3) return (t + r) % 4;\n    else if (t <= 5) return 4 + ((t - 4 + r) % 2);\n    else return 6 + ((t - 6 + r) % 2);\n}\n\ninline int get_tile(int i, int j) {\n    return rotate_tile(grid[i][j], rot[i][j]);\n}\n\n// Fast loop tracing with step limit\nint trace_loop(int si, int sj, int sd, int max_steps = 500) {\n    int i = si, j = sj, d = sd;\n    for (int len = 1; len <= max_steps; len++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 == -1) return 0;\n        i += di[d2];\n        j += dj[d2];\n        d = (d2 + 2) % 4;\n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        if (i == si && j == sj && d == sd) return len;\n    }\n    return 0;\n}\n\n// Sample-based loop detection (faster than full scan)\npair<long long, long long> sample_loops(mt19937& rng, int samples = 200) {\n    vector<int> loops;\n    \n    for (int s = 0; s < samples; s++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        int d = rng() % 4;\n        \n        int len = trace_loop(i, j, d, 600);\n        if (len > 1) {\n            loops.push_back(len);\n        }\n    }\n    \n    // Also check strategic points (edges, corners)\n    for (int i = 0; i < N; i += 5) {\n        for (int j = 0; j < N; j += 5) {\n            for (int d = 0; d < 4; d++) {\n                int len = trace_loop(i, j, d, 600);\n                if (len > 1) loops.push_back(len);\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    // Get unique top 2\n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Full scan for final evaluation\npair<long long, long long> full_scan_loops() {\n    vector<int> loops;\n    static bool vis[N][N][4];\n    memset(vis, 0, sizeof(vis));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                if (vis[i][j][d]) continue;\n                \n                vector<tuple<int,int,int>> path;\n                int ci = i, cj = j, cd = d;\n                \n                while (ci >= 0 && ci < N && cj >= 0 && cj < N && !vis[ci][cj][cd]) {\n                    vis[ci][cj][cd] = true;\n                    path.push_back({ci, cj, cd});\n                    \n                    int t = get_tile(ci, cj);\n                    int d2 = to[t][cd];\n                    if (d2 == -1) break;\n                    \n                    ci += di[d2];\n                    cj += dj[d2];\n                    cd = (d2 + 2) % 4;\n                }\n                \n                if (ci >= 0 && ci < N && cj >= 0 && cj < N) {\n                    for (int k = 0; k < (int)path.size(); k++) {\n                        if (get<0>(path[k]) == ci && \n                            get<1>(path[k]) == cj && \n                            get<2>(path[k]) == cd) {\n                            int loop_len = path.size() - k;\n                            if (loop_len > 1) {\n                                loops.push_back(loop_len);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Evaluate connectivity score for a tile (heuristic)\nint connectivity_score(int i, int j, int r) {\n    int score = 0;\n    int old_rot = rot[i][j];\n    rot[i][j] = r;\n    \n    // Check all 4 directions\n    for (int d = 0; d < 4; d++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 != -1) {\n            int ni = i + di[d2];\n            int nj = j + dj[d2];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nt = get_tile(ni, nj);\n                int back_d = (d2 + 2) % 4;\n                if (to[nt][back_d] != -1) {\n                    score += 10;\n                }\n            }\n        }\n    }\n    \n    rot[i][j] = old_rot;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Multiple restarts with different seeds\n    long long global_best = 0;\n    int best_rot[N][N];\n    memset(best_rot, 0, sizeof(best_rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    int restart = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Leave 150ms for final output\n        if (elapsed >= 1850) break;\n        \n        // Initialize rotations\n        memset(rot, 0, sizeof(rot));\n        \n        // Smart initialization: try to create connections\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int best_r = 0;\n                int best_score = -1;\n                for (int r = 0; r < 4; r++) {\n                    int score = connectivity_score(i, j, r);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n        \n        // Add some randomness to initial configuration\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (rng() % 3 == 0) {\n                    rot[i][j] = rng() % 4;\n                }\n            }\n        }\n        \n        // Get initial score\n        auto [l1, l2] = sample_loops(rng, 100);\n        long long current_score = l1 * l2;\n        long long local_best = current_score;\n        \n        // Simulated annealing with adaptive temperature\n        double temp = 500.0;\n        int iterations = 0;\n        int no_improve = 0;\n        \n        while (elapsed < 1850) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1850) break;\n            \n            // Adaptive temperature based on time remaining\n            double time_ratio = (1850.0 - elapsed) / 1850.0;\n            temp = 500.0 * pow(time_ratio, 2.0) + 1.0;\n            \n            // Number of tiles to change (increases with temperature)\n            int num_changes = 1 + (int)(3.0 * temp / 500.0);\n            num_changes = min(num_changes, 5);\n            \n            vector<pair<int,int>> changes;\n            vector<int> old_rots;\n            \n            for (int c = 0; c < num_changes; c++) {\n                int i = rng() % N;\n                int j = rng() % N;\n                changes.push_back({i, j});\n                old_rots.push_back(rot[i][j]);\n                rot[i][j] = (old_rots.back() + 1 + rng() % 3) % 4;\n            }\n            \n            auto [nl1, nl2] = sample_loops(rng, 80);\n            long long new_score = nl1 * nl2;\n            \n            bool accept = false;\n            if (new_score >= current_score) {\n                accept = true;\n                if (new_score > local_best) {\n                    local_best = new_score;\n                    no_improve = 0;\n                    memcpy(best_rot, rot, sizeof(rot));\n                }\n            } else if (temp > 0.5) {\n                double prob = exp((double)(new_score - current_score) / temp);\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (!accept) {\n                for (int c = 0; c < num_changes; c++) {\n                    rot[changes[c].first][changes[c].second] = old_rots[c];\n                }\n            } else {\n                current_score = new_score;\n            }\n            \n            iterations++;\n            no_improve++;\n            \n            // Restart if stuck\n            if (no_improve > 5000 && restart < 3) {\n                break;\n            }\n        }\n        \n        if (local_best > global_best) {\n            global_best = local_best;\n        }\n        \n        restart++;\n    }\n    \n    // Restore best configuration\n    memcpy(rot, best_rot, sizeof(rot));\n    \n    // Final full evaluation\n    auto [fl1, fl2] = full_scan_loops();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << rot[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int LEFT = 1, UP = 2, RIGHT = 4, DOWN = 8;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dirs[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\nint N;\nlong long T;\nvector<vector<int>> board;\nint emptyR, emptyC;\nstring operations;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Quick connection check\ninline bool connects(int r1, int c1, int r2, int c2, const vector<vector<int>>& b) {\n    if (b[r1][c1] == 0 || b[r2][c2] == 0) return false;\n    if (r2 == r1 + 1) return (b[r1][c1] & DOWN) && (b[r2][c2] & UP);\n    if (r2 == r1 - 1) return (b[r1][c1] & UP) && (b[r2][c2] & DOWN);\n    if (c2 == c1 + 1) return (b[r1][c1] & RIGHT) && (b[r2][c2] & LEFT);\n    if (c2 == c1 - 1) return (b[r1][c1] & LEFT) && (b[r2][c2] & RIGHT);\n    return false;\n}\n\n// Compute connected components\nstruct ComponentInfo {\n    int numComponents;\n    int maxTreeSize;\n    int totalEdges;\n    vector<vector<int>> componentId;\n    vector<int> componentSize;\n};\n\nComponentInfo computeComponents(const vector<vector<int>>& b) {\n    ComponentInfo info{0, 0, 0, vector<vector<int>>(N, vector<int>(N, -1)), {}};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] != 0 && info.componentId[i][j] == -1) {\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                info.componentId[i][j] = info.numComponents;\n                \n                while (!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    size++;\n                    \n                    for (int d = 0; d < 4; d++) {\n                        int nr = r + dr[d], nc = c + dc[d];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                            b[nr][nc] != 0 && info.componentId[nr][nc] == -1 &&\n                            connects(r, c, nr, nc, b)) {\n                            info.componentId[nr][nc] = info.numComponents;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                \n                info.componentSize.push_back(size);\n                info.maxTreeSize = max(info.maxTreeSize, size);\n                info.numComponents++;\n            }\n        }\n    }\n    \n    // Count edges\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            if (connects(i, j, i + 1, j, b)) info.totalEdges++;\n        }\n    }\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N - 1; j++) {\n            if (connects(i, j, i, j + 1, b)) info.totalEdges++;\n        }\n    }\n    \n    return info;\n}\n\n// Advanced evaluation with component awareness\ndouble evaluate(const vector<vector<int>>& b) {\n    auto info = computeComponents(b);\n    int totalTiles = N * N - 1;\n    \n    // Base score from largest component\n    double score = info.maxTreeSize * 100.0;\n    \n    // Penalty for many small components (encourage merging)\n    if (info.numComponents > 1) {\n        score -= info.numComponents * 50.0;\n    }\n    \n    // Bonus for edges (connectivity)\n    score += info.totalEdges * 20.0;\n    \n    // Huge bonus for complete tree\n    if (info.maxTreeSize == totalTiles) {\n        score += 1000000.0;\n    }\n    \n    // Bonus for having few large components vs many small ones\n    double variance = 0;\n    for (int s : info.componentSize) {\n        variance += (double)s * s;\n    }\n    score += variance * 0.5;\n    \n    return score;\n}\n\n// Tabu state for preventing cycles\nstruct TabuState {\n    vector<vector<int>> board;\n    int emptyR, emptyC;\n    \n    bool operator==(const TabuState& other) const {\n        if (emptyR != other.emptyR || emptyC != other.emptyC) return false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (board[i][j] != other.board[i][j]) return false;\n        return true;\n    }\n};\n\n// Board state for saving/restoring\nstruct BoardState {\n    vector<vector<int>> board;\n    int emptyR, emptyC;\n    string ops;\n    \n    void save(const vector<vector<int>>& b, int er, int ec, const string& o) {\n        board = b;\n        emptyR = er;\n        emptyC = ec;\n        ops = o;\n    }\n    \n    void restore(vector<vector<int>>& b, int& er, int& ec, string& o) {\n        b = board;\n        er = emptyR;\n        ec = emptyC;\n        o = ops;\n    }\n};\n\n// BFS path for empty square\nstring getEmptyPath(const vector<vector<int>>& b, int er, int ec, int targetR, int targetC) {\n    if (er == targetR && ec == targetC) return \"\";\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<int>> dirUsed(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({er, ec});\n    visited[er][ec] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        \n        if (r == targetR && c == targetC) {\n            string path;\n            int cr = r, cc = c;\n            while (parent[cr][cc].first != -1) {\n                path += dirs[dirUsed[cr][cc]];\n                int pr = parent[cr][cc].first;\n                int pc = parent[cr][cc].second;\n                cr = pr; cc = pc;\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                dirUsed[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n    }\n    return \"\";\n}\n\n// Execute single move\nbool executeMove(int dir, vector<vector<int>>& b, int& er, int& ec, string& ops) {\n    int nr = er + dr[dir];\n    int nc = ec + dc[dir];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n    if (b[nr][nc] == 0) return false;\n    if (ops.size() >= (size_t)T) return false;\n    \n    b[er][ec] = b[nr][nc];\n    b[nr][nc] = 0;\n    er = nr;\n    ec = nc;\n    ops += dirs[dir];\n    return true;\n}\n\n// Run one search with given seed\nBoardState runSearch(long long seed, auto startTime) {\n    mt19937 localRng(seed);\n    \n    vector<vector<int>> localBoard = board;\n    int localER = emptyR, localEC = emptyC;\n    string localOps = \"\";\n    \n    BoardState bestState;\n    bestState.save(localBoard, localER, localEC, localOps);\n    double bestScore = evaluate(localBoard);\n    int bestTreeSize = computeComponents(localBoard).maxTreeSize;\n    \n    // Tabu list (store last 100 states)\n    deque<TabuState> tabuList;\n    const int TABU_SIZE = 100;\n    \n    double temperature = 500.0;\n    int noImprovement = 0;\n    int lastMoveDir = -1;\n    \n    while (localOps.size() < (size_t)T) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        \n        if (elapsed > 2850) break;\n        if (bestTreeSize == N * N - 1) break;\n        \n        // Get valid moves (avoid immediate reversal)\n        vector<int> moves;\n        for (int d = 0; d < 4; d++) {\n            if (lastMoveDir >= 0 && d == opp[lastMoveDir]) continue;\n            int nr = localER + dr[d];\n            int nc = localEC + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && localBoard[nr][nc] != 0) {\n                // Check tabu\n                TabuState ts{localBoard, localER, localEC};\n                // Execute move temporarily to check resulting state\n                int ter = nr, tec = nc;\n                ts.board[localER][localEC] = localBoard[nr][nc];\n                ts.board[nr][nc] = 0;\n                ts.emptyR = nr;\n                ts.emptyC = nc;\n                \n                bool isTabu = false;\n                for (const auto& tabu : tabuList) {\n                    if (tabu == ts) {\n                        isTabu = true;\n                        break;\n                    }\n                }\n                \n                if (!isTabu || localOps.size() < 20) {  // Allow tabu early on\n                    moves.push_back(d);\n                }\n            }\n        }\n        \n        if (moves.empty()) {\n            // All moves tabu, clear oldest\n            if (!tabuList.empty()) tabuList.pop_front();\n            continue;\n        }\n        \n        // Evaluate moves with lookahead\n        vector<pair<double, int>> moveScores;\n        for (int d : moves) {\n            // Save state\n            auto savedBoard = localBoard;\n            int savedER = localER, savedEC = localEC;\n            auto savedOps = localOps;\n            \n            // Make move\n            executeMove(d, localBoard, localER, localEC, localOps);\n            \n            // Lookahead: try one more move\n            double score = evaluate(localBoard);\n            vector<int> nextMoves;\n            for (int nd = 0; nd < 4; nd++) {\n                if (nd == opp[d]) continue;\n                int nnr = localER + dr[nd];\n                int nnc = localEC + dc[nd];\n                if (nnr >= 0 && nnr < N && nnc >= 0 && nnc < N && localBoard[nnr][nnc] != 0) {\n                    nextMoves.push_back(nd);\n                }\n            }\n            \n            // Simple 1-ply lookahead\n            if (!nextMoves.empty()) {\n                double bestNext = score;\n                for (int nd : nextMoves) {\n                    auto savedBoard2 = localBoard;\n                    int savedER2 = localER, savedEC2 = localEC;\n                    executeMove(nd, localBoard, localER, localEC, localOps);\n                    bestNext = max(bestNext, evaluate(localBoard));\n                    localBoard = savedBoard2;\n                    localER = savedER2;\n                    localEC = savedEC2;\n                    localOps = savedOps;\n                }\n                score = (score + bestNext) / 2.0;\n            }\n            \n            moveScores.push_back({score, d});\n            \n            // Restore state\n            localBoard = savedBoard;\n            localER = savedER;\n            localEC = savedEC;\n            localOps = savedOps;\n        }\n        \n        // Sort moves\n        sort(moveScores.begin(), moveScores.end(), [](auto& a, auto& b) {\n            return a.first > b.first;\n        });\n        \n        // Simulated annealing selection\n        int selectedDir = moveScores[0].second;\n        double currentScore = bestScore;\n        \n        for (int i = 0; i < min((int)moveScores.size(), 15); i++) {\n            double delta = moveScores[i].first - currentScore;\n            if (delta >= 0) {\n                selectedDir = moveScores[i].second;\n                break;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                double prob = exp(delta / temperature);\n                if (dist(localRng) < prob) {\n                    selectedDir = moveScores[i].second;\n                    break;\n                }\n            }\n        }\n        \n        // Execute move\n        executeMove(selectedDir, localBoard, localER, localEC, localOps);\n        lastMoveDir = selectedDir;\n        \n        // Add to tabu list\n        TabuState ts{localBoard, localER, localEC};\n        tabuList.push_back(ts);\n        if ((int)tabuList.size() > TABU_SIZE) tabuList.pop_front();\n        \n        // Update best\n        double newScore = evaluate(localBoard);\n        auto info = computeComponents(localBoard);\n        \n        if (newScore > bestScore) {\n            bestScore = newScore;\n            bestTreeSize = info.maxTreeSize;\n            bestState.save(localBoard, localER, localEC, localOps);\n            noImprovement = 0;\n            temperature = max(10.0, temperature * 0.99);  // Slow down cooling on improvement\n        } else {\n            noImprovement++;\n        }\n        \n        // Adaptive temperature\n        if (noImprovement > 300) {\n            temperature *= 1.5;  // Heat up to escape\n            noImprovement = 0;\n        }\n        \n        // Time-based cooling\n        elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - startTime).count();\n        double timeRatio = elapsed / 2850.0;\n        temperature = max(1.0, 500.0 * (1.0 - timeRatio * 0.9));\n    }\n    \n    return bestState;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> T;\n    \n    board.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') {\n                board[i][j] = c - '0';\n            } else {\n                board[i][j] = c - 'a' + 10;\n            }\n            if (board[i][j] == 0) {\n                emptyR = i;\n                emptyC = j;\n            }\n        }\n    }\n    \n    BoardState globalBest;\n    globalBest.save(board, emptyR, emptyC, \"\");\n    int globalBestTreeSize = computeComponents(board).maxTreeSize;\n    double globalBestScore = evaluate(board);\n    \n    // Run multiple independent searches\n    int numSearches = 12;\n    vector<long long> seeds;\n    for (int i = 0; i < numSearches; i++) {\n        seeds.push_back(rng());\n    }\n    \n    for (int i = 0; i < numSearches; i++) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        \n        if (elapsed > 2900) break;\n        if (globalBestTreeSize == N * N - 1) break;\n        \n        BoardState searchResult = runSearch(seeds[i], startTime);\n        \n        // Restore to evaluate\n        vector<vector<int>> tempBoard;\n        int tempER, tempEC;\n        string tempOps;\n        searchResult.restore(tempBoard, tempER, tempEC, tempOps);\n        \n        double searchScore = evaluate(tempBoard);\n        auto searchInfo = computeComponents(tempBoard);\n        \n        if (searchScore > globalBestScore || \n            (searchInfo.maxTreeSize == N * N - 1 && globalBestTreeSize < N * N - 1)) {\n            globalBestScore = searchScore;\n            globalBestTreeSize = searchInfo.maxTreeSize;\n            globalBest = searchResult;\n        }\n    }\n    \n    // Output best operations\n    cout << globalBest.ops << endl;\n    \n    return 0;\n}","ahc012":"#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\nstruct Strawberry {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n    \n    long long side(long long x, long long y) const {\n        return (qx - px) * (y - py) - (qy - py) * (x - px);\n    }\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> cuts;\nmt19937 rng(12345);\n\nbool lineHitsStrawberry(const Line& line) {\n    for (int i = 0; i < N; i++) {\n        if (line.side(strawberries[i].x, strawberries[i].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Try to find a valid line near the given specification\nbool tryFindLine(long long px, long long py, long long qx, long long qy, Line& outLine) {\n    Line base = {px, py, qx, qy};\n    \n    // Try small adjustments\n    for (int dx = -5; dx <= 5; dx++) {\n        for (int dy = -5; dy <= 5; dy++) {\n            Line test = {px + dx, py + dy, qx + dx, qy + dy};\n            if (!lineHitsStrawberry(test)) {\n                outLine = test;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    set<pair<long long, long long>> usedDirections;\n    \n    // Generate cuts with multiple strategies\n    vector<Line> allCandidates;\n    \n    // Strategy 1: Dense vertical lines (spacing ~150)\n    for (int i = 0; i < 40; i++) {\n        long long x = -9000 + i * 150 + (rng() % 50);\n        Line line;\n        if (tryFindLine(x, -15000, x, 15000, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Strategy 2: Dense horizontal lines (spacing ~150)\n    for (int i = 0; i < 40; i++) {\n        long long y = -9000 + i * 150 + (rng() % 50);\n        Line line;\n        if (tryFindLine(-15000, y, 15000, y, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Strategy 3: Diagonal lines at various angles\n    vector<double> angles;\n    for (int i = 1; i <= 16; i++) {\n        angles.push_back(i * 3.14159265359 / 17);\n    }\n    \n    for (double angle : angles) {\n        long long dx = (long long)(cos(angle) * 20000);\n        long long dy = (long long)(sin(angle) * 20000);\n        long long px_perp = (long long)(cos(angle + 3.14159265359/2) * 20000);\n        long long py_perp = (long long)(sin(angle + 3.14159265359/2) * 20000);\n        \n        for (int offset = 0; offset < 20; offset++) {\n            long long ox = -10000 + offset * 500 + (rng() % 100);\n            long long oy = -10000 + offset * 500 + (rng() % 100);\n            long long px = ox;\n            long long py = oy;\n            long long qx = px + dx;\n            long long qy = py + dy;\n            \n            Line line;\n            if (tryFindLine(px, py, qx, qy, line)) {\n                allCandidates.push_back(line);\n            }\n        }\n    }\n    \n    // Strategy 4: Random lines for additional coverage\n    for (int i = 0; i < 50; i++) {\n        double angle = rng() % 360 * 3.14159265359 / 180.0;\n        long long dx = (long long)(cos(angle) * 20000);\n        long long dy = (long long)(sin(angle) * 20000);\n        long long offset = (rng() % 20001) - 10000;\n        long long px = (long long)(offset * cos(angle + 3.14159265359/2));\n        long long py = (long long)(offset * sin(angle + 3.14159265359/2));\n        long long qx = px + dx;\n        long long qy = py + dy;\n        \n        Line line;\n        if (tryFindLine(px, py, qx, qy, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Select up to K cuts, prioritizing diversity\n    cuts.clear();\n    vector<bool> used(allCandidates.size(), false);\n    \n    // First pass: take vertical and horizontal for grid structure\n    for (size_t i = 0; i < allCandidates.size() && (int)cuts.size() < K; i++) {\n        long long dx = allCandidates[i].qx - allCandidates[i].px;\n        long long dy = allCandidates[i].qy - allCandidates[i].py;\n        \n        // Prefer axis-aligned lines first\n        if (abs(dx) < 1000 || abs(dy) < 1000) {\n            cuts.push_back(allCandidates[i]);\n            used[i] = true;\n        }\n    }\n    \n    // Second pass: fill remaining with diagonal lines\n    for (size_t i = 0; i < allCandidates.size() && (int)cuts.size() < K; i++) {\n        if (!used[i]) {\n            cuts.push_back(allCandidates[i]);\n        }\n    }\n    \n    // Final safety check\n    vector<Line> validCuts;\n    for (const auto& line : cuts) {\n        if (!lineHitsStrawberry(line)) {\n            validCuts.push_back(line);\n        }\n    }\n    cuts = validCuts;\n    \n    // Ensure we have at least some cuts\n    if (cuts.empty()) {\n        // Fallback: simple grid\n        for (int i = 0; i < K && i < 50; i++) {\n            long long x = -9500 + i * 400;\n            for (int adj = 0; adj < 100; adj++) {\n                Line line = {x + adj, -15000, x + adj, 15000};\n                if (!lineHitsStrawberry(line)) {\n                    cuts.push_back(line);\n                    break;\n                }\n            }\n        }\n    }\n    \n    cout << cuts.size() << \"\\n\";\n    for (const auto& line : cuts) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Global variables\nint N, M;\nbool has_dot[65][65];\nbool used_edge[65][65][4];\nvector<int> dots_in_row[65];\nvector<int> dots_in_col[65];\n\nstruct Point {\n    int x, y;\n    long long w;\n    int valid_rect_count;\n};\n\nvector<Point> sorted_points;\nvector<array<int, 8>> result_moves;\n\nauto start_time = chrono::steady_clock::now();\nconst double TIME_LIMIT = 4.5;\n\nstruct Rectangle {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    vector<pair<int,int>> rect_pts;\n    int edge_count;\n};\n\n// Mark a single unit edge\nvoid mark_unit_edge(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y2 == y1 + 1) {\n        used_edge[x1][y1][1] = true;\n    } else if (y1 == y2 && x2 == x1 + 1) {\n        used_edge[x1][y1][0] = true;\n    } else if (x2 == x1 + 1 && y2 == y1 + 1) {\n        used_edge[x1][y1][2] = true;\n    } else if (x2 == x1 - 1 && y2 == y1 + 1) {\n        used_edge[x2][y2][3] = true;\n    } else if (x1 == x2 && y1 == y2 + 1) {\n        used_edge[x2][y2][1] = true;\n    } else if (y1 == y2 && x1 == x2 + 1) {\n        used_edge[x2][y2][0] = true;\n    } else if (x1 == x2 + 1 && y1 == y2 + 1) {\n        used_edge[x2][y2][2] = true;\n    } else if (x1 == x2 - 1 && y1 == y2 + 1) {\n        used_edge[x1][y1][3] = true;\n    }\n}\n\n// Check if a single unit edge is used\nbool is_unit_edge_used(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y2 == y1 + 1) {\n        return used_edge[x1][y1][1];\n    } else if (y1 == y2 && x2 == x1 + 1) {\n        return used_edge[x1][y1][0];\n    } else if (x2 == x1 + 1 && y2 == y1 + 1) {\n        return used_edge[x1][y1][2];\n    } else if (x2 == x1 - 1 && y2 == y1 + 1) {\n        return used_edge[x2][y2][3];\n    } else if (x1 == x2 && y1 == y2 + 1) {\n        return used_edge[x2][y2][1];\n    } else if (y1 == y2 && x1 == x2 + 1) {\n        return used_edge[x2][y2][0];\n    } else if (x1 == x2 + 1 && y1 == y2 + 1) {\n        return used_edge[x2][y2][2];\n    } else if (x1 == x2 - 1 && y1 == y2 + 1) {\n        return used_edge[x1][y1][3];\n    }\n    return false;\n}\n\n// Mark all edges along a line segment\nvoid mark_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return;\n    \n    int sx = (dx == 0) ? 0 : (dx > 0 ? 1 : -1);\n    int sy = (dy == 0) ? 0 : (dy > 0 ? 1 : -1);\n    \n    int cx = x1, cy = y1;\n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        mark_unit_edge(cx, cy, nx, ny);\n        cx = nx;\n        cy = ny;\n    }\n}\n\n// Check if all edges along a line segment are unused\nbool check_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return true;\n    \n    int sx = (dx == 0) ? 0 : (dx > 0 ? 1 : -1);\n    int sy = (dy == 0) ? 0 : (dy > 0 ? 1 : -1);\n    \n    int cx = x1, cy = y1;\n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        if (is_unit_edge_used(cx, cy, nx, ny)) return false;\n        cx = nx;\n        cy = ny;\n    }\n    return true;\n}\n\n// Check perimeter constraints and count edges\nbool check_perimeter(const vector<pair<int,int>>& pts, const vector<pair<int,int>>& dots, int& edge_count) {\n    edge_count = 0;\n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        if (!check_segment(x1, y1, x2, y2)) return false;\n        edge_count += max(abs(x2 - x1), abs(y2 - y1));\n    }\n    \n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0) ? 0 : (dx / abs(dx));\n        int sy = (dy == 0) ? 0 : (dy / abs(dy));\n        \n        for (int k = 1; k < steps; ++k) {\n            int cx = x1 + k * sx;\n            int cy = y1 + k * sy;\n            if (has_dot[cx][cy]) {\n                bool allowed = false;\n                for (const auto& d : dots) {\n                    if (d.first == cx && d.second == cy) {\n                        allowed = true;\n                        break;\n                    }\n                }\n                if (!allowed) return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Find all valid rectangles for a point\nvector<Rectangle> find_all_rectangles(int x, int y) {\n    vector<Rectangle> rectangles;\n    \n    // 1. Axis Aligned rectangle\n    for (int x2 : dots_in_row[y]) {\n        if (x2 == x) continue;\n        for (int y2 : dots_in_col[x]) {\n            if (y2 == y) continue;\n            if (has_dot[x2][y2]) {\n                vector<pair<int,int>> rect = {{x, y}, {x2, y}, {x2, y2}, {x, y2}};\n                vector<pair<int,int>> dots = {{x2, y}, {x2, y2}, {x, y2}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, x2, y, x2, y2, x, y2, rect, edge_count});\n                }\n            }\n        }\n    }\n    \n    // 2. 45-degree - Vertical Diagonal\n    for (int yd : dots_in_col[x]) {\n        if (yd == y) continue;\n        int dy = yd - y;\n        if (abs(dy) % 2 != 0) continue;\n        int w = abs(dy) / 2;\n        int ym = y + dy / 2;\n        int xa = x - w;\n        int xb = x + w;\n        \n        if (xa >= 0 && xa < N && xb >= 0 && xb < N) {\n            if (has_dot[xa][ym] && has_dot[xb][ym]) {\n                vector<pair<int,int>> rect = {{x, y}, {xb, ym}, {x, yd}, {xa, ym}};\n                vector<pair<int,int>> dots = {{x, yd}, {xa, ym}, {xb, ym}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, xb, ym, x, yd, xa, ym, rect, edge_count});\n                }\n            }\n        }\n    }\n    \n    // 3. 45-degree - Horizontal Diagonal\n    for (int xd : dots_in_row[y]) {\n        if (xd == x) continue;\n        int dx = xd - x;\n        if (abs(dx) % 2 != 0) continue;\n        int w = abs(dx) / 2;\n        int xm = x + dx / 2;\n        int ya = y - w;\n        int yb = y + w;\n        \n        if (ya >= 0 && ya < N && yb >= 0 && yb < N) {\n            if (has_dot[xm][ya] && has_dot[xm][yb]) {\n                vector<pair<int,int>> rect = {{x, y}, {xm, yb}, {xd, y}, {xm, ya}};\n                vector<pair<int,int>> dots = {{xd, y}, {xm, ya}, {xm, yb}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, xm, yb, xd, y, xm, ya, rect, edge_count});\n                }\n            }\n        }\n    }\n    \n    return rectangles;\n}\n\n// Count valid rectangles for a point\nint count_valid_rectangles(int x, int y) {\n    return (int)find_all_rectangles(x, y).size();\n}\n\nvoid apply_rectangle(const Rectangle& rect) {\n    has_dot[rect.x1][rect.y1] = true;\n    dots_in_row[rect.y1].push_back(rect.x1);\n    dots_in_col[rect.x1].push_back(rect.y1);\n    \n    for (size_t i = 0; i < 4; ++i) {\n        mark_segment(rect.rect_pts[i].first, rect.rect_pts[i].second,\n                    rect.rect_pts[(i + 1) % 4].first, rect.rect_pts[(i + 1) % 4].second);\n    }\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    long long c = (N - 1) / 2;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        has_dot[x][y] = true;\n        dots_in_row[y].push_back(x);\n        dots_in_col[x].push_back(y);\n    }\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            sorted_points.push_back({x, y, w, 0});\n        }\n    }\n    \n    // Multiple passes to fill points\n    bool any_change = true;\n    int pass = 0;\n    \n    while (any_change) {\n        any_change = false;\n        pass++;\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        // Update valid rectangle counts and sort\n        for (auto& p : sorted_points) {\n            if (!has_dot[p.x][p.y]) {\n                p.valid_rect_count = count_valid_rectangles(p.x, p.y);\n            } else {\n                p.valid_rect_count = -1;\n            }\n        }\n        \n        // Sort by: has valid rects, then by weight (higher first), then by constraint (fewer options first)\n        sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n            bool a_valid = (a.valid_rect_count > 0);\n            bool b_valid = (b.valid_rect_count > 0);\n            if (a_valid != b_valid) return a_valid > b_valid;\n            if (a.w != b.w) return a.w > b.w;\n            // Prefer more constrained points (fewer options)\n            return a.valid_rect_count < b.valid_rect_count;\n        });\n        \n        // Find best move\n        Rectangle best_rect;\n        bool found = false;\n        int best_edge_count = 1000000;\n        long long best_weight = -1;\n        \n        for (const auto& p : sorted_points) {\n            if (has_dot[p.x][p.y]) continue;\n            if (p.valid_rect_count <= 0) continue;\n            \n            auto rects = find_all_rectangles(p.x, p.y);\n            if (rects.empty()) continue;\n            \n            // Choose rectangle with minimum edges (conserves edge space)\n            for (const auto& rect : rects) {\n                if (!found || rect.edge_count < best_edge_count || \n                    (rect.edge_count == best_edge_count && p.w > best_weight)) {\n                    best_rect = rect;\n                    best_edge_count = rect.edge_count;\n                    best_weight = p.w;\n                    found = true;\n                }\n            }\n            \n            if (found && p.w < best_weight - 100) break; // Don't go too far down in weight\n        }\n        \n        if (found) {\n            result_moves.push_back({best_rect.x1, best_rect.y1, best_rect.x2, best_rect.y2, \n                                    best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4});\n            apply_rectangle(best_rect);\n            any_change = true;\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& m : result_moves) {\n        cout << m[0] << \" \" << m[1] << \" \" << m[2] << \" \" << m[3] << \" \" \n             << m[4] << \" \" << m[5] << \" \" << m[6] << \" \" << m[7] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 10;\n\nstruct Candy {\n    int flavor;\n    int row, col;\n};\n\nclass GameState {\npublic:\n    array<array<int, N>, N> grid;  // 0 = empty, 1-3 = flavor\n    vector<Candy> candies;\n    \n    GameState() {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = 0;\n    }\n    \n    GameState(const GameState& other) = default;\n    \n    void placeCandy(int row, int col, int flavor) {\n        grid[row][col] = flavor;\n        candies.push_back({flavor, row, col});\n    }\n    \n    vector<pair<int,int>> getEmptyCells() const {\n        vector<pair<int,int>> empty;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    empty.push_back({i, j});\n                }\n            }\n        }\n        return empty;\n    }\n    \n    GameState tilt(char dir) const {\n        GameState result = *this;\n        auto& g = result.grid;\n        \n        if (dir == 'F') {  // Forward (up)\n            for (int j = 0; j < N; j++) {\n                int writeRow = 0;\n                for (int i = 0; i < N; i++) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow++;\n                    }\n                }\n            }\n        } else if (dir == 'B') {  // Backward (down)\n            for (int j = 0; j < N; j++) {\n                int writeRow = N - 1;\n                for (int i = N - 1; i >= 0; i--) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow--;\n                    }\n                }\n            }\n        } else if (dir == 'L') {  // Left\n            for (int i = 0; i < N; i++) {\n                int writeCol = 0;\n                for (int j = 0; j < N; j++) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol++;\n                    }\n                }\n            }\n        } else if (dir == 'R') {  // Right\n            for (int i = 0; i < N; i++) {\n                int writeCol = N - 1;\n                for (int j = N - 1; j >= 0; j--) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol--;\n                    }\n                }\n            }\n        }\n        \n        // Update candy positions\n        result.candies.clear();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (g[i][j] != 0) {\n                    result.candies.push_back({g[i][j], i, j});\n                }\n            }\n        }\n        \n        return result;\n    }\n    \n    int countSameFlavorAdjacency() const {\n        int count = 0;\n        const int dr[] = {-1, 1, 0, 0};\n        const int dc[] = {0, 0, -1, 1};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) continue;\n                for (int d = 0; d < 4; d++) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (grid[ni][nj] == grid[i][j]) {\n                            count++;\n                        }\n                    }\n                }\n            }\n        }\n        return count / 2;  // Each adjacency counted twice\n    }\n    \n    vector<int> getComponentSizes() const {\n        vector<int> sizes;\n        array<array<bool, N>, N> visited{};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0 && !visited[i][j]) {\n                    int flavor = grid[i][j];\n                    int size = 0;\n                    vector<pair<int,int>> stack = {{i, j}};\n                    visited[i][j] = true;\n                    \n                    while (!stack.empty()) {\n                        auto [r, c] = stack.back();\n                        stack.pop_back();\n                        size++;\n                        \n                        const int dr[] = {-1, 1, 0, 0};\n                        const int dc[] = {0, 0, -1, 1};\n                        \n                        for (int d = 0; d < 4; d++) {\n                            int nr = r + dr[d], nc = c + dc[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                if (!visited[nr][nc] && grid[nr][nc] == flavor) {\n                                    visited[nr][nc] = true;\n                                    stack.push_back({nr, nc});\n                                }\n                            }\n                        }\n                    }\n                    sizes.push_back(size);\n                }\n            }\n        }\n        return sizes;\n    }\n    \n    double evaluateScore() const {\n        auto sizes = getComponentSizes();\n        array<int, 4> flavorCount{};\n        \n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] != 0)\n                    flavorCount[grid[i][j]]++;\n        \n        double numerator = 0;\n        for (int s : sizes) numerator += s * s;\n        \n        double denominator = 0;\n        for (int f = 1; f <= 3; f++) denominator += flavorCount[f] * flavorCount[f];\n        \n        if (denominator == 0) return 0;\n        return 1e6 * numerator / denominator;\n    }\n    \n    // Heuristic evaluation for greedy selection\n    double heuristicEvaluate(const vector<int>& futureFlavors, int lookAhead) const {\n        double score = countSameFlavorAdjacency() * 10.0;\n        \n        // Add component size bonus\n        auto sizes = getComponentSizes();\n        for (int s : sizes) {\n            score += s * s * 0.5;\n        }\n        \n        // Consider future flavors - prefer tilts that create space for upcoming flavors\n        if (lookAhead > 0 && !futureFlavors.empty()) {\n            array<int, 4> flavorCount{};\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (grid[i][j] != 0)\n                        flavorCount[grid[i][j]]++;\n            \n            // Bonus for having clusters of flavors that appear soon\n            for (int f = 1; f <= 3; f++) {\n                if (flavorCount[f] > 0) {\n                    int upcoming = 0;\n                    for (int i = 0; i < min(lookAhead, (int)futureFlavors.size()); i++) {\n                        if (futureFlavors[i] == f) upcoming++;\n                    }\n                    score += upcoming * flavorCount[f] * 0.3;\n                }\n            }\n        }\n        \n        return score;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read flavor sequence\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    GameState state;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Find the p-th empty cell (1-indexed)\n        auto empty = state.getEmptyCells();\n        int row = empty[p - 1].first;\n        int col = empty[p - 1].second;\n        \n        // Place the candy\n        state.placeCandy(row, col, flavors[t]);\n        \n        // Skip tilt on last candy (nothing happens)\n        if (t == 99) {\n            cout << 'F' << endl;\n            continue;\n        }\n        \n        // Evaluate all 4 tilt directions\n        vector<pair<double, char>> evaluations;\n        \n        for (char dir : dirs) {\n            GameState next = state.tilt(dir);\n            \n            // Base heuristic score\n            double score = next.heuristicEvaluate(\n                vector<int>(flavors.begin() + t + 1, flavors.end()),\n                5\n            );\n            \n            // Add some randomness for exploration\n            score += (rng() % 100) * 0.01;\n            \n            evaluations.push_back({score, dir});\n        }\n        \n        // Select best direction\n        sort(evaluations.begin(), evaluations.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        char bestDir = evaluations[0].second;\n        cout << bestDir << endl;\n        \n        // Update state\n        state = state.tilt(bestDir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Compute degree sequence from edge string (sorted)\nvector<int> computeDegreeSeq(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Count edges\nint countEdges(const string& edges) {\n    int cnt = 0;\n    for (char c : edges) {\n        if (c == '1') cnt++;\n    }\n    return cnt;\n}\n\n// Sum of squared degrees\nlong long computeSumSqDegrees(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2\nint count2Paths(const vector<int>& deg) {\n    int paths = 0;\n    for (int d : deg) {\n        if (d >= 2) paths += d * (d - 1) / 2;\n    }\n    return paths;\n}\n\n// Degree variance\ndouble computeDegreeVariance(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    double mean = accumulate(deg.begin(), deg.end(), 0.0) / deg.size();\n    double var = 0;\n    for (int d : deg) {\n        var += (d - mean) * (d - mean);\n    }\n    return var / deg.size();\n}\n\n// Degree entropy\ndouble computeDegreeEntropy(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    int total = accumulate(deg.begin(), deg.end(), 0);\n    if (total == 0) return 0;\n    double entropy = 0;\n    for (int d : deg) {\n        if (d > 0) {\n            double p = (double)d / total;\n            entropy -= p * log2(p);\n        }\n    }\n    return entropy;\n}\n\n// Build adjacency matrix\nvector<vector<bool>> buildAdj(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    return adj;\n}\n\n// Count triangles\nint countTriangles(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    int triangles = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!adj[i][j]) continue;\n            for (int k = j + 1; k < N; k++) {\n                if (adj[i][k] && adj[j][k]) {\n                    triangles++;\n                }\n            }\n        }\n    }\n    return triangles;\n}\n\n// Count connected components\nint countConnectedComponents(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    vector<bool> visited(N, false);\n    int components = 0;\n    for (int i = 0; i < N; i++) {\n        if (!visited[i]) {\n            components++;\n            vector<int> q = {i};\n            visited[i] = true;\n            int head = 0;\n            while (head < (int)q.size()) {\n                int u = q[head++];\n                for (int v = 0; v < N; v++) {\n                    if (adj[u][v] && !visited[v]) {\n                        visited[v] = true;\n                        q.push_back(v);\n                    }\n                }\n            }\n        }\n    }\n    return components;\n}\n\nstruct GraphInfo {\n    string edges;\n    int edge_count;\n    vector<int> degree_seq;\n    long long sum_sq_deg;\n    int two_paths;\n    int triangles;\n    int components;\n    double degree_var;\n    double degree_entropy;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n    \n    // PROVEN N selection based on epsilon (from 139M version)\n    // Key insight: epsilon is the primary driver of required N\n    int N;\n    if (eps < 0.01) {\n        N = 15;\n    } else if (eps < 0.03) {\n        N = 20;\n    } else if (eps < 0.05) {\n        N = 26;\n    } else if (eps < 0.08) {\n        N = 34;\n    } else if (eps < 0.12) {\n        N = 45;\n    } else if (eps < 0.16) {\n        N = 56;\n    } else if (eps < 0.20) {\n        N = 68;\n    } else if (eps < 0.25) {\n        N = 80;\n    } else if (eps < 0.30) {\n        N = 90;\n    } else if (eps < 0.35) {\n        N = 96;\n    } else if (eps < 0.38) {\n        N = 99;\n    } else {\n        N = 100;\n    }\n    \n    // Adjust for very large M\n    if (M >= 85) N = min(100, N + 3);\n    if (M >= 95) N = 100;\n    \n    // Critical adjustment for difficult combinations\n    if (M >= 70 && eps >= 0.25) N = 100;\n    if (M >= 80 && eps >= 0.20) N = 100;\n    \n    N = max(4, min(100, N));\n    int total_edges = N * (N - 1) / 2;\n    \n    // Store graph information\n    vector<GraphInfo> graphs(M);\n    \n    // CRITICAL: Use CONSISTENT graph generation for all graphs\n    // Different shuffle patterns caused unpredictable variance\n    // Use same deterministic pattern, only edge count varies\n    mt19937 base_rng(20240101);  // Fixed seed for reproducibility\n    \n    for (int k = 0; k < M; k++) {\n        GraphInfo& info = graphs[k];\n        \n        // Even distribution of edge counts\n        int target_edges = (M > 1) ? (k * total_edges) / max(1, M - 1) : total_edges / 2;\n        target_edges = max(0, min(total_edges, target_edges));\n        info.edge_count = target_edges;\n        \n        // CONSISTENT graph generation: same shuffle pattern for all graphs\n        string g(total_edges, '0');\n        vector<int> positions(total_edges);\n        iota(positions.begin(), positions.end(), 0);\n        \n        // Same shuffle for all graphs (only edge count differs)\n        // This ensures structural similarity, making edge count the primary differentiator\n        shuffle(positions.begin(), positions.end(), base_rng);\n        \n        for (int i = 0; i < target_edges && i < total_edges; i++) {\n            g[positions[i]] = '1';\n        }\n        \n        info.edges = g;\n        info.degree_seq = computeDegreeSeq(g, N);\n        info.sum_sq_deg = computeSumSqDegrees(info.degree_seq);\n        info.two_paths = count2Paths(info.degree_seq);\n        info.triangles = (eps < 0.20) ? countTriangles(g, N) : 0;\n        info.components = countConnectedComponents(g, N);\n        info.degree_var = computeDegreeVariance(info.degree_seq);\n        info.degree_entropy = computeDegreeEntropy(info.degree_seq);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << graphs[k].edges << \"\\n\";\n    }\n    cout << flush;\n    \n    // PROBABILISTIC SCORING (restored from 139M version)\n    // Model each feature as Gaussian with noise-dependent variance\n    \n    // Expected noise variances\n    double edge_noise_var = total_edges * eps * (1.0 - eps);\n    double edge_noise_std = sqrt(max(1.0, edge_noise_var));\n    \n    // Feature weights based on stability under noise\n    // Edge count: most stable (variance \u221d eps(1-eps))\n    // Degree features: moderately stable\n    // Triangles: only for very low eps\n    \n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        if (h.empty() || h.length() != (size_t)total_edges) {\n            cout << 0 << \"\\n\";\n            cout << flush;\n            continue;\n        }\n        \n        // Compute query features\n        int h_edges = countEdges(h);\n        vector<int> h_deg = computeDegreeSeq(h, N);\n        long long h_sum_sq = computeSumSqDegrees(h_deg);\n        int h_2paths = count2Paths(h_deg);\n        int h_triangles = (eps < 0.20) ? countTriangles(h, N) : 0;\n        int h_components = countConnectedComponents(h, N);\n        double h_degree_var = computeDegreeVariance(h_deg);\n        double h_entropy = computeDegreeEntropy(h_deg);\n        \n        int best_k = 0;\n        double best_log_prob = -1e18;\n        \n        for (int k = 0; k < M; k++) {\n            double log_prob = 0;\n            \n            // Edge count (Gaussian model) - ALWAYS most important\n            double edge_diff = h_edges - graphs[k].edge_count;\n            log_prob -= 0.5 * (edge_diff * edge_diff) / (edge_noise_var + 1);\n            \n            // Sum of squared degrees\n            double sq_diff = (double)(h_sum_sq - graphs[k].sum_sq_deg);\n            double sq_noise_var = N * N * N * eps * 0.3;\n            log_prob -= 0.5 * (sq_diff * sq_diff) / (sq_noise_var * sq_noise_var + 1);\n            \n            // 2-path count\n            double path_diff = h_2paths - graphs[k].two_paths;\n            double path_noise_var = total_edges * N * eps * 0.2;\n            log_prob -= 0.5 * (path_diff * path_diff) / (max(1.0, path_noise_var) + 1);\n            \n            // Degree variance\n            double var_diff = h_degree_var - graphs[k].degree_var;\n            double var_weight = (eps < 0.25) ? 50.0 : (eps < 0.35) ? 20.0 : 5.0;\n            log_prob -= var_weight * var_diff * var_diff;\n            \n            // Degree entropy\n            double ent_diff = h_entropy - graphs[k].degree_entropy;\n            double ent_weight = (eps < 0.20) ? 30.0 : (eps < 0.30) ? 10.0 : 2.0;\n            log_prob -= ent_weight * ent_diff * ent_diff;\n            \n            // Triangle count (only for low eps where it's reliable)\n            if (eps < 0.15 && graphs[k].triangles > 0) {\n                double tri_diff = h_triangles - graphs[k].triangles;\n                double tri_noise_var = graphs[k].triangles * eps * 3 + 1;\n                log_prob -= 0.5 * (tri_diff * tri_diff) / (tri_noise_var + 1);\n            }\n            \n            // Component count (discrete penalty)\n            if (h_components != graphs[k].components) {\n                log_prob -= 2.0;\n            }\n            \n            if (log_prob > best_log_prob) {\n                best_log_prob = log_prob;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nstruct Edge {\n    int id;\n    int u, v;\n    long long w;\n    double mid_x, mid_y;\n    double importance;\n};\n\nclass Solver {\npublic:\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<vector<pair<int, int>>> adj;\n    vector<pair<int, int>> coords;\n    vector<vector<long long>> base_dist;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    static constexpr long long INF = 1e18;\n    static constexpr long long UNREACHABLE = 1000000000;\n    \n    void compute_base_distances() {\n        base_dist.assign(N, vector<long long>(N, INF));\n        \n        for (int src = 0; src < N; src++) {\n            base_dist[src][src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > base_dist[src][u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < base_dist[src][v]) {\n                        base_dist[src][v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n    }\n    \n    void compute_edge_importance() {\n        vector<double> importance(M, 0);\n        \n        int samples = min(N, 30);\n        for (int i = 0; i < samples; i++) {\n            int src = i * N / samples;\n            vector<long long> dist(N, INF);\n            vector<int> parent_edge(N, -1);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        parent_edge[v] = edge_idx;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int v = 0; v < N; v++) {\n                if (v != src && parent_edge[v] != -1) {\n                    importance[parent_edge[v]] += 1.0;\n                }\n            }\n        }\n        \n        long long max_w = 1;\n        for (auto& e : edges) max_w = max(max_w, e.w);\n        \n        double center_x = 500, center_y = 500;\n        for (int i = 0; i < M; i++) {\n            double dist_from_center = hypot(edges[i].mid_x - center_x, edges[i].mid_y - center_y);\n            double weight_factor = 1.0 + (max_w - edges[i].w) / (double)max_w * 0.3;\n            double spatial_factor = 1.0 + dist_from_center / 1000.0;\n            edges[i].importance = importance[i] * weight_factor * spatial_factor;\n        }\n    }\n    \n    long long compute_day_frustration_fast(const vector<int>& edges_to_remove) {\n        if (edges_to_remove.empty()) return 0;\n        \n        vector<bool> edge_removed(M, false);\n        for (int idx : edges_to_remove) {\n            edge_removed[idx] = true;\n        }\n        \n        long long total_increase = 0;\n        int samples = min(N, 15);\n        \n        for (int src = 0; src < samples; src++) {\n            int src_idx = src * N / samples;\n            vector<long long> dist(N, INF);\n            dist[src_idx] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src_idx});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    if (edge_removed[edge_idx]) continue;\n                    \n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int dst = 0; dst < samples; dst++) {\n                if (src == dst) continue;\n                int dst_idx = dst * N / samples;\n                \n                long long d_k = (dist[dst_idx] >= INF) ? UNREACHABLE : dist[dst_idx];\n                long long d_base = (base_dist[src_idx][dst_idx] >= INF) ? UNREACHABLE : base_dist[src_idx][dst_idx];\n                \n                total_increase += max(0LL, d_k - d_base);\n            }\n        }\n        \n        double scale = (double)(N * (N - 1)) / (samples * (samples - 1));\n        return (long long)(total_increase * scale);\n    }\n    \n    vector<int> solve() {\n        start_time = chrono::steady_clock::now();\n        \n        compute_base_distances();\n        compute_edge_importance();\n        \n        // Sort edges by importance (descending)\n        vector<int> edge_order(M);\n        iota(edge_order.begin(), edge_order.end(), 0);\n        sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n            return edges[a].importance > edges[b].importance;\n        });\n        \n        // Initial assignment with spatial awareness\n        vector<int> assignment(M, -1);\n        vector<vector<int>> day_edges(D);\n        vector<double> day_center_x(D, 500), day_center_y(D, 500);\n        vector<long long> day_importance(D, 0);\n        \n        for (int edge_idx : edge_order) {\n            int best_day = 0;\n            double best_score = 1e18;\n            \n            for (int d = 0; d < D; d++) {\n                if ((int)day_edges[d].size() < K) {\n                    // Score based on importance balance and spatial spread\n                    double importance_score = day_importance[d];\n                    double spatial_score = 0;\n                    if (!day_edges[d].empty()) {\n                        spatial_score = hypot(edges[edge_idx].mid_x - day_center_x[d], \n                                            edges[edge_idx].mid_y - day_center_y[d]);\n                    }\n                    double score = importance_score * 0.7 - spatial_score * 0.3;\n                    \n                    if (score < best_score) {\n                        best_score = score;\n                        best_day = d;\n                    }\n                }\n            }\n            \n            assignment[edge_idx] = best_day + 1;\n            day_edges[best_day].push_back(edge_idx);\n            day_importance[best_day] += (long long)(edges[edge_idx].importance * 1000);\n            \n            // Update day center\n            int n = day_edges[best_day].size();\n            day_center_x[best_day] = (day_center_x[best_day] * (n-1) + edges[edge_idx].mid_x) / n;\n            day_center_y[best_day] = (day_center_y[best_day] * (n-1) + edges[edge_idx].mid_y) / n;\n        }\n        \n        // Compute initial day frustrations\n        vector<long long> day_frustration(D);\n        long long current_total = 0;\n        for (int d = 0; d < D; d++) {\n            day_frustration[d] = compute_day_frustration_fast(day_edges[d]);\n            current_total += day_frustration[d];\n        }\n        \n        long long best_total = current_total;\n        vector<int> best_assignment = assignment;\n        \n        // Aggressive local search with time budget\n        double time_limit = 5.3;\n        double temperature = 0.8;\n        int iteration = 0;\n        int no_improve_count = 0;\n        \n        vector<double> edge_selection_prob(M);\n        double total_importance = 0;\n        for (int i = 0; i < M; i++) {\n            edge_selection_prob[i] = edges[i].importance + 1.0;\n            total_importance += edge_selection_prob[i];\n        }\n        \n        while (no_improve_count < 50) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Select edge biased by importance\n            double r = uniform_real_distribution<>(0.0, total_importance)(rng);\n            int edge_idx = 0;\n            double cumsum = 0;\n            for (int i = 0; i < M; i++) {\n                cumsum += edge_selection_prob[i];\n                if (r <= cumsum) {\n                    edge_idx = i;\n                    break;\n                }\n            }\n            \n            int old_day = assignment[edge_idx] - 1;\n            int new_day = uniform_int_distribution<>(0, D - 1)(rng);\n            \n            if (new_day == old_day || (int)day_edges[new_day].size() >= K) {\n                continue;\n            }\n            \n            // Fast delta computation\n            vector<int> old_day_temp;\n            old_day_temp.reserve(day_edges[old_day].size());\n            for (int e : day_edges[old_day]) {\n                if (e != edge_idx) old_day_temp.push_back(e);\n            }\n            \n            vector<int> new_day_temp = day_edges[new_day];\n            new_day_temp.push_back(edge_idx);\n            \n            long long new_old = compute_day_frustration_fast(old_day_temp);\n            long long new_new = compute_day_frustration_fast(new_day_temp);\n            \n            long long delta = (new_old + new_new) - (day_frustration[old_day] + day_frustration[new_day]);\n            \n            double accept_prob = exp(-delta / (temperature * max(1LL, current_total / D) + 1));\n            \n            if (delta < 0 || uniform_real_distribution<>(0.0, 1.0)(rng) < accept_prob) {\n                assignment[edge_idx] = new_day + 1;\n                \n                auto it = find(day_edges[old_day].begin(), day_edges[old_day].end(), edge_idx);\n                if (it != day_edges[old_day].end()) day_edges[old_day].erase(it);\n                day_edges[new_day].push_back(edge_idx);\n                \n                day_frustration[old_day] = new_old;\n                day_frustration[new_day] = new_new;\n                \n                current_total += delta;\n                \n                if (current_total < best_total) {\n                    best_total = current_total;\n                    best_assignment = assignment;\n                    no_improve_count = 0;\n                } else {\n                    no_improve_count++;\n                }\n            } else {\n                no_improve_count++;\n            }\n            \n            iteration++;\n            temperature *= 0.9998;\n        }\n        \n        return best_assignment;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    Solver solver;\n    solver.N = N;\n    solver.M = M;\n    solver.D = D;\n    solver.K = K;\n    solver.rng.seed(42);\n    \n    solver.edges.resize(M);\n    solver.adj.resize(N);\n    solver.coords.resize(N);\n    \n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        solver.edges[i] = {i, u, v, (long long)w, 0, 0, 0};\n        solver.adj[u].push_back({v, i});\n        solver.adj[v].push_back({u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        int u = solver.edges[i].u;\n        int v = solver.edges[i].v;\n        solver.edges[i].mid_x = (solver.coords[u].first + solver.coords[v].first) / 2.0;\n        solver.edges[i].mid_y = (solver.coords[u].second + solver.coords[v].second) / 2.0;\n    }\n    \n    auto assignment = solver.solve();\n    \n    for (int i = 0; i < M; i++) {\n        cout << assignment[i] << (i == M - 1 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D;\n    cin >> D;\n    \n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; i++) cin >> f1[i];\n    for (int i = 0; i < D; i++) cin >> r1[i];\n    for (int i = 0; i < D; i++) cin >> f2[i];\n    for (int i = 0; i < D; i++) cin >> r2[i];\n    \n    // Compute valid positions\n    vector<vector<vector<bool>>> valid1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> valid2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[z][y][x] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Common positions - ALL will be shared blocks\n    vector<vector<vector<bool>>> common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                common[z][y][x] = valid1[z][y][x] && valid2[z][y][x];\n            }\n        }\n    }\n    \n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    int block_id = 1;\n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    // Track which positions are used\n    vector<vector<vector<bool>>> used1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> used2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // Step 1: ALL common positions are used as shared blocks\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x]) {\n                    used1[z][y][x] = true;\n                    used2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Step 2: For non-common positions, find MINIMUM cells to satisfy silhouettes\n    for (int z = 0; z < D; z++) {\n        // Arrangement 1 - non-common positions only\n        vector<int> need_x1, need_y1;\n        for (int x = 0; x < D; x++) {\n            if (f1[z][x] == '1') {\n                bool covered = false;\n                for (int y = 0; y < D; y++) {\n                    if (common[z][y][x]) { covered = true; break; }\n                }\n                if (!covered) need_x1.push_back(x);\n            }\n        }\n        for (int y = 0; y < D; y++) {\n            if (r1[z][y] == '1') {\n                bool covered = true;\n                for (int x = 0; x < D; x++) {\n                    if (common[z][y][x]) { covered = false; break; }\n                }\n                if (covered) need_y1.push_back(y);\n            }\n        }\n        \n        vector<bool> covered_x1(D, false), covered_y1(D, false);\n        \n        // Check what's already covered by common positions\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (common[z][y][x]) {\n                    if (f1[z][x] == '1') covered_x1[x] = true;\n                    if (r1[z][y] == '1') covered_y1[y] = true;\n                }\n            }\n        }\n        \n        // Cover remaining x with non-common positions\n        for (int x : need_x1) {\n            if (!covered_x1[x]) {\n                for (int y = 0; y < D; y++) {\n                    if (valid1[z][y][x] && !common[z][y][x]) {\n                        used1[z][y][x] = true;\n                        covered_x1[x] = true;\n                        if (r1[z][y] == '1') covered_y1[y] = true;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        // Cover remaining y with non-common positions\n        for (int y = 0; y < D; y++) {\n            if (r1[z][y] == '1' && !covered_y1[y]) {\n                for (int x = 0; x < D; x++) {\n                    if (valid1[z][y][x] && !common[z][y][x]) {\n                        used1[z][y][x] = true;\n                        covered_y1[y] = true;\n                        if (f1[z][x] == '1') covered_x1[x] = true;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        // Arrangement 2 - non-common positions only\n        vector<bool> covered_x2(D, false), covered_y2(D, false);\n        \n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (common[z][y][x]) {\n                    if (f2[z][x] == '1') covered_x2[x] = true;\n                    if (r2[z][y] == '1') covered_y2[y] = true;\n                }\n            }\n        }\n        \n        for (int x = 0; x < D; x++) {\n            if (f2[z][x] == '1' && !covered_x2[x]) {\n                for (int y = 0; y < D; y++) {\n                    if (valid2[z][y][x] && !common[z][y][x]) {\n                        used2[z][y][x] = true;\n                        covered_x2[x] = true;\n                        if (r2[z][y] == '1') covered_y2[y] = true;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        for (int y = 0; y < D; y++) {\n            if (r2[z][y] == '1' && !covered_y2[y]) {\n                for (int x = 0; x < D; x++) {\n                    if (valid2[z][y][x] && !common[z][y][x]) {\n                        used2[z][y][x] = true;\n                        covered_y2[y] = true;\n                        if (f2[z][x] == '1') covered_x2[x] = true;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Step 3: Assign connected components as blocks\n    // First: shared blocks (ALL common positions - 3D connected components)\n    vector<vector<vector<bool>>> visited_shared(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x] && !visited_shared[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited_shared[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                common[nz][ny][nx] && !visited_shared[nz][ny][nx]) {\n                                visited_shared[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Second: arrangement 1 only (3D connected components)\n    vector<vector<vector<bool>>> visited1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used1[z][y][x] && b1[z][y][x] == 0 && !visited1[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited1[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used1[nz][ny][nx] && b1[nz][ny][nx] == 0 && !visited1[nz][ny][nx]) {\n                                visited1[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Third: arrangement 2 only (3D connected components)\n    vector<vector<vector<bool>>> visited2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used2[z][y][x] && b2[z][y][x] == 0 && !visited2[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited2[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used2[nz][ny][nx] && b2[nz][ny][nx] == 0 && !visited2[nz][ny][nx]) {\n                                visited2[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    \n    // Output in correct order: x*D^2 + y*D + z\n    for (int i = 0; i < 2; i++) {\n        vector<int> output;\n        output.reserve(D * D * D);\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                    output.push_back(i == 0 ? b1[z][y][x] : b2[z][y][x]);\n                }\n            }\n        }\n        \n        for (int j = 0; j < (int)output.size(); j++) {\n            cout << output[j] << (j == (int)output.size() - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <numeric>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        return parent[x] == x ? x : parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        parent[y] = x;\n        return true;\n    }\n};\n\nlong long dist_ll(Point a, Point b) {\n    long long dx = a.x - b.x;\n    long long dy = a.y - b.y;\n    return round(sqrt(dx * dx + dy * dy));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    vector<Point> stations(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n    }\n    \n    vector<Point> residents(K);\n    for (int i = 0; i < K; i++) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n    \n    // Precompute distances from each resident to each station\n    vector<vector<long long>> resident_station_dist(K, vector<long long>(N));\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            resident_station_dist[k][i] = dist_ll(residents[k], stations[i]);\n        }\n    }\n    \n    // Build MST from station 0 for initial connectivity\n    vector<pair<long long, int>> mst_edges;\n    vector<Edge> sorted_edges = edges;\n    sort(sorted_edges.begin(), sorted_edges.end(), \n         [](const Edge& a, const Edge& b) { return a.w < b.w; });\n    \n    DSU dsu(N);\n    vector<int> edge_in_mst(M, 0);\n    long long mst_cost = 0;\n    int edges_added = 0;\n    \n    for (int i = 0; i < M && edges_added < N - 1; i++) {\n        int idx = -1;\n        for (int j = 0; j < M; j++) {\n            if (edge_in_mst[j]) continue;\n            if (edges[j].w == sorted_edges[i].w && \n                dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                idx = j;\n                break;\n            }\n        }\n        if (idx == -1) {\n            for (int j = 0; j < M; j++) {\n                if (edge_in_mst[j]) continue;\n                if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                    idx = j;\n                    break;\n                }\n            }\n        }\n        if (idx != -1) {\n            dsu.unite(edges[idx].u, edges[idx].v);\n            edge_in_mst[idx] = 1;\n            mst_cost += edges[idx].w;\n            edges_added++;\n        }\n    }\n    \n    // Find connected component from station 0\n    vector<int> reachable(N, 0);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (edge_in_mst[i]) {\n            adj[edges[i].u].push_back(edges[i].v);\n            adj[edges[i].v].push_back(edges[i].u);\n        }\n    }\n    \n    queue<int> q;\n    q.push(0);\n    reachable[0] = 1;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (!reachable[v]) {\n                reachable[v] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Assign residents to nearest reachable station\n    vector<long long> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        long long min_dist = 1e18;\n        int best_station = -1;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i]) {\n                if (resident_station_dist[k][i] < min_dist) {\n                    min_dist = resident_station_dist[k][i];\n                    best_station = i;\n                }\n            }\n        }\n        if (best_station != -1 && min_dist <= 5000) {\n            P[best_station] = max(P[best_station], min_dist);\n        }\n    }\n    \n    // Calculate initial cost\n    auto calc_cost = [&]() -> long long {\n        long long cost = 0;\n        for (int i = 0; i < N; i++) {\n            cost += P[i] * P[i];\n        }\n        for (int i = 0; i < M; i++) {\n            if (edge_in_mst[i]) {\n                cost += edges[i].w;\n            }\n        }\n        return cost;\n    };\n    \n    auto check_coverage = [&]() -> bool {\n        for (int k = 0; k < K; k++) {\n            bool covered = false;\n            for (int i = 0; i < N; i++) {\n                if (reachable[i] && resident_station_dist[k][i] <= P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n            if (!covered) return false;\n        }\n        return true;\n    };\n    \n    long long best_cost = calc_cost();\n    vector<int> best_edge_state = edge_in_mst;\n    vector<long long> best_P = P;\n    \n    // Try adding beneficial edges\n    mt19937 rng(42);\n    for (int iter = 0; iter < 500; iter++) {\n        vector<int> current_edge_state = best_edge_state;\n        vector<long long> current_P = best_P;\n        \n        // Recompute reachable\n        vector<int> cur_reachable(N, 0);\n        vector<vector<int>> cur_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (current_edge_state[i]) {\n                cur_adj[edges[i].u].push_back(edges[i].v);\n                cur_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> cq;\n        cq.push(0);\n        cur_reachable[0] = 1;\n        while (!cq.empty()) {\n            int u = cq.front(); cq.pop();\n            for (int v : cur_adj[u]) {\n                if (!cur_reachable[v]) {\n                    cur_reachable[v] = 1;\n                    cq.push(v);\n                }\n            }\n        }\n        \n        // Try adding a random edge\n        int edge_to_add = uniform_int_distribution<>(0, M-1)(rng);\n        if (!current_edge_state[edge_to_add]) {\n            current_edge_state[edge_to_add] = 1;\n            \n            // Recompute reachable\n            fill(cur_reachable.begin(), cur_reachable.end(), 0);\n            for (int i = 0; i < N; i++) cur_adj[i].clear();\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    cur_adj[edges[i].u].push_back(edges[i].v);\n                    cur_adj[edges[i].v].push_back(edges[i].u);\n                }\n            }\n            cq = queue<int>();\n            cq.push(0);\n            cur_reachable[0] = 1;\n            while (!cq.empty()) {\n                int u = cq.front(); cq.pop();\n                for (int v : cur_adj[u]) {\n                    if (!cur_reachable[v]) {\n                        cur_reachable[v] = 1;\n                        cq.push(v);\n                    }\n                }\n            }\n            \n            // Recalculate P\n            fill(current_P.begin(), current_P.end(), 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    current_P[best_station] = max(current_P[best_station], min_dist);\n                }\n            }\n            \n            // Calculate new cost\n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += current_P[i] * current_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            // Check if all residents covered\n            bool all_covered = true;\n            for (int k = 0; k < K; k++) {\n                bool covered = false;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i] && resident_station_dist[k][i] <= current_P[i]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    all_covered = false;\n                    break;\n                }\n            }\n            \n            if (all_covered && new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = current_edge_state;\n                best_P = current_P;\n            }\n        }\n    }\n    \n    // Try removing expensive edges if possible\n    vector<pair<long long, int>> edge_by_cost;\n    for (int i = 0; i < M; i++) {\n        if (best_edge_state[i]) {\n            edge_by_cost.push_back({edges[i].w, i});\n        }\n    }\n    sort(edge_by_cost.rbegin(), edge_by_cost.rend());\n    \n    for (auto& [w, idx] : edge_by_cost) {\n        vector<int> test_edge_state = best_edge_state;\n        test_edge_state[idx] = 0;\n        \n        // Check if still connected\n        vector<int> test_reachable(N, 0);\n        vector<vector<int>> test_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (test_edge_state[i]) {\n                test_adj[edges[i].u].push_back(edges[i].v);\n                test_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> tq;\n        tq.push(0);\n        test_reachable[0] = 1;\n        while (!tq.empty()) {\n            int u = tq.front(); tq.pop();\n            for (int v : test_adj[u]) {\n                if (!test_reachable[v]) {\n                    test_reachable[v] = 1;\n                    tq.push(v);\n                }\n            }\n        }\n        \n        // Check if all residents still coverable\n        bool all_coverable = true;\n        for (int k = 0; k < K; k++) {\n            bool can_cover = false;\n            for (int i = 0; i < N; i++) {\n                if (test_reachable[i] && resident_station_dist[k][i] <= 5000) {\n                    can_cover = true;\n                    break;\n                }\n            }\n            if (!can_cover) {\n                all_coverable = false;\n                break;\n            }\n        }\n        \n        if (all_coverable) {\n            vector<long long> test_P(N, 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (test_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    test_P[best_station] = max(test_P[best_station], min_dist);\n                }\n            }\n            \n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += test_P[i] * test_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (test_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = test_edge_state;\n                best_P = test_P;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << best_P[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << best_edge_state[i] << (i == M-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cstring>\n\nusing namespace std;\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\nint N = 30;\nint grid[30][30];\nPoint pos[465]; \n\nvector<tuple<int, int, int, int>> ops;\n\n// Directions for neighbors\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid swap_balls(int x1, int y1, int x2, int y2) {\n    int v1 = grid[x1][y1];\n    int v2 = grid[x2][y2];\n    grid[x1][y1] = v2;\n    grid[x2][y2] = v1;\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n}\n\n// Anchor marks cells in the current row that already contain a correct value\nbool anchor[30][30];\n\n// BFS to find closest needed value and move it to (tr, tc)\nint find_and_move(int tr, int tc, int val_min, int val_max) {\n    Point target = {tr, tc};\n    \n    static int dist[30][30];\n    static Point parent[30][30];\n    static bool visited[30][30];\n    \n    // Reset visited\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            visited[i][j] = false;\n        }\n    }\n    \n    queue<Point> q;\n    q.push(target);\n    visited[tr][tc] = true;\n    dist[tr][tc] = 0;\n    parent[tr][tc] = {-1, -1};\n    \n    Point best_pos = {-1, -1};\n    \n    while(!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n        \n        // Check if this cell has a needed value\n        int val = grid[curr.x][curr.y];\n        if (val >= val_min && val <= val_max) {\n            best_pos = curr;\n            break; \n        }\n        \n        // Expand neighbors\n        for(int i=0; i<6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (is_valid(nx, ny)) {\n                // Obstacle checks\n                if (nx < tr) continue; // Rows above are fixed\n                if (nx == tr && ny < tc) continue; // Cols left in current row are fixed\n                if (nx == tr && anchor[nx][ny]) continue; // Anchors in current row are fixed\n                \n                if (!visited[nx][ny]) {\n                    visited[nx][ny] = true;\n                    dist[nx][ny] = dist[curr.x][curr.y] + 1;\n                    parent[nx][ny] = curr;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n    \n    if (best_pos.x == -1) return -1;\n    \n    // Reconstruct path from best_pos to target\n    vector<Point> path;\n    Point curr = best_pos;\n    while (true) {\n        path.push_back(curr);\n        if (curr == target) break;\n        curr = parent[curr.x][curr.y];\n    }\n    \n    // Execute swaps: move value from path[0] to path.back()\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        swap_balls(path[i].x, path[i].y, path[i+1].x, path[i+1].y);\n    }\n    \n    return grid[tr][tc];\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> grid[i][j];\n            pos[grid[i][j]] = {i, j};\n        }\n    }\n    \n    ops.reserve(10000);\n    \n    // Process each row from top to bottom\n    for (int r = 0; r < N; ++r) {\n        int row_min = r * (r + 1) / 2;\n        int row_max = (r + 1) * (r + 2) / 2 - 1;\n        \n        // Identify anchors: cells in Row r that already have a value belonging to Row r\n        memset(anchor, 0, sizeof(anchor));\n        for (int c = 0; c <= r; ++c) {\n            if (grid[r][c] >= row_min && grid[r][c] <= row_max) {\n                anchor[r][c] = true;\n            }\n        }\n        \n        // Fill row r positions 0 to r\n        for (int c = 0; c <= r; ++c) {\n            // If this cell is an anchor, it already has a valid value for this row.\n            // We keep it in place to minimize swaps.\n            if (anchor[r][c]) continue;\n            \n            // Otherwise, find the closest value belonging to this row from the free region\n            // and move it here.\n            int val = find_and_move(r, c, row_min, row_max);\n            if (val == -1) {\n                // Should not happen as there are exactly enough values\n                return 1;\n            }\n            // After move, grid[r][c] contains a value in [row_min, row_max].\n            // It is effectively fixed for subsequent steps in this row (handled by ny < tc check).\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \" << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0;\nconst int ENTRANCE_J = 4;\n\nstruct Container {\n    int id;\n    int pi, pj;\n    bool retrieved;\n};\n\n// Check if a specific cell is reachable from entrance through empty cells\nbool isCellReachable(int ti, int tj, const vector<vector<int>>& cellContainer,\n                     const vector<vector<bool>>& obstacle) {\n    if (obstacle[ti][tj]) return false;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) return true;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && cellContainer[ni][nj] == -1) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return false;\n}\n\n// Check if all placed containers are reachable\nbool allContainersReachable(const vector<Container>& containers,\n                            const vector<vector<int>>& cellContainer,\n                            const vector<vector<bool>>& obstacle) {\n    for (const auto& c : containers) {\n        if (!c.retrieved && !isCellReachable(c.pi, c.pj, cellContainer, obstacle)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Get all accessible containers with their info\nvector<pair<int, int>> getAccessibleContainers(const vector<Container>& containers,\n                                                const vector<vector<int>>& cellContainer,\n                                                const vector<vector<bool>>& obstacle) {\n    vector<pair<int, int>> accessible; // (container_index, id)\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj]) {\n                visited[ni][nj] = true;\n                \n                int containerIdx = cellContainer[ni][nj];\n                \n                if (containerIdx == -1) {\n                    // Empty cell - can traverse through\n                    q.push({ni, nj});\n                } else {\n                    // Cell has a container - can retrieve but not traverse through\n                    if (!containers[containerIdx].retrieved) {\n                        accessible.push_back({containerIdx, containers[containerIdx].id});\n                    }\n                }\n            }\n        }\n    }\n    return accessible;\n}\n\n// Get all reachable empty cells from entrance\nvector<pair<int,int>> getReachableEmptyCells(const vector<vector<int>>& cellContainer,\n                                              const vector<vector<bool>>& obstacle,\n                                              const vector<vector<int>>& dist) {\n    vector<pair<int,int>> result;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && cellContainer[ni][nj] == -1) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n                result.push_back({ni, nj});\n            }\n        }\n    }\n    \n    // Sort by distance (farthest first)\n    sort(result.begin(), result.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        return dist[a.first][a.second] > dist[b.first][b.second];\n    });\n    \n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    int D_val;\n    cin >> D_val >> N;\n    \n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n    \n    // Compute BFS distance from entrance for all cells\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    dist[ENTRANCE_I][ENTRANCE_J] = 0;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                dist[ni][nj] == -1 && !obstacle[ni][nj]) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Track which cells are occupied (-1 = empty, otherwise container index)\n    vector<vector<int>> cellContainer(D, vector<int>(D, -1));\n    \n    vector<Container> containers;\n    int totalContainers = D * D - 1 - N;\n    \n    // Storage phase\n    for (int d = 0; d < totalContainers; d++) {\n        int t;\n        cin >> t;\n        \n        // Get all reachable empty cells (sorted farthest first)\n        auto reachableCells = getReachableEmptyCells(cellContainer, obstacle, dist);\n        \n        int bestI = -1, bestJ = -1;\n        \n        // Try each reachable cell, starting from farthest\n        for (auto& [ni, nj] : reachableCells) {\n            // Temporarily place container here\n            cellContainer[ni][nj] = -2; // Mark as temporarily occupied\n            \n            // Check if all existing containers remain reachable\n            bool allReachable = true;\n            for (const auto& c : containers) {\n                if (!isCellReachable(c.pi, c.pj, cellContainer, obstacle)) {\n                    allReachable = false;\n                    break;\n                }\n            }\n            \n            // Restore\n            cellContainer[ni][nj] = -1;\n            \n            if (allReachable) {\n                bestI = ni;\n                bestJ = nj;\n                break; // Take the farthest valid cell\n            }\n        }\n        \n        // Fallback: if no cell keeps all containers reachable, just take farthest reachable\n        if (bestI == -1 && !reachableCells.empty()) {\n            bestI = reachableCells[0].first;\n            bestJ = reachableCells[0].second;\n        }\n        \n        if (bestI == -1) {\n            // Last resort: any empty non-obstacle cell\n            for (int i = 0; i < D; i++) {\n                for (int j = 0; j < D; j++) {\n                    if (cellContainer[i][j] == -1 && !obstacle[i][j] && \n                        !(i == ENTRANCE_I && j == ENTRANCE_J)) {\n                        bestI = i;\n                        bestJ = j;\n                        break;\n                    }\n                }\n                if (bestI != -1) break;\n            }\n        }\n        \n        int containerIdx = containers.size();\n        containers.push_back({t, bestI, bestJ, false});\n        cellContainer[bestI][bestJ] = containerIdx;\n        cout << bestI << \" \" << bestJ << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval phase - pick lowest ID accessible container\n    vector<pair<int,int>> retrievalOrder;\n    \n    for (int step = 0; step < totalContainers; step++) {\n        auto accessible = getAccessibleContainers(containers, cellContainer, obstacle);\n        \n        if (accessible.empty()) {\n            cerr << \"Error: No accessible container found at step \" << step << endl;\n            return 1;\n        }\n        \n        // Sort by ID and pick lowest\n        sort(accessible.begin(), accessible.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.second < b.second;\n        });\n        \n        int bestIdx = accessible[0].first;\n        \n        containers[bestIdx].retrieved = true;\n        int ri = containers[bestIdx].pi;\n        int rj = containers[bestIdx].pj;\n        cellContainer[ri][rj] = -1; // Mark as empty now\n        retrievalOrder.push_back({ri, rj});\n    }\n    \n    // Output retrieval order\n    for (auto& [qi, qj] : retrievalOrder) {\n        cout << qi << \" \" << qj << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    // Use a 2D vector to store the grid. \n    // n=50 is small, so memory usage is negligible.\n    vector<vector<int>> grid(n, vector<int>(n));\n\n    // Read the input grid\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    // Output the grid exactly as is.\n    // Reasoning:\n    // 1. The input constraints state 1 <= c_{i,j} <= m, so there are no 0s in the input.\n    // 2. The score is (number of 0s) + 1. Since input has 0 zeros, Score = 1.\n    // 3. Score 1 is the theoretical minimum (count cannot be negative).\n    // 4. The input is guaranteed to satisfy connectivity for colors 1..m.\n    // 5. Color 0 connectivity is satisfied via the \"outside\" region (as per problem note).\n    // 6. Adjacencies are preserved because the map is identical.\n    // Thus, echoing the input is the optimal and safest strategy.\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 <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Elo-style ratings for relative weight estimation\n    vector<double> rating(N, 1000.0);\n    vector<int> comparison_count(N, 0);\n    \n    mt19937_64 rng(42);\n    \n    int queries_used = 0;\n    \n    auto update_elo = [&](int i, int j, int result) {\n        const double K = 25.0;\n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        double actual_i, actual_j;\n        if (result < 0) {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result > 0) {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else {\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n    };\n    \n    // Phase 1: Generate all pairs and shuffle\n    vector<pair<int, int>> all_pairs;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            all_pairs.push_back({i, j});\n        }\n    }\n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    \n    // Execute comparisons - MUST complete exactly Q queries\n    int pair_idx = 0;\n    while (queries_used < Q) {\n        int i, j;\n        \n        if (pair_idx < (int)all_pairs.size()) {\n            i = all_pairs[pair_idx].first;\n            j = all_pairs[pair_idx].second;\n            pair_idx++;\n        } else {\n            // Ran out of unique pairs, use random pairs\n            i = rng() % N;\n            j = rng() % N;\n            if (i == j) j = (j + 1) % N;\n        }\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        comparison_count[i]++;\n        comparison_count[j]++;\n        \n        int cmp_result = 0;\n        if (result == \"<\") cmp_result = -1;\n        else if (result == \">\") cmp_result = 1;\n        \n        update_elo(i, j, cmp_result);\n    }\n    \n    // Phase 2: Convert ratings to weights\n    vector<double> weight(N);\n    double min_rating = *min_element(rating.begin(), rating.end());\n    double max_rating = *max_element(rating.begin(), rating.end());\n    double rating_range = max(1.0, max_rating - min_rating);\n    \n    for (int i = 0; i < N; i++) {\n        double normalized = (rating[i] - min_rating) / rating_range;\n        weight[i] = exp(normalized * 5.0);\n    }\n    \n    // Phase 3: Multi-way partitioning\n    // Sort items by weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return weight[a] > weight[b];\n    });\n    \n    // Greedy assignment: heaviest items to lightest groups\n    vector<double> group_weight(D, 0.0);\n    vector<int> assignment(N, 0);\n    vector<vector<int>> groups(D);\n    \n    for (int idx : indices) {\n        int best_group = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] < group_weight[best_group]) {\n                best_group = g;\n            }\n        }\n        assignment[idx] = best_group;\n        group_weight[best_group] += weight[idx];\n        groups[best_group].push_back(idx);\n    }\n    \n    // Phase 4: Local search optimization (limited iterations for speed)\n    auto calculate_variance = [&]() -> double {\n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        double variance = 0;\n        for (int g = 0; g < D; g++) {\n            variance += (group_weight[g] - mean) * (group_weight[g] - mean);\n        }\n        return variance;\n    };\n    \n    int max_iterations = 1000;\n    for (int iter = 0; iter < max_iterations; iter++) {\n        bool improved = false;\n        \n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        // Find heaviest and lightest groups\n        int heaviest_g = 0, lightest_g = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] > group_weight[heaviest_g]) heaviest_g = g;\n            if (group_weight[g] < group_weight[lightest_g]) lightest_g = g;\n        }\n        \n        if (heaviest_g == lightest_g) break;\n        \n        // Try moving item from heaviest to lightest\n        for (int i : groups[heaviest_g]) {\n            double new_w_h = group_weight[heaviest_g] - weight[i];\n            double new_w_l = group_weight[lightest_g] + weight[i];\n            \n            double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n            double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                (new_w_l - mean) * (new_w_l - mean);\n            \n            if (new_contrib < old_contrib - 1e-9) {\n                assignment[i] = lightest_g;\n                \n                auto it = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                groups[heaviest_g].erase(it);\n                groups[lightest_g].push_back(i);\n                \n                group_weight[heaviest_g] = new_w_h;\n                group_weight[lightest_g] = new_w_l;\n                \n                improved = true;\n                break;\n            }\n        }\n        \n        // Try swapping items\n        if (!improved && !groups[heaviest_g].empty() && !groups[lightest_g].empty()) {\n            for (int i : groups[heaviest_g]) {\n                for (int j : groups[lightest_g]) {\n                    double new_w_h = group_weight[heaviest_g] - weight[i] + weight[j];\n                    double new_w_l = group_weight[lightest_g] - weight[j] + weight[i];\n                    \n                    double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                        (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n                    double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                        (new_w_l - mean) * (new_w_l - mean);\n                    \n                    if (new_contrib < old_contrib - 1e-9) {\n                        assignment[i] = lightest_g;\n                        assignment[j] = heaviest_g;\n                        \n                        auto it_i = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                        auto it_j = find(groups[lightest_g].begin(), groups[lightest_g].end(), j);\n                        *it_i = j;\n                        *it_j = i;\n                        \n                        group_weight[heaviest_g] = new_w_h;\n                        group_weight[lightest_g] = new_w_l;\n                        \n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Validate all assignments are in valid range\n    for (int i = 0; i < N; i++) {\n        if (assignment[i] < 0) assignment[i] = 0;\n        if (assignment[i] >= D) assignment[i] = D - 1;\n    }\n    \n    // Output 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\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    \n    int bps = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<int> box_stack(n + 1);\n    vector<int> box_height(n + 1);\n    vector<bool> removed(n + 1, false);\n    \n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < bps; j++) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            box_stack[box] = i;\n            box_height[box] = j;\n        }\n    }\n    \n    vector<pair<int, int>> ops;\n    \n    auto update_positions = [&](int s) {\n        for (size_t i = 0; i < stacks[s].size(); i++) {\n            int b = stacks[s][i];\n            box_stack[b] = s;\n            box_height[b] = (int)i;\n        }\n    };\n    \n    // Estimate how many times a box will need to be moved before access\n    auto estimate_rehandles = [&](int box, int dest_stack, int current_target) -> int {\n        if (removed[box] || box <= current_target) return 0;\n        \n        int access_time = box - current_target;\n        int dest_size = (int)stacks[dest_stack].size();\n        \n        // Count boxes in dest stack that will be accessed before this box\n        int blocking = 0;\n        for (int b : stacks[dest_stack]) {\n            if (!removed[b] && b > current_target && b < box) {\n                blocking++;\n            }\n        }\n        \n        // Each blocking box means one extra move\n        return blocking;\n    };\n    \n    auto find_best_destination = [&](int exclude_stack, const vector<int>& moving_boxes, int current_target) -> int {\n        int best = -1;\n        long long best_score = -1000000000000LL;\n        \n        int current_empty = 0;\n        for (int i = 0; i < m; i++) {\n            if (stacks[i].empty()) current_empty++;\n        }\n        \n        for (int d = 0; d < m; d++) {\n            if (d == exclude_stack) continue;\n            \n            long long score = 0;\n            int dest_size = (int)stacks[d].size();\n            \n            // === CRITICAL: Empty stacks are extremely valuable ===\n            if (stacks[d].empty()) {\n                score += 50000000;\n                \n                // Preserve at least 1-2 empty stacks if possible\n                if (current_empty <= 2) {\n                    score -= 20000000;\n                }\n            }\n            \n            // === CRITICAL: Block detection for future targets (50 lookahead) ===\n            for (int f = current_target + 1; f <= min(current_target + 50, n); f++) {\n                if (removed[f]) continue;\n                if (box_stack[f] == d && box_height[f] >= dest_size) {\n                    int dist = f - current_target;\n                    // Closer = much heavier penalty\n                    score -= (long long)(8000000 - dist * 150000);\n                }\n            }\n            \n            // === Score moving boxes by access time ===\n            int soon_count = 0;\n            int total_rehandles = 0;\n            \n            for (int b : moving_boxes) {\n                if (removed[b]) continue;\n                \n                int access_time = b - current_target;\n                \n                if (access_time <= 5) {\n                    score -= 1000000;  // Very soon - expensive to bury\n                    soon_count++;\n                } else if (access_time <= 15) {\n                    score -= 400000;   // Soon\n                } else if (access_time <= 30) {\n                    score += 15000;    // Medium\n                } else if (access_time <= 60) {\n                    score += 30000;    // Long\n                } else {\n                    score += 50000;    // Very long - good for grouping\n                }\n                \n                // Estimate re-handling cost\n                total_rehandles += estimate_rehandles(b, d, current_target);\n            }\n            \n            // Penalty for estimated re-handling\n            score -= (long long)total_rehandles * 100000;\n            \n            // If we have soon boxes, STRONGLY prefer empty stack\n            if (soon_count > 0) {\n                if (stacks[d].empty()) {\n                    score += 5000000;\n                } else {\n                    score -= 2000000;\n                }\n            }\n            \n            // === Destination top box analysis ===\n            if (!stacks[d].empty()) {\n                int dest_top = stacks[d].back();\n                if (dest_top > current_target + 100) {\n                    score += 100000;\n                } else if (dest_top > current_target + 50) {\n                    score += 50000;\n                } else if (dest_top > current_target + 20) {\n                    score += 10000;\n                } else if (dest_top > current_target) {\n                    score -= 150000;\n                } else {\n                    score -= 800000;\n                }\n            } else {\n                // Empty stack - check if moving boxes have good access time spread\n                int min_access = n, max_access = 0;\n                for (int b : moving_boxes) {\n                    if (!removed[b]) {\n                        int access = b - current_target;\n                        min_access = min(min_access, access);\n                        max_access = max(max_access, access);\n                    }\n                }\n                if (max_access - min_access < 50) {\n                    score += 150000;  // Good grouping - similar access times\n                }\n            }\n            \n            // === Stack balance ===\n            score -= (long long)stacks[d].size() * 8000;\n            \n            // Bonus for filling smaller stacks\n            int min_nonempty = n + 1;\n            for (int i = 0; i < m; i++) {\n                if (i != exclude_stack && !stacks[i].empty()) {\n                    min_nonempty = min(min_nonempty, (int)stacks[i].size());\n                }\n            }\n            if (min_nonempty <= n && stacks[d].size() == (size_t)min_nonempty) {\n                score += 40000;\n            }\n            \n            // === Maintain workspace (softer penalties) ===\n            int would_be_empty = current_empty - (stacks[d].empty() ? 1 : 0);\n            if (would_be_empty >= 2) {\n                score += 20000;\n            } else if (would_be_empty == 0) {\n                score -= 50000;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best = d;\n            }\n        }\n        \n        if (best == -1) {\n            for (int d = 0; d < m; d++) {\n                if (d != exclude_stack) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n        \n        return best;\n    };\n    \n    for (int target = 1; target <= n; target++) {\n        if (removed[target]) continue;\n        \n        int s = box_stack[target];\n        int h = box_height[target];\n        int top = (int)stacks[s].size() - 1;\n        \n        if (h == top) {\n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        } else {\n            vector<int> moving_boxes;\n            for (int i = h + 1; i <= top; i++) {\n                moving_boxes.push_back(stacks[s][i]);\n            }\n            \n            int dest = find_best_destination(s, moving_boxes, target);\n            \n            int move_box = moving_boxes[0];\n            ops.push_back({move_box, dest + 1});\n            \n            stacks[s].resize(h + 1);\n            update_positions(s);\n            \n            for (int b : moving_boxes) {\n                stacks[dest].push_back(b);\n            }\n            update_positions(dest);\n            \n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        }\n    }\n    \n    for (const auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    vector<vector<int>> d(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    const int DI[] = {-1, 0, 1, 0};\n    const int DJ[] = {0, 1, 0, -1};\n    const char DIR[] = {'U', 'R', 'D', 'L'};\n    \n    // Check if move is valid (no wall)\n    auto can_move = [&](int i, int j, int dir) -> bool {\n        int ni = i + DI[dir], nj = j + DJ[dir];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        \n        if (dir == 0 && i > 0 && h[i-1][j] == '1') return false;\n        if (dir == 1 && v[i][j] == '1') return false;\n        if (dir == 2 && h[i][j] == '1') return false;\n        if (dir == 3 && j > 0 && v[i][j-1] == '1') return false;\n        \n        return true;\n    };\n    \n    // BFS to find shortest path from (si,sj) to (ti,tj)\n    auto find_path = [&](int si, int sj, int ti, int tj) -> string {\n        if (si == ti && sj == tj) return \"\";\n        \n        vector<vector<int>> bd(N, vector<int>(N, -1));\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n        vector<vector<int>> pdir(N, vector<int>(N, -1));\n        queue<pair<int,int>> bq;\n        \n        bd[si][sj] = 0;\n        bq.push({si, sj});\n        \n        while (!bq.empty()) {\n            auto [i, j] = bq.front();\n            bq.pop();\n            \n            if (i == ti && j == tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (can_move(i, j, dir)) {\n                    int ni = i + DI[dir], nj = j + DJ[dir];\n                    if (bd[ni][nj] == -1) {\n                        bd[ni][nj] = bd[i][j] + 1;\n                        parent[ni][nj] = {i, j};\n                        pdir[ni][nj] = dir;\n                        bq.push({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (bd[ti][tj] == -1) return \"\";\n        \n        string path = \"\";\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path += DIR[pdir[ci][cj]];\n            auto [pi, pj] = parent[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    // Create priority list of squares (higher d = higher priority for revisits)\n    vector<tuple<int, int, int>> squares;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            squares.push_back({d[i][j], i, j});\n        }\n    }\n    sort(squares.rbegin(), squares.rend());\n    \n    // DFS to create initial route that visits all squares and returns to (0,0)\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string route = \"\";\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        // Sort neighbors by d value (visit high-d squares first in spanning tree)\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            if (can_move(i, j, dir)) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        \n        for (auto [val, dir] : neighbors) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            route += DIR[dir];\n            dfs(ni, nj);\n            // Return: opposite direction - this ensures we return to (i,j)\n            int opp_dir = (dir + 2) % 4;\n            route += DIR[opp_dir];\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Verify the route ends at (0,0)\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    // If not at (0,0), add return path\n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        route += back;\n    }\n    \n    // Now optimize: add revisits to high-priority squares\n    // Strategy: insert round-trips to high-d squares at strategic points\n    const int MAX_LEN = 100000;\n    \n    if ((int)route.length() < MAX_LEN - 1000) {\n        // Calculate current visit counts\n        vector<vector<int>> visit_count(N, vector<int>(N, 0));\n        int pi = 0, pj = 0;\n        visit_count[0][0]++;\n        \n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            visit_count[pi][pj]++;\n        }\n        \n        // Try to add revisits to high-priority squares\n        // We'll insert round-trips at positions where we're close to target squares\n        string optimized = route;\n        \n        // Find all positions in the route\n        vector<pair<int,int>> positions;\n        positions.push_back({0, 0});\n        pi = 0; pj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            positions.push_back({pi, pj});\n        }\n        \n        // Add revisits to top priority squares\n        for (auto [val, ti, tj] : squares) {\n            if ((int)optimized.length() >= MAX_LEN - 500) break;\n            \n            // Find the closest position in route to this square\n            int best_idx = -1;\n            int best_dist = N * N;\n            for (int idx = 0; idx < (int)positions.size(); idx++) {\n                int dist = abs(positions[idx].first - ti) + abs(positions[idx].second - tj);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_idx = idx;\n                }\n            }\n            \n            if (best_idx >= 0 && best_dist < N) {\n                // Check if we should add a revisit\n                int current_visits = visit_count[ti][tj];\n                int target_visits = max(2, (int)(val * optimized.length() / 50000));\n                \n                if (current_visits < target_visits) {\n                    // Insert a round-trip to (ti, tj) at position best_idx\n                    int pi_pos = positions[best_idx].first;\n                    int pj_pos = positions[best_idx].second;\n                    \n                    string to_target = find_path(pi_pos, pj_pos, ti, tj);\n                    string back = find_path(ti, tj, pi_pos, pj_pos);\n                    \n                    if (!to_target.empty() && !back.empty() && \n                        (int)optimized.length() + (int)to_target.length() + (int)back.length() < MAX_LEN - 100) {\n                        // Insert at position best_idx\n                        string new_route = optimized.substr(0, best_idx);\n                        new_route += to_target + back;\n                        new_route += optimized.substr(best_idx);\n                        optimized = new_route;\n                        visit_count[ti][tj]++;\n                        \n                        // Update positions (simplified - just add the detour positions)\n                        // This is approximate but should work for validation\n                    }\n                }\n            }\n        }\n        \n        route = optimized;\n    }\n    \n    // Final validation: ensure route ends at (0,0)\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n            route += back;\n        } else {\n            // Truncate and add return path\n            route = route.substr(0, MAX_LEN - (int)back.length() - 10);\n            route += back;\n        }\n    }\n    \n    // Final validation: ensure all squares visited\n    vector<vector<bool>> final_visited(N, vector<bool>(N, false));\n    int vi = 0, vj = 0;\n    final_visited[0][0] = true;\n    \n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                vi += DI[dir];\n                vj += DJ[dir];\n                break;\n            }\n        }\n        if (vi < 0 || vi >= N || vj < 0 || vj >= N) {\n            // Invalid move - this shouldn't happen\n            cerr << \"Invalid move detected!\" << endl;\n            return 1;\n        }\n        final_visited[vi][vj] = true;\n    }\n    \n    // If any square not visited, we have a problem - but DFS should have visited all\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!final_visited[i][j]) {\n                cerr << \"Square (\" << i << \",\" << j << \") not visited!\" << endl;\n                // Try to add it if possible\n                if ((int)route.length() < MAX_LEN - 500) {\n                    string to_sq = find_path(0, 0, i, j);\n                    string back = find_path(i, j, 0, 0);\n                    if (!to_sq.empty() && !back.empty()) {\n                        route = to_sq + back + route;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure length constraint\n    if ((int)route.length() > MAX_LEN) {\n        route = route.substr(0, MAX_LEN);\n        // Re-validate end position\n        ci = 0; cj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n        }\n        if (ci != 0 || cj != 0) {\n            string back = find_path(ci, cj, 0, 0);\n            if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n                route += back;\n            }\n        }\n    }\n    \n    // One final check\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        // This is a critical error - truncate to make it valid\n        cerr << \"Warning: Route does not end at (0,0), truncating\" << endl;\n        // Find the last position that was at (0,0)\n        int last_zero = 0;\n        ci = 0; cj = 0;\n        for (int idx = 0; idx < (int)route.length(); idx++) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == route[idx]) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n            if (ci == 0 && cj == 0) {\n                last_zero = idx + 1;\n            }\n        }\n        route = route.substr(0, last_zero);\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<string> grid;\nvector<string> targets;\nvector<vector<pair<int, int>>> char_positions;\nvector<vector<int>> overlap;\n\ninline int dist(pair<int, int> p1, pair<int, int> p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\nint calc_overlap(const string& a, const string& b) {\n    int max_ov = 0;\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = 1; len <= max_len; len++) {\n        if (a.substr(a.size() - len) == b.substr(0, len)) {\n            max_ov = len;\n        }\n    }\n    return max_ov;\n}\n\n// Build solution with look-ahead position selection\npair<string, vector<pair<int, int>>> build_solution(const vector<int>& order, int& total_cost, int lookahead = 2) {\n    string S;\n    S.reserve(1000);\n    vector<pair<int, int>> positions;\n    positions.reserve(5000);\n    pair<int, int> cur_pos = {si, sj};\n    total_cost = 0;\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        int overlap_len = 0;\n        \n        if ((int)S.size() >= 4) {\n            for (int len = min(5, (int)S.size()); len >= 1; len--) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    if (S[S.size() - len + k] != t[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        for (int i = overlap_len; i < 5; i++) {\n            char c = t[i];\n            int c_idx = c - 'A';\n            const auto& positions_c = char_positions[c_idx];\n            \n            pair<int, int> best_pos = positions_c[0];\n            double best_score = 1e9;\n            \n            // Collect next characters for look-ahead\n            vector<int> next_chars;\n            int temp_i = i + 1;\n            int temp_idx = idx;\n            while ((int)next_chars.size() < lookahead) {\n                if (temp_i < 5) {\n                    next_chars.push_back(targets[temp_idx][temp_i] - 'A');\n                    temp_i++;\n                } else {\n                    bool found = false;\n                    for (int k = idx + 1; k < (int)order.size() && (int)next_chars.size() < lookahead; k++) {\n                        next_chars.push_back(targets[order[k]][0] - 'A');\n                        found = true;\n                        break;\n                    }\n                    if (!found) break;\n                }\n            }\n            \n            for (auto& pos : positions_c) {\n                double score = dist(cur_pos, pos);\n                \n                pair<int, int> prev_pos = pos;\n                for (size_t k = 0; k < next_chars.size(); k++) {\n                    int next_c = next_chars[k];\n                    int min_d = INT_MAX;\n                    pair<int, int> best_next = char_positions[next_c][0];\n                    for (auto& np : char_positions[next_c]) {\n                        int d = dist(prev_pos, np);\n                        if (d < min_d) {\n                            min_d = d;\n                            best_next = np;\n                        }\n                    }\n                    score += min_d * (1.0 / (k + 1));\n                    prev_pos = best_next;\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_pos = pos;\n                }\n            }\n            \n            total_cost += dist(cur_pos, best_pos) + 1;\n            positions.push_back(best_pos);\n            S += c;\n            cur_pos = best_pos;\n        }\n    }\n    \n    return {S, positions};\n}\n\ninline bool check_coverage(const string& S) {\n    for (int i = 0; i < M; i++) {\n        if (S.find(targets[i]) == string::npos) return false;\n    }\n    return true;\n}\n\nvector<int> build_greedy_order(mt19937& rng, bool randomize = false, int start_override = -1) {\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    \n    uniform_int_distribution<int> dist_int(0, M - 1);\n    int start = (start_override >= 0) ? (start_override % M) : (randomize ? dist_int(rng) : 0);\n    \n    order.push_back(start);\n    used[start] = true;\n    \n    for (int step = 1; step < M; step++) {\n        int last = order.back();\n        vector<pair<int, int>> candidates;\n        candidates.reserve(M - step);\n        \n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                candidates.push_back({overlap[last][i], i});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first > b.first;\n        });\n        \n        int top_k = randomize ? min((int)candidates.size(), 30) : 1;\n        uniform_int_distribution<int> pick_dist(0, top_k - 1);\n        int pick_idx = randomize ? pick_dist(rng) : 0;\n        int best_next = candidates[pick_idx].second;\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\n// Weighted swap candidate selection based on overlap deficit\nint select_swap_position(const vector<int>& order, mt19937& rng) {\n    uniform_int_distribution<int> uniform_dist(0, M - 2);\n    \n    // 50% chance: weighted by low overlap\n    // 50% chance: uniform random\n    if (rng() % 2 == 0) {\n        vector<pair<int, int>> weighted;\n        weighted.reserve(M - 1);\n        for (int i = 0; i < M - 1; i++) {\n            int weight = 5 - overlap[order[i]][order[i + 1]];  // Lower overlap = higher weight\n            weight = max(1, weight);\n            for (int w = 0; w < weight; w++) {\n                weighted.push_back({i, weight});\n            }\n        }\n        if (!weighted.empty()) {\n            uniform_int_distribution<int> w_dist(0, weighted.size() - 1);\n            return weighted[w_dist(rng)].first;\n        }\n    }\n    return uniform_dist(rng);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    grid.resize(N);\n    char_positions.resize(26);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    overlap.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) {\n                overlap[i][j] = calc_overlap(targets[i], targets[j]);\n            }\n        }\n    }\n    \n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> best_order;\n    vector<pair<int, int>> best_positions;\n    int best_cost = INT_MAX;\n    bool best_valid = false;\n    \n    // Phase 1: Generate diverse initial solutions (0-300ms)\n    int trial = 0;\n    while (get_elapsed_ms() < 300) {\n        bool randomize = (trial % 2 != 0);\n        vector<int> order = build_greedy_order(rng, randomize, trial);\n        \n        int cost;\n        auto [S, positions] = build_solution(order, cost, 2);\n        bool valid = check_coverage(S) && (int)positions.size() <= 5000;\n        \n        if (valid && cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n            best_positions = positions;\n            best_valid = true;\n        } else if (!best_valid && (int)positions.size() <= 5000) {\n            best_cost = cost;\n            best_order = order;\n            best_positions = positions;\n        }\n        trial++;\n    }\n    \n    // Phase 2: Aggressive adjacent swap local search (300-900ms) - MAIN OPTIMIZATION\n    if (best_valid) {\n        int no_improve_count = 0;\n        \n        while (get_elapsed_ms() < 900 && no_improve_count < 10) {\n            bool improved = false;\n            \n            for (int iter = 0; iter < 500 && get_elapsed_ms() < 900; iter++) {\n                int i = select_swap_position(best_order, rng);\n                \n                vector<int> new_order = best_order;\n                swap(new_order[i], new_order[i + 1]);\n                \n                int cost;\n                auto [S, positions] = build_solution(new_order, cost, 2);\n                \n                if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                    improved = true;\n                    no_improve_count = 0;\n                }\n            }\n            \n            if (!improved) no_improve_count++;\n        }\n    }\n    \n    // Phase 3: Wide 2-opt local search (900-1350ms)\n    if (best_valid) {\n        while (get_elapsed_ms() < 1350) {\n            bool improved = false;\n            \n            for (int i = 0; i < M - 2 && get_elapsed_ms() < 1350; i++) {\n                // Try wider range\n                for (int j = i + 2; j < min(i + 50, M); j++) {\n                    vector<int> new_order = best_order;\n                    reverse(new_order.begin() + i + 1, new_order.begin() + j + 1);\n                    \n                    int cost;\n                    auto [S, positions] = build_solution(new_order, cost, 2);\n                    \n                    if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost - 3) {\n                        best_cost = cost;\n                        best_order = new_order;\n                        best_positions = positions;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Phase 4: Simulated annealing with tighter parameters (1350-1750ms)\n    if (best_valid) {\n        double temperature = best_cost * 0.15;  // Lower starting temp\n        double cooling_rate = 0.9998;  // Slower cooling\n        uniform_real_distribution<double> dist_real(0.0, 1.0);\n        \n        vector<int> current_order = best_order;\n        int current_cost = best_cost;\n        \n        while (get_elapsed_ms() < 1750) {\n            int i = select_swap_position(current_order, rng);\n            int j = i + 1 + (rng() % min(20, M - i - 1));\n            j = min(j, M - 1);\n            \n            vector<int> new_order = current_order;\n            swap(new_order[i], new_order[j]);\n            \n            int cost;\n            auto [S, positions] = build_solution(new_order, cost, 2);\n            \n            bool accept = false;\n            if ((int)positions.size() <= 5000 && check_coverage(S)) {\n                if (cost < current_cost) {\n                    accept = true;\n                } else if (temperature > 20) {\n                    double delta = (double)(cost - current_cost);\n                    double prob = exp(-delta / temperature);\n                    if (dist_real(rng) < prob) {\n                        accept = true;\n                    }\n                }\n            }\n            \n            if (accept) {\n                current_order = new_order;\n                current_cost = cost;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    auto [S2, positions2] = build_solution(best_order, best_cost, 3);\n                    best_positions = positions2;\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n    }\n    \n    // Phase 5: Final intensive hill climbing (1750-1950ms)\n    if (best_valid && get_elapsed_ms() < 1950) {\n        uniform_int_distribution<int> swap_dist(0, M - 2);\n        \n        while (get_elapsed_ms() < 1950) {\n            bool improved = false;\n            \n            for (int iter = 0; iter < 300 && get_elapsed_ms() < 1950; iter++) {\n                // Mix of adjacent and distant swaps\n                int i, j;\n                if (rng() % 3 == 0) {\n                    // Distant swap\n                    i = swap_dist(rng);\n                    j = swap_dist(rng);\n                    if (i > j) swap(i, j);\n                    if (i == j) continue;\n                } else {\n                    // Adjacent swap (more productive)\n                    i = select_swap_position(best_order, rng);\n                    j = i + 1;\n                }\n                \n                vector<int> new_order = best_order;\n                swap(new_order[i], new_order[j]);\n                \n                int cost;\n                auto [S, positions] = build_solution(new_order, cost, 2);\n                \n                if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                    improved = true;\n                }\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Final rebuild with best look-ahead\n    if (best_valid) {\n        int cost;\n        auto [S, positions] = build_solution(best_order, cost, 3);\n        best_positions = positions;\n    }\n    \n    // Fallback\n    if (best_positions.empty()) {\n        pair<int, int> cur_pos = {si, sj};\n        for (int i = 0; i < M; i++) {\n            for (char c : targets[i]) {\n                int c_idx = c - 'A';\n                pair<int, int> best_pos = char_positions[c_idx][0];\n                for (auto& pos : char_positions[c_idx]) {\n                    if (dist(cur_pos, pos) < dist(cur_pos, best_pos)) {\n                        best_pos = pos;\n                    }\n                }\n                best_positions.push_back(best_pos);\n                cur_pos = best_pos;\n            }\n        }\n    }\n    \n    for (auto& p : best_positions) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    int N, M;\n    double eps;\n    \n    // Read input\n    cin >> N >> M >> eps;\n    \n    vector<vector<pair<int, int> > > shapes(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k][i].first >> shapes[k][i].second;\n        }\n    }\n    \n    // Simple strategy: drill every square\n    vector<pair<int, int> > oil_cells;\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                oil_cells.push_back(make_pair(i, j));\n            }\n        }\n    }\n    \n    // Output answer\n    cout << \"a \" << (int)oil_cells.size();\n    for (size_t i = 0; i < oil_cells.size(); ++i) {\n        cout << \" \" << oil_cells[i].first << \" \" << oil_cells[i].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 <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global constants\nconst int W = 1000;\n\n// Problem data\nint D, N;\nvector<vector<int>> a; // a[d][k]\n\n// Grid dimensions\nint R, C;\n\n// State: H[d][r], W[d][c]\n// Using vector of vectors\nvector<vector<int>> H;\nvector<vector<int>> W_vec; // Renamed to W_vec to avoid conflict with constant W\n\n// Mapping from k to (r, c)\npair<int, int> get_rc(int k) {\n    return {k / C, k % C};\n}\n\n// Calculate total cost\nlong long calculate_cost() {\n    long long total_cost = 0;\n    \n    // Area costs\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                total_cost += 100LL * (a[d][k] - area);\n            }\n        }\n    }\n    \n    // Partition costs\n    for (int d = 1; d < D; ++d) {\n        // Horizontal lines\n        int y_prev = 0;\n        int y_curr = 0;\n        for (int r = 0; r < R; ++r) {\n            y_prev += H[d-1][r];\n            y_curr += H[d][r];\n            total_cost += (long long)W * abs(y_prev - y_curr);\n        }\n        // Vertical lines\n        int x_prev = 0;\n        int x_curr = 0;\n        for (int c = 0; c < C; ++c) {\n            x_prev += W_vec[d-1][c];\n            x_curr += W_vec[d][c];\n            total_cost += (long long)W * abs(x_prev - x_curr);\n        }\n    }\n    \n    return total_cost;\n}\n\n// Calculate delta cost for a change in H[d][r] or W_vec[d][c]\n// This is more efficient for SA\nlong long calculate_delta_cost(int d, int type, int idx, int delta) {\n    // type 0: H, 1: W_vec\n    long long delta_cost = 0;\n    \n    // Area cost change for day d\n    if (type == 0) { // H[d][idx] changes by delta\n        int r = idx;\n        int old_h = H[d][r];\n        int new_h = old_h + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kr == r) {\n                long long old_area = (long long)old_h * W_vec[d][kc];\n                long long new_area = (long long)new_h * W_vec[d][kc];\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    } else { // W_vec[d][idx] changes by delta\n        int c = idx;\n        int old_w = W_vec[d][c];\n        int new_w = old_w + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kc == c) {\n                long long old_area = (long long)H[d][kr] * old_w;\n                long long new_area = (long long)H[d][kr] * new_w;\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    }\n    \n    // Partition cost change\n    // Affected days: d (with d-1) and d+1 (with d)\n    // If d=0, only d+1. But L_0=0, so partition cost starts from d=1.\n    // Partition cost between d-1 and d depends on cumulative sums at d-1 and d.\n    // Changing H[d][idx] changes cumulative sums for r >= idx on day d.\n    \n    auto update_partition = [&](int day_idx, int type_p, int idx_p, int delta_p) {\n        // day_idx is the day being modified (d)\n        // We need to compare with day_idx-1 and day_idx+1\n        long long cost_change = 0;\n        \n        // Compare with day_idx - 1\n        if (day_idx > 0) {\n            int sum_prev = 0;\n            int sum_curr = 0;\n            // We only need to sum from idx_p to end because before idx_p sums are same\n            // But wait, cumulative sum at r depends on H[0]...H[r].\n            // If H[idx] changes, all cumulative sums Y_r for r > idx change.\n            // Y_idx also changes.\n            // So for all r from idx to R-1, Y_r changes by delta_p.\n            // Cost adds W * |delta_p| for each such line.\n            // Number of lines affected: R - idx_p.\n            // Wait, lines are at Y_1, ..., Y_R.\n            // Y_r = sum(H[0]...H[r-1]).\n            // If H[idx] changes, Y_r changes for r > idx.\n            // So lines Y_{idx+1} ... Y_R change.\n            // Count = R - idx.\n            // But Y_R is at W (fixed sum), so Y_R doesn't change?\n            // We enforce sum H = W. So if H[idx] += delta, some H[other] -= delta.\n            // So Y_R remains W.\n            // So lines affected are those between idx and the 'other' index.\n            // This makes delta calculation complex if we swap.\n            // Let's stick to full cost recalc for partition if needed, or simplify.\n            // Given N is small, full partition cost recalc for affected days is fast.\n            // Affected days: d-1 (boundary d-1|d) and d (boundary d|d+1).\n            // Just recalc partition cost for these two boundaries.\n        }\n        return cost_change;\n    };\n\n    // Simpler approach: Recalculate partition cost for boundaries involving day d.\n    // Boundaries: (d-1, d) and (d, d+1).\n    // Store previous partition cost for these boundaries to subtract.\n    // But implementing this cleanly is verbose.\n    // Given the speed of O(N) area calc, O(R+C) partition calc is also fast.\n    // Let's just calculate the delta for partition explicitly.\n    \n    // Partition cost contribution of day d with d-1:\n    // Sum_r W * |Y_{d,r} - Y_{d-1,r}|\n    // If H[d][idx] changes by delta, Y_{d,r} changes by delta for r > idx.\n    // (Assuming we adjust another H[d][other] to keep sum constant).\n    // If we do swap move (H[idx]+=1, H[other]-=1), then Y_r changes by 1 for r in (min, max].\n    // This is getting complicated for delta.\n    // Given 3 seconds, we can afford O(R+C) per step.\n    // Let's implement a function that recalculates partition cost for day d boundaries.\n    \n    return delta_cost; // Placeholder, will implement full delta in SA loop or use full cost for safety if fast enough\n}\n\n// Function to calculate partition cost between day d1 and d2\nlong long calc_partition_between(int d1, int d2) {\n    long long cost = 0;\n    int y1 = 0, y2 = 0;\n    for (int r = 0; r < R; ++r) {\n        y1 += H[d1][r];\n        y2 += H[d2][r];\n        cost += (long long)W * abs(y1 - y2);\n    }\n    int x1 = 0, x2 = 0;\n    for (int c = 0; c < C; ++c) {\n        x1 += W_vec[d1][c];\n        x2 += W_vec[d2][c];\n        cost += (long long)W * abs(x1 - x2);\n    }\n    return cost;\n}\n\n// Global current cost\nlong long current_cost = 0;\n\nvoid update_cost_after_change(int d, const vector<int>& old_H, const vector<int>& old_W) {\n    // Recompute area cost for day d\n    // Recompute partition cost for (d-1, d) and (d, d+1)\n    // This is O(N + R + C).\n    \n    // We need to subtract old contributions and add new.\n    // To do this cleanly, we need to store per-day costs.\n    // Let's store vector<long long> area_cost(D), partition_cost(D) (cost between d-1 and d)\n    // partition_cost[0] = 0.\n    // Total = sum(area) + sum(partition).\n}\n\n// Let's use a simpler SA structure where we just recompute necessary parts.\n// Since D is small, we can store per-day area cost and per-boundary partition cost.\nvector<long long> day_area_cost;\nvector<long long> boundary_part_cost; // size D, boundary_part_cost[d] is cost between d-1 and d. [0] is 0.\n\nvoid init_costs() {\n    day_area_cost.assign(D, 0);\n    boundary_part_cost.assign(D, 0);\n    \n    for (int d = 0; d < D; ++d) {\n        long long cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                cost += 100LL * (a[d][k] - area);\n            }\n        }\n        day_area_cost[d] = cost;\n    }\n    \n    for (int d = 1; d < D; ++d) {\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n    }\n    \n    current_cost = 0;\n    for (long long c : day_area_cost) current_cost += c;\n    for (long long c : boundary_part_cost) current_cost += c;\n}\n\nvoid apply_move_and_update(int d, int type, int idx, int delta) {\n    // Apply move\n    if (type == 0) {\n        H[d][idx] += delta;\n    } else {\n        W_vec[d][idx] += delta;\n    }\n    \n    // Update day_area_cost[d]\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    // Update boundary_part_cost[d] (between d-1 and d)\n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    // Update boundary_part_cost[d+1] (between d and d+1)\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nvoid revert_move_and_update(int d, int type, int idx, int delta) {\n    // Revert\n    if (type == 0) {\n        H[d][idx] -= delta;\n    } else {\n        W_vec[d][idx] -= delta;\n    }\n    \n    // Recalculate costs (same as apply, effectively undoing the change in values)\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int W_in;\n    if (!(cin >> W_in >> D >> N)) return 0;\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    // Determine R, C\n    // Try to find R that minimizes initial area cost heuristic\n    int best_R = 1;\n    long long min_init_cost = -1;\n    \n    for (int r_try = 1; r_try <= N; ++r_try) {\n        int c_try = (N + r_try - 1) / r_try;\n        // Heuristic cost estimate\n        // Distribute W to rows/cols based on sqrt(area)\n        long long est_cost = 0;\n        // Just pick the one closest to square\n        if (min_init_cost == -1 || abs(r_try - c_try) < abs(best_R - (N + best_R - 1) / best_R)) {\n             best_R = r_try;\n        }\n    }\n    // Prefer square-ish\n    best_R = max(1, (int)round(sqrt(N)));\n    R = best_R;\n    C = (N + R - 1) / R;\n    \n    // Initialize H and W_vec\n    H.assign(D, vector<int>(R));\n    W_vec.assign(D, vector<int>(C));\n    \n    mt19937 rng(12345);\n    \n    for (int d = 0; d < D; ++d) {\n        // Calculate target \"weight\" for each row and col\n        vector<long long> row_weight(R, 0);\n        vector<long long> col_weight(C, 0);\n        \n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            // Use sqrt of area as weight\n            long long w = (long long)sqrt(a[d][k]) + 1;\n            row_weight[r] += w;\n            col_weight[c] += w;\n        }\n        \n        long long sum_rw = accumulate(row_weight.begin(), row_weight.end(), 0LL);\n        long long sum_cw = accumulate(col_weight.begin(), col_weight.end(), 0LL);\n        \n        // Distribute W\n        int rem_h = W;\n        for (int r = 0; r < R; ++r) {\n            int h = (sum_rw == 0) ? W/R : (int)((double)row_weight[r] / sum_rw * W);\n            H[d][r] = h;\n            rem_h -= h;\n        }\n        // Distribute remainder\n        int r_idx = 0;\n        while (rem_h > 0) {\n            H[d][r_idx % R]++;\n            rem_h--;\n            r_idx++;\n        }\n        // Ensure min 1\n        for(int r=0; r<R; ++r) if(H[d][r] < 1) H[d][r] = 1;\n        // Re-normalize sum to W (simple adjust)\n        int sum_h = accumulate(H[d].begin(), H[d].end(), 0);\n        if (sum_h != W) {\n            H[d][0] += (W - sum_h);\n        }\n        \n        int rem_w = W;\n        for (int c = 0; c < C; ++c) {\n            int w = (sum_cw == 0) ? W/C : (int)((double)col_weight[c] / sum_cw * W);\n            W_vec[d][c] = w;\n            rem_w -= w;\n        }\n        int c_idx = 0;\n        while (rem_w > 0) {\n            W_vec[d][c_idx % C]++;\n            rem_w--;\n            c_idx++;\n        }\n        for(int c=0; c<C; ++c) if(W_vec[d][c] < 1) W_vec[d][c] = 1;\n        int sum_w = accumulate(W_vec[d].begin(), W_vec[d].end(), 0);\n        if (sum_w != W) {\n            W_vec[d][0] += (W - sum_w);\n        }\n    }\n    \n    init_costs();\n    \n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double T = 10000.0;\n    double T_end = 1.0;\n    double alpha = 0.99995;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break; // Leave margin\n        \n        // Pick move\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        int type = uniform_int_distribution<int>(0, 1)(rng); // 0: H, 1: W\n        int dim = (type == 0) ? R : C;\n        int idx = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        // Pick another index to swap with to maintain sum\n        int idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        while (idx2 == idx) idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 1)(rng)) delta = -1;\n        \n        // Check validity (must be >= 1)\n        if (type == 0) {\n            if (H[d][idx] + delta < 1 || H[d][idx2] - delta < 1) continue;\n        } else {\n            if (W_vec[d][idx] + delta < 1 || W_vec[d][idx2] - delta < 1) continue;\n        }\n        \n        // Apply first change\n        if (type == 0) H[d][idx] += delta;\n        else W_vec[d][idx] += delta;\n        \n        // Calculate cost delta roughly? \n        // No, let's just apply both and calc cost.\n        if (type == 0) H[d][idx2] -= delta;\n        else W_vec[d][idx2] -= delta;\n        \n        // We need to calculate new cost efficiently.\n        // Since we changed two indices, we can just recompute day_area_cost[d] and boundaries.\n        // Store old values to revert if rejected.\n        int old_val1 = (type == 0) ? H[d][idx] - delta : W_vec[d][idx] - delta;\n        int old_val2 = (type == 0) ? H[d][idx2] + delta : W_vec[d][idx2] + delta;\n        \n        long long old_day_cost = day_area_cost[d];\n        long long old_bound1 = (d > 0) ? boundary_part_cost[d] : 0;\n        long long old_bound2 = (d < D-1) ? boundary_part_cost[d+1] : 0;\n        \n        // Recompute area cost\n        long long new_area_cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                new_area_cost += 100LL * (a[d][k] - area);\n            }\n        }\n        \n        long long new_bound1 = 0, new_bound2 = 0;\n        if (d > 0) new_bound1 = calc_partition_between(d-1, d);\n        if (d < D-1) new_bound2 = calc_partition_between(d, d+1);\n        \n        long long delta_E = (new_area_cost - old_day_cost) + (new_bound1 - old_bound1) + (new_bound2 - old_bound2);\n        \n        bool accept = false;\n        if (delta_E <= 0) accept = true;\n        else {\n            double p = exp(-delta_E / T);\n            if (uniform_real_distribution<double>(0, 1)(rng) < p) accept = true;\n        }\n        \n        if (accept) {\n            current_cost += delta_E;\n            day_area_cost[d] = new_area_cost;\n            if (d > 0) boundary_part_cost[d] = new_bound1;\n            if (d < D-1) boundary_part_cost[d+1] = new_bound2;\n        } else {\n            // Revert\n            if (type == 0) {\n                H[d][idx] = old_val1;\n                H[d][idx2] = old_val2;\n            } else {\n                W_vec[d][idx] = old_val1;\n                W_vec[d][idx2] = old_val2;\n            }\n        }\n        \n        T *= alpha;\n        iter++;\n    }\n    \n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            int i_start = 0;\n            for (int i = 0; i < r; ++i) i_start += H[d][i];\n            int i_end = i_start + H[d][r];\n            \n            int j_start = 0;\n            for (int j = 0; j < c; ++j) j_start += W_vec[d][j];\n            int j_end = j_start + W_vec[d][c];\n            \n            cout << i_start << \" \" << j_start << \" \" << i_end << \" \" << j_end << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\nusing ll = long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int STAMP_SIZE = 3;\nconst int POS_LIMIT = 7;\n\nll A[N][N];\nll S[M][STAMP_SIZE][STAMP_SIZE];\nll Grid[N][N];\nll GridMod[N][N];\nll CurrentScore = 0;\n\nstruct Op {\n    uint8_t m, p, q;\n};\n\nstruct FastRNG {\n    uint64_t state;\n    FastRNG(uint64_t seed) : state(seed) {}\n    uint64_t next() {\n        state ^= state << 13;\n        state ^= state >> 7;\n        state ^= state << 17;\n        return state;\n    }\n    int nextInt(int max) { return next() % max; }\n    double nextDouble() { return (next() >> 11) * (1.0 / (uint64_t(1) << 53)); }\n};\n\ninline ll get_mod(ll v) {\n    ll r = v % MOD;\n    return r < 0 ? r + MOD : r;\n}\n\ninline ll calc_delta(int m, int p, int q, int delta) {\n    ll change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            ll new_val = Grid[r][c] + delta * S[m][i][j];\n            change += get_mod(new_val) - GridMod[r][c];\n        }\n    }\n    return change;\n}\n\ninline void apply_op(int m, int p, int q, int delta) {\n    ll score_change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            Grid[r][c] += delta * S[m][i][j];\n            ll old_mod = GridMod[r][c];\n            GridMod[r][c] = get_mod(Grid[r][c]);\n            score_change += GridMod[r][c] - old_mod;\n        }\n    }\n    CurrentScore += score_change;\n}\n\nvoid init_grid() {\n    CurrentScore = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Grid[i][j] = A[i][j];\n            GridMod[i][j] = get_mod(A[i][j]);\n            CurrentScore += GridMod[i][j];\n        }\n    }\n}\n\nll run_sa(uint64_t seed, double time_limit, vector<Op>& ops) {\n    FastRNG rng(seed);\n    init_grid();\n    ops.clear();\n    \n    // Greedy initialization\n    for (int step = 0; step < K; ++step) {\n        ll best_delta = 0;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < POS_LIMIT; ++p) {\n                for (int q = 0; q < POS_LIMIT; ++q) {\n                    ll d = calc_delta(m, p, q, 1);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_m = m; best_p = p; best_q = q;\n                    }\n                }\n            }\n        }\n        \n        if (best_delta <= 0) break;\n        apply_op(best_m, best_p, best_q, 1);\n        ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n    }\n    \n    ll best_score = CurrentScore;\n    vector<Op> best_ops = ops;\n    \n    auto start = chrono::steady_clock::now();\n    ll T_start = 1000000000LL;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        double progress = elapsed / time_limit;\n        ll T = (ll)(T_start * exp(-progress * 6.0));\n        if (T < 100) T = 100;\n        \n        int move = rng.nextInt(100);\n        \n        if (ops.empty()) {\n            int m = rng.nextInt(M);\n            int p = rng.nextInt(POS_LIMIT);\n            int q = rng.nextInt(POS_LIMIT);\n            ll delta = calc_delta(m, p, q, 1);\n            if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                apply_op(m, p, q, 1);\n                ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        } else if (ops.size() >= K) {\n            if (move < 70) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        } else {\n            if (move < 50) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else if (move < 80) {\n                // Add\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                ll delta = calc_delta(m, p, q, 1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(m, p, q, 1);\n                    ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        }\n        \n        if (CurrentScore > best_score) {\n            best_score = CurrentScore;\n            best_ops = ops;\n        }\n    }\n    \n    ops = best_ops;\n    return best_score;\n}\n\nvoid final_refine(vector<Op>& ops, double time_limit) {\n    auto start = chrono::steady_clock::now();\n    \n    // Initialize grid with current operations ONCE\n    init_grid();\n    for (const auto& op : ops) {\n        apply_op(op.m, op.p, op.q, 1);\n    }\n    \n    // Single continuous refinement loop (no grid reset!)\n    bool improved = true;\n    while (improved) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        improved = false;\n        \n        ll best_delta = 0;\n        int best_type = -1, best_idx = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        // Try ALL changes\n        for (int idx = 0; idx < (int)ops.size(); ++idx) {\n            Op old = ops[idx];\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < POS_LIMIT; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        if (m == old.m && p == old.p && q == old.q) continue;\n                        ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 0;\n                            best_idx = idx;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try removes\n        for (int idx = 0; idx < (int)ops.size(); ++idx) {\n            Op old = ops[idx];\n            ll delta = calc_delta(old.m, old.p, old.q, -1);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_type = 1;\n                best_idx = idx;\n            }\n        }\n        \n        // Try adds\n        if (ops.size() < K) {\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < POS_LIMIT; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        ll delta = calc_delta(m, p, q, 1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 2;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (best_delta > 0) {\n            improved = true;\n            if (best_type == 0) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                apply_op(best_m, best_p, best_q, 1);\n                ops[best_idx] = {(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q};\n            } else if (best_type == 1) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                ops[best_idx] = ops.back();\n                ops.pop_back();\n            } else {\n                apply_op(best_m, best_p, best_q, 1);\n                ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, m_in, k_in;\n    cin >> n_in >> m_in >> k_in;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    for (int m = 0; m < M; ++m)\n        for (int i = 0; i < STAMP_SIZE; ++i)\n            for (int j = 0; j < STAMP_SIZE; ++j)\n                cin >> S[m][i][j];\n\n    vector<Op> best_ops;\n    ll best_score = 0;\n    \n    // 3 SA runs @ 0.55s each = 1.65s\n    double sa_time = 0.55;\n    for (int run = 0; run < 3; ++run) {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + run * 1000000 + run * 12345;\n        vector<Op> ops;\n        ll score = run_sa(seed, sa_time, ops);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n    \n    // Final refinement @ 0.30s (continuous, no reset)\n    final_refine(best_ops, 0.30);\n    \n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << (int)op.m << \" \" << (int)op.p << \" \" << (int)op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dchar[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int id;\n    int r, c;\n    int holding;\n    bool is_large;\n};\n\nclass Solver {\n    int grid[N][N];\n    Crane cranes[N];\n    vector<int> inputs[N];\n    int input_idx[N];\n    int next_dispatch[N];\n    int total_dispatched;\n    vector<string> ans;\n    int turn;\n\npublic:\n    Solver(const vector<vector<int>>& A) {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = -1;\n            cranes[i].id = i;\n            cranes[i].r = i;\n            cranes[i].c = 0;\n            cranes[i].holding = -1;\n            cranes[i].is_large = (i == 0);\n            input_idx[i] = 0;\n            next_dispatch[i] = i * N;\n            for(int j=0; j<N; ++j) inputs[i].push_back(A[i][j]);\n        }\n        total_dispatched = 0;\n        turn = 0;\n        ans.resize(N);\n    }\n\n    void receive_containers() {\n        for(int i=0; i<N; ++i) {\n            if(input_idx[i] < N) {\n                bool has_container = (grid[i][0] != -1);\n                bool crane_holding = false;\n                for(int k=0; k<N; ++k) {\n                    if(cranes[k].r == i && cranes[k].c == 0 && cranes[k].holding != -1) {\n                        crane_holding = true;\n                        break;\n                    }\n                }\n                if(!has_container && !crane_holding) {\n                    grid[i][0] = inputs[i][input_idx[i]];\n                    input_idx[i]++;\n                }\n            }\n        }\n    }\n\n    void dispatch_containers() {\n        for(int i=0; i<N; ++i) {\n            if(grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                grid[i][N-1] = -1;\n                total_dispatched++;\n                if(cid == next_dispatch[i]) {\n                    next_dispatch[i]++;\n                }\n            }\n        }\n    }\n\n    bool can_move(int crane_idx, int nr, int nc, const vector<pair<int,int>>& next_pos) {\n        if(nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n        for(int k=0; k<crane_idx; ++k) {\n            if(next_pos[k].first == nr && next_pos[k].second == nc) return false;\n            if(next_pos[k].first == cranes[crane_idx].r && next_pos[k].second == cranes[crane_idx].c) {\n                if(nr == cranes[k].r && nc == cranes[k].c) return false;\n            }\n        }\n        for(int k=crane_idx+1; k<N; ++k) {\n            if(cranes[k].r == nr && cranes[k].c == nc) return false;\n        }\n        return true;\n    }\n\n    bool valid_cell_for_carry(int crane_idx, int r, int c) {\n        if(cranes[crane_idx].holding == -1 || cranes[crane_idx].is_large) return true;\n        return grid[r][c] == -1;\n    }\n\n    int get_container_priority(int cid) {\n        int target_row = cid / N;\n        int expected = next_dispatch[target_row];\n        if(cid == expected) return 3;\n        if(cid < expected + N) return 2;\n        return 1;\n    }\n\n    void solve() {\n        while(turn < MAX_TURNS && total_dispatched < N*N) {\n            turn++;\n            receive_containers();\n            \n            vector<char> moves(N, '.');\n            vector<pair<int,int>> next_pos(N);\n            for(int i=0; i<N; ++i) next_pos[i] = {cranes[i].r, cranes[i].c};\n\n            // Find all containers and their priorities\n            struct ContainerInfo {\n                int id, r, c, target_row, priority;\n            };\n            vector<ContainerInfo> containers;\n            for(int i=0; i<N; ++i) {\n                for(int j=0; j<N; ++j) {\n                    if(grid[i][j] != -1) {\n                        containers.push_back({grid[i][j], i, j, grid[i][j]/N, get_container_priority(grid[i][j])});\n                    }\n                }\n            }\n            sort(containers.begin(), containers.end(), [](const ContainerInfo& a, const ContainerInfo& b) {\n                return a.priority > b.priority;\n            });\n\n            for(int i=0; i<N; ++i) {\n                Crane& cr = cranes[i];\n                long long best_score = -1e18;\n                char best_move = '.';\n                int nr = cr.r, nc = cr.c;\n\n                // Base score\n                long long base_score = 0;\n                if(cr.holding != -1) {\n                    int t_row = cr.holding / N;\n                    base_score -= (abs(cr.r - t_row) + abs(cr.c - (N-1))) * 10;\n                    if(cr.holding == next_dispatch[t_row]) base_score += 5000;\n                }\n\n                // Try P (Pick up)\n                if(cr.holding == -1 && grid[cr.r][cr.c] != -1) {\n                    int cid = grid[cr.r][cr.c];\n                    int t_row = cid / N;\n                    long long s = base_score;\n                    int prio = get_container_priority(cid);\n                    if(prio == 3) s += 20000;\n                    else if(prio == 2) s += 5000;\n                    else s += 1000;\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = 'P';\n                        nr = cr.r; nc = cr.c;\n                    }\n                }\n\n                // Try Q (Place/Dispatch)\n                if(cr.holding != -1 && grid[cr.r][cr.c] == -1) {\n                    int t_row = cr.holding / N;\n                    long long s = base_score;\n                    if(cr.r == t_row && cr.c == N-1) {\n                        if(cr.holding == next_dispatch[t_row]) s += 35000;\n                        else s += 15000;\n                    } else if(cr.c == N-1) {\n                        s += 8000;\n                    } else if(cr.c >= 2 && cr.c <= N-2) {\n                        // Buffer - prefer storing containers in their target row\n                        if(cr.r == t_row) s += 500;\n                        else s -= 500;\n                    } else {\n                        s -= 3000;\n                    }\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = 'Q';\n                        nr = cr.r; nc = cr.c;\n                    }\n                }\n\n                // Try moves\n                for(int d=0; d<4; ++d) {\n                    int tr = cr.r + dr[d];\n                    int tc = cr.c + dc[d];\n                    if(!can_move(i, tr, tc, next_pos)) continue;\n                    if(!valid_cell_for_carry(i, tr, tc)) continue;\n\n                    long long s = 0;\n                    if(cr.holding != -1) {\n                        int t_row = cr.holding / N;\n                        int dist = abs(tr - t_row) + abs(tc - (N-1));\n                        s -= dist * 10;\n                        if(cr.holding == next_dispatch[t_row]) s += 7000;\n                        if(tr == t_row && tc == N-1) s += 20000;\n                        if(tc == N-1 && tr != t_row) s -= 8000;\n                        // Prefer buffer in target row\n                        if(tc >= 2 && tc <= N-2 && tr == t_row) s += 1000;\n                    } else {\n                        // Empty - prioritize high-priority containers\n                        int best_container_dist = 10000;\n                        for(const auto& cont : containers) {\n                            if(cont.c == 0) {\n                                int d = abs(tr - cont.r) + abs(tc - 0);\n                                if(cont.priority == 3) d -= 200;\n                                else if(cont.priority == 2) d -= 50;\n                                if(d < best_container_dist) best_container_dist = d;\n                            }\n                        }\n                        s -= best_container_dist * 8;\n                        \n                        // Look for buffered containers that are high priority\n                        for(const auto& cont : containers) {\n                            if(cont.c >= 1 && cont.c <= N-2 && cont.priority >= 2) {\n                                int d = abs(tr - cont.r) + abs(tc - cont.c);\n                                s -= d * 5;\n                            }\n                        }\n                        \n                        // Large crane should help move between rows\n                        if(cr.is_large) {\n                            for(int r=0; r<N; ++r) {\n                                if(grid[r][1] != -1 || grid[r][2] != -1 || grid[r][3] != -1) {\n                                    int cid = -1;\n                                    if(grid[r][1] != -1) cid = grid[r][1];\n                                    else if(grid[r][2] != -1) cid = grid[r][2];\n                                    else if(grid[r][3] != -1) cid = grid[r][3];\n                                    if(cid != -1 && cid == next_dispatch[r]) {\n                                        int d = abs(tr - r) + abs(tc - 1);\n                                        s -= d * 3;\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = dchar[d];\n                        nr = tr; nc = tc;\n                    }\n                }\n\n                moves[i] = best_move;\n                if(best_move == 'P' || best_move == 'Q' || best_move == '.') {\n                    next_pos[i] = {cr.r, cr.c};\n                } else {\n                    next_pos[i] = {nr, nc};\n                }\n            }\n\n            // Execute\n            for(int i=0; i<N; ++i) {\n                ans[i] += moves[i];\n                Crane& cr = cranes[i];\n                char m = moves[i];\n                if(m == 'P') {\n                    cr.holding = grid[cr.r][cr.c];\n                    grid[cr.r][cr.c] = -1;\n                } else if(m == 'Q') {\n                    grid[cr.r][cr.c] = cr.holding;\n                    cr.holding = -1;\n                } else if(m == 'U') cr.r--;\n                else if(m == 'D') cr.r++;\n                else if(m == 'L') cr.c--;\n                else if(m == 'R') cr.c++;\n            }\n\n            dispatch_containers();\n        }\n\n        size_t max_len = 0;\n        for(const auto& s : ans) max_len = max(max_len, s.size());\n        if(max_len == 0) max_len = 1;\n        for(int i=0; i<N; ++i) {\n            while(ans[i].size() < max_len) ans[i] += '.';\n        }\n    }\n\n    void print_ans() {\n        for(int i=0; i<N; ++i) {\n            cout << ans[i] << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.print_ans();\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <string>\n#include <cstdlib>\n\nusing namespace std;\n\n// Structure to represent grid coordinates\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Coord& o) const { return !(*this == o); }\n};\n\n// Manhattan distance between two coordinates\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint N;\nint h[25][25];\nvector<Coord> sources;\nvector<Coord> sinks;\n\n// Flow targets for each source cell: list of {sink_coord, amount}\nstruct FlowTarget {\n    Coord sink;\n    int amount;\n};\nvector<FlowTarget> source_flows[25][25];\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\n    // Read input and identify sources (h > 0) and sinks (h < 0)\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    // Working copy of heights to track remaining supply/demand\n    int cur_h[25][25];\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            cur_h[i][j] = h[i][j];\n    \n    // Indices of active sources and sinks\n    vector<int> src_idx(sources.size());\n    iota(src_idx.begin(), src_idx.end(), 0);\n    vector<int> snk_idx(sinks.size());\n    iota(snk_idx.begin(), snk_idx.end(), 0);\n\n    // Greedy Flow Calculation\n    // Repeatedly pick the pair (source, sink) with minimum distance and transfer soil.\n    // This approximates the Minimum Cost Flow / Earth Mover's Distance.\n    while (!src_idx.empty() && !snk_idx.empty()) {\n        int s_choice = -1;\n        int k_choice = -1;\n        int min_d = 1e9;\n\n        // Find the pair with minimum Manhattan distance\n        for (int s : src_idx) {\n            for (int k : snk_idx) {\n                int d = dist(sources[s], sinks[k]);\n                if (d < min_d) {\n                    min_d = d;\n                    s_choice = s;\n                    k_choice = k;\n                }\n            }\n        }\n        \n        if (s_choice == -1) break;\n\n        Coord u = sources[s_choice];\n        Coord v = sinks[k_choice];\n        // Transfer as much as possible\n        int amount = min(cur_h[u.r][u.c], -cur_h[v.r][v.c]);\n        \n        source_flows[u.r][u.c].push_back({v, amount});\n        \n        cur_h[u.r][u.c] -= amount;\n        cur_h[v.r][v.c] += amount;\n        \n        // Remove exhausted source or sink from active lists\n        if (cur_h[u.r][u.c] == 0) {\n            for(int i=0; i<src_idx.size(); ++i) {\n                if(src_idx[i] == s_choice) {\n                    src_idx[i] = src_idx.back();\n                    src_idx.pop_back();\n                    break;\n                }\n            }\n        }\n        if (cur_h[v.r][v.c] == 0) {\n            for(int i=0; i<snk_idx.size(); ++i) {\n                if(snk_idx[i] == k_choice) {\n                    snk_idx[i] = snk_idx.back();\n                    snk_idx.pop_back();\n                    break;\n                }\n            }\n        }\n    }\n\n    vector<string> ops;\n    Coord cur = {0, 0}; // Truck starts at (0,0)\n\n    // List of sources that have soil to transport\n    vector<Coord> active_sources;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!source_flows[i][j].empty()) {\n                active_sources.push_back({i, j});\n            }\n        }\n    }\n\n    // Order sources using Nearest Neighbor heuristic to minimize empty travel\n    vector<bool> visited_source(active_sources.size(), false);\n    int sources_remaining = active_sources.size();\n\n    while (sources_remaining > 0) {\n        int best_idx = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < active_sources.size(); ++i) {\n            if (!visited_source[i]) {\n                int d = dist(cur, active_sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n        }\n\n        if (best_idx == -1) break;\n\n        Coord u = active_sources[best_idx];\n        visited_source[best_idx] = true;\n        sources_remaining--;\n\n        // Move truck to source u\n        while (cur != u) {\n            if (cur.r < u.r) { cur.r++; ops.push_back(\"D\"); }\n            else if (cur.r > u.r) { cur.r--; ops.push_back(\"U\"); }\n            else if (cur.c < u.c) { cur.c++; ops.push_back(\"R\"); }\n            else if (cur.c > u.c) { cur.c--; ops.push_back(\"L\"); }\n        }\n\n        // Calculate total load to pick up at u\n        int total_load = 0;\n        for (auto& flow : source_flows[u.r][u.c]) {\n            total_load += flow.amount;\n        }\n\n        // Load soil\n        ops.push_back(\"+\" + to_string(total_load));\n\n        // Visit assigned sinks for this source\n        // Order sinks using Nearest Neighbor to minimize loaded travel\n        vector<FlowTarget> targets = source_flows[u.r][u.c];\n        vector<bool> visited_target(targets.size(), false);\n        int targets_remaining = targets.size();\n\n        while (targets_remaining > 0) {\n            int best_t = -1;\n            int min_td = 1e9;\n            for (int i = 0; i < targets.size(); ++i) {\n                if (!visited_target[i]) {\n                    int d = dist(cur, targets[i].sink);\n                    if (d < min_td) {\n                        min_td = d;\n                        best_t = i;\n                    }\n                }\n            }\n            \n            Coord v = targets[best_t].sink;\n            // Move truck to sink v\n            while (cur != v) {\n                if (cur.r < v.r) { cur.r++; ops.push_back(\"D\"); }\n                else if (cur.r > v.r) { cur.r--; ops.push_back(\"U\"); }\n                else if (cur.c < v.c) { cur.c++; ops.push_back(\"R\"); }\n                else if (cur.c > v.c) { cur.c--; ops.push_back(\"L\"); }\n            }\n\n            // Unload soil\n            int amt = targets[best_t].amount;\n            ops.push_back(\"-\" + to_string(amt));\n            \n            visited_target[best_t] = true;\n            targets_remaining--;\n        }\n    }\n\n    // Output the sequence of operations\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 <cmath>\n#include <random>\n#include <set>\n\nusing namespace std;\n\nstruct Position {\n    int priority;\n    int i;\n    int j;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n    \n    int seed_count = 2 * N * (N - 1);\n    int grid_size = N * N;\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    \n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n    \n    mt19937 rng(42);\n    \n    vector<int> global_max(M, 0);\n    for (int d = 0; d < M; d++) {\n        for (int i = 0; i < seed_count; i++) {\n            global_max[d] = max(global_max[d], X[i][d]);\n        }\n    }\n    \n    vector<int> prev_best_seeds;\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<int> dim_max(M, 0);\n        vector<vector<int>> dim_top_seeds(M);\n        \n        for (int d = 0; d < M; d++) {\n            vector<pair<int, int>> dim_values;\n            for (int i = 0; i < seed_count; i++) {\n                dim_values.push_back({X[i][d], i});\n            }\n            sort(dim_values.begin(), dim_values.end(), greater<pair<int,int>>());\n            dim_max[d] = dim_values[0].first;\n            \n            for (size_t i = 0; i < min((size_t)3, dim_values.size()); i++) {\n                dim_top_seeds[d].push_back(dim_values[i].second);\n            }\n        }\n        \n        double diversity_weight = 1.0 - (double)turn / (T + 2);\n        double elite_weight = (double)turn / (T + 2);\n        \n        vector<pair<double, int>> seed_score(seed_count);\n        vector<int> seed_total(seed_count, 0);\n        \n        for (int i = 0; i < seed_count; i++) {\n            double score = 0;\n            int total = 0;\n            int dim_excellence_count = 0;\n            \n            for (int d = 0; d < M; d++) {\n                total += X[i][d];\n                \n                if (dim_max[d] > 0) {\n                    double ratio = (double)X[i][d] / dim_max[d];\n                    score += ratio * ratio * 8.0;\n                    \n                    if (X[i][d] == dim_max[d]) {\n                        score += 12.0;\n                        dim_excellence_count++;\n                    } else if (X[i][d] >= dim_max[d] * 0.95) {\n                        score += 6.0;\n                    } else if (X[i][d] >= dim_max[d] * 0.85) {\n                        score += 2.0;\n                    }\n                }\n            }\n            \n            score += total * 0.015;\n            \n            if (turn > 0 && find(prev_best_seeds.begin(), prev_best_seeds.end(), i) != prev_best_seeds.end()) {\n                score += 2.5 * elite_weight;\n            }\n            \n            score += dim_excellence_count * 3.0 * diversity_weight;\n            \n            seed_score[i] = {score, i};\n            seed_total[i] = total;\n        }\n        \n        sort(seed_score.begin(), seed_score.end(), [](const auto& a, const auto& b) {\n            if (abs(a.first - b.first) > 0.01) return a.first > b.first;\n            return a.second < b.second;\n        });\n        \n        vector<int> selected;\n        vector<bool> selected_flag(seed_count, false);\n        \n        for (int d = 0; d < M; d++) {\n            for (int seed_id : dim_top_seeds[d]) {\n                if (!selected_flag[seed_id] && (int)selected.size() < grid_size) {\n                    selected.push_back(seed_id);\n                    selected_flag[seed_id] = true;\n                    break;\n                }\n            }\n        }\n        \n        for (int d = 0; d < M && (int)selected.size() < grid_size - 5; d++) {\n            for (size_t idx = 1; idx < dim_top_seeds[d].size() && (int)selected.size() < grid_size - 5; idx++) {\n                int seed_id = dim_top_seeds[d][idx];\n                if (!selected_flag[seed_id]) {\n                    selected.push_back(seed_id);\n                    selected_flag[seed_id] = true;\n                }\n            }\n        }\n        \n        for (const auto& p : seed_score) {\n            if ((int)selected.size() >= grid_size) break;\n            if (!selected_flag[p.second]) {\n                selected.push_back(p.second);\n                selected_flag[p.second] = true;\n            }\n        }\n        \n        auto calc_offspring_potential = [&](int i, int j) -> int {\n            int potential = 0;\n            for (int d = 0; d < M; d++) {\n                potential += max(X[i][d], X[j][d]);\n            }\n            return potential;\n        };\n        \n        auto calc_compatibility = [&](int i, int j) -> double {\n            double comp = 0;\n            for (int d = 0; d < M; d++) {\n                comp += (X[i][d] + X[j][d]) / 2.0;\n            }\n            return comp;\n        };\n        \n        // Calculate position priorities\n        vector<Position> positions;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int neighbors = 0;\n                const int di[] = {-1, 1, 0, 0};\n                const int dj[] = {0, 0, -1, 1};\n                for (int dir = 0; dir < 4; dir++) {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        neighbors++;\n                    }\n                }\n                int center_dist = abs(i - N/2) + abs(j - N/2);\n                positions.push_back({neighbors * 10 - center_dist, i, j});\n            }\n        }\n        sort(positions.begin(), positions.end(), [](const Position& a, const Position& b) {\n            return a.priority > b.priority;\n        });\n        \n        // Find max total for swap heuristic\n        int max_total = 0;\n        for (int si : selected) {\n            max_total = max(max_total, seed_total[si]);\n        }\n        \n        vector<vector<int>> best_A;\n        int best_potential = -1;\n        \n        // Try multiple placement strategies\n        int num_attempts = max(3, 6 - turn); // More attempts in early turns\n        \n        for (int attempt = 0; attempt < num_attempts; attempt++) {\n            vector<vector<int>> A(N, vector<int>(N, -1));\n            vector<bool> placed(selected.size(), false);\n            \n            // Create seed ordering - varies by attempt\n            vector<pair<int, int>> seed_order;\n            for (size_t i = 0; i < selected.size(); i++) {\n                int base_score = seed_total[selected[i]];\n                // Add variation based on attempt\n                if (attempt > 0) {\n                    base_score += (int)(rng() % 500);\n                }\n                seed_order.push_back({base_score, (int)i});\n            }\n            \n            if (attempt == 0) {\n                // Sort by total value (greedy)\n                sort(seed_order.begin(), seed_order.end(), greater<pair<int,int>>());\n            } else if (attempt == 1) {\n                // Sort by dimensional excellence\n                sort(seed_order.begin(), seed_order.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n                    int exc_a = 0, exc_b = 0;\n                    for (int d = 0; d < M; d++) {\n                        if (X[selected[a.second]][d] == dim_max[d]) exc_a++;\n                        if (X[selected[b.second]][d] == dim_max[d]) exc_b++;\n                    }\n                    return exc_a > exc_b;\n                });\n            } else {\n                // Mixed ordering with randomness\n                shuffle(seed_order.begin(), seed_order.end(), rng);\n            }\n            \n            // Place seeds\n            for (size_t idx = 0; idx < seed_order.size(); idx++) {\n                int si = seed_order[idx].second;\n                int seed_id = selected[si];\n                \n                if (placed[si]) continue;\n                \n                int best_pos_idx = -1;\n                double best_pos_score = -1e9;\n                \n                for (size_t pidx = 0; pidx < positions.size(); pidx++) {\n                    int pi = positions[pidx].i;\n                    int pj = positions[pidx].j;\n                    if (A[pi][pj] != -1) continue;\n                    \n                    double pos_score = 0;\n                    int neighbor_count = 0;\n                    int max_pot = 0;\n                    \n                    const int di[] = {-1, 1, 0, 0};\n                    const int dj[] = {0, 0, -1, 1};\n                    \n                    for (int dir = 0; dir < 4; dir++) {\n                        int ni = pi + di[dir];\n                        int nj = pj + dj[dir];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1) {\n                            pos_score += calc_compatibility(seed_id, A[ni][nj]);\n                            max_pot = max(max_pot, calc_offspring_potential(seed_id, A[ni][nj]));\n                            neighbor_count++;\n                        }\n                    }\n                    \n                    if (neighbor_count > 0) {\n                        pos_score /= neighbor_count;\n                        pos_score += max_pot * 0.002;\n                    }\n                    \n                    int available = 0;\n                    for (int dir = 0; dir < 4; dir++) {\n                        int ni = pi + di[dir];\n                        int nj = pj + dj[dir];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] == -1) {\n                            available++;\n                        }\n                    }\n                    pos_score += available * 0.3;\n                    \n                    // Add small randomness for exploration\n                    if (attempt > 0) {\n                        pos_score += (double)(rng() % 100) / 1000.0;\n                    }\n                    \n                    if (pos_score > best_pos_score) {\n                        best_pos_score = pos_score;\n                        best_pos_idx = (int)pidx;\n                    }\n                }\n                \n                if (best_pos_idx >= 0) {\n                    A[positions[best_pos_idx].i][positions[best_pos_idx].j] = seed_id;\n                    placed[si] = true;\n                }\n            }\n            \n            // Fill remaining\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1) {\n                        for (size_t si = 0; si < selected.size(); si++) {\n                            if (!placed[si]) {\n                                A[i][j] = selected[si];\n                                placed[si] = true;\n                                goto filled;\n                            }\n                        }\n                        filled:;\n                    }\n                }\n            }\n            \n            // Calculate initial potential\n            int current_potential = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1) continue;\n                    if (j + 1 < N && A[i][j+1] != -1) {\n                        current_potential += calc_offspring_potential(A[i][j], A[i][j+1]);\n                    }\n                    if (i + 1 < N && A[i+1][j] != -1) {\n                        current_potential += calc_offspring_potential(A[i][j], A[i+1][j]);\n                    }\n                }\n            }\n            \n            // Local optimization with swaps\n            bool improved = true;\n            int max_swaps = 50 + turn * 5; // More swaps in later turns\n            int swap_count = 0;\n            \n            while (improved && swap_count < max_swaps) {\n                improved = false;\n                swap_count++;\n                \n                // Recalculate current potential\n                current_potential = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] == -1) continue;\n                        if (j + 1 < N && A[i][j+1] != -1) {\n                            current_potential += calc_offspring_potential(A[i][j], A[i][j+1]);\n                        }\n                        if (i + 1 < N && A[i+1][j] != -1) {\n                            current_potential += calc_offspring_potential(A[i][j], A[i+1][j]);\n                        }\n                    }\n                }\n                \n                // Try all pairs of positions\n                for (int i1 = 0; i1 < N && !improved; i1++) {\n                    for (int j1 = 0; j1 < N && !improved; j1++) {\n                        for (int i2 = i1; i2 < N && !improved; i2++) {\n                            for (int j2 = (i2 == i1 ? j1 + 1 : 0); j2 < N && !improved; j2++) {\n                                if (A[i1][j1] == -1 || A[i2][j2] == -1) continue;\n                                if (i1 == i2 && j1 == j2) continue;\n                                \n                                // Focus on high-value seeds\n                                int total1 = seed_total[A[i1][j1]];\n                                int total2 = seed_total[A[i2][j2]];\n                                if (total1 < max_total * 0.6 && total2 < max_total * 0.6) continue;\n                                \n                                swap(A[i1][j1], A[i2][j2]);\n                                \n                                int new_potential = 0;\n                                for (int i = 0; i < N; i++) {\n                                    for (int j = 0; j < N; j++) {\n                                        if (A[i][j] == -1) continue;\n                                        if (j + 1 < N && A[i][j+1] != -1) {\n                                            new_potential += calc_offspring_potential(A[i][j], A[i][j+1]);\n                                        }\n                                        if (i + 1 < N && A[i+1][j] != -1) {\n                                            new_potential += calc_offspring_potential(A[i][j], A[i+1][j]);\n                                        }\n                                    }\n                                }\n                                \n                                if (new_potential > current_potential) {\n                                    current_potential = new_potential;\n                                    improved = true;\n                                } else {\n                                    swap(A[i1][j1], A[i2][j2]);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (current_potential > best_potential) {\n                best_potential = current_potential;\n                best_A = A;\n            }\n        }\n        \n        // Output the best grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << best_A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds\n        vector<pair<int, int>> new_totals;\n        \n        for (int i = 0; i < seed_count; i++) {\n            int total = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                total += X[i][j];\n                global_max[j] = max(global_max[j], X[i][j]);\n            }\n            new_totals.push_back({total, i});\n        }\n        \n        sort(new_totals.begin(), new_totals.end(), greater<pair<int,int>>());\n        prev_best_seeds.clear();\n        for (int i = 0; i < min(15, seed_count); i++) {\n            prev_best_seeds.push_back(new_totals[i].second);\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n    bool operator<(const Point& o) const {\n        if (x != o.x) return x < o.x;\n        return y < o.y;\n    }\n};\n\nint dist(Point a, Point b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> S(N), T(N);\n    for (int i = 0; i < N; i++) cin >> S[i];\n    for (int i = 0; i < N; i++) cin >> T[i];\n    \n    vector<Point> sources, targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (S[i][j] == '1') sources.push_back({i, j});\n            if (T[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n    \n    // Design arm: star topology with varying edge lengths\n    int V_prime = min(V, (int)sources.size() + 1);\n    if (V_prime < 2) V_prime = 2;\n    int num_fingertips = V_prime - 1;\n    \n    cout << V_prime << \"\\n\";\n    vector<int> edge_len(V_prime, 0);\n    for (int i = 1; i < V_prime; i++) {\n        edge_len[i] = (i - 1) % (N - 1) + 1;\n        cout << 0 << \" \" << edge_len[i] << \"\\n\";\n    }\n    \n    // Find good initial root position (center of sources)\n    int sum_x = 0, sum_y = 0;\n    for (auto& p : sources) {\n        sum_x += p.x;\n        sum_y += p.y;\n    }\n    int root_x = sum_x / M;\n    int root_y = sum_y / M;\n    root_x = max(0, min(N - 1, root_x));\n    root_y = max(0, min(N - 1, root_y));\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Grid state tracking\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = (S[i][j] == '1' ? 1 : 0);\n        }\n    }\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            is_target[i][j] = (T[i][j] == '1' ? 1 : 0);\n        }\n    }\n    \n    // Fingertip state\n    vector<int> fp_dir(num_fingertips, 0);  // 0:R, 1:D, 2:L, 3:U\n    vector<bool> fp_holding(num_fingertips, false);\n    \n    auto get_fp_pos = [&](int fp_idx) -> Point {\n        int d = fp_dir[fp_idx];\n        return {root_x + DX[d] * edge_len[fp_idx + 1], \n                root_y + DY[d] * edge_len[fp_idx + 1]};\n    };\n    \n    auto in_bounds = [&](Point p) -> bool {\n        return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n    };\n    \n    auto can_pick = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 1;\n    };\n    \n    auto can_place = [&](Point p) -> bool {\n        return in_bounds(p) && grid[p.x][p.y] == 0;\n    };\n    \n    vector<string> commands;\n    int turns = 0;\n    int delivered = 0;\n    \n    // Create source-target matching (greedy by distance)\n    vector<bool> src_used(sources.size(), false);\n    vector<bool> tgt_used(targets.size(), false);\n    vector<pair<int, int>> pairs;\n    \n    for (int iter = 0; iter < M; iter++) {\n        int best_si = -1, best_ti = -1, best_d = 1e9;\n        for (int i = 0; i < (int)sources.size(); i++) {\n            if (src_used[i]) continue;\n            for (int j = 0; j < (int)targets.size(); j++) {\n                if (tgt_used[j]) continue;\n                int d = dist(sources[i], targets[j]);\n                if (d < best_d) {\n                    best_d = d;\n                    best_si = i;\n                    best_ti = j;\n                }\n            }\n        }\n        if (best_si >= 0) {\n            src_used[best_si] = true;\n            tgt_used[best_ti] = true;\n            pairs.push_back({best_si, best_ti});\n        }\n    }\n    \n    // Process pairs using multiple fingertips in parallel\n    int pair_idx = 0;\n    vector<int> fp_task(num_fingertips, -1);  // Which pair each fingertip is handling\n    \n    while ((pair_idx < (int)pairs.size() || \n           count(fp_task.begin(), fp_task.end(), -1) < num_fingertips) && \n           turns < 99000) {\n        \n        string cmd(V_prime * 2, '.');\n        bool action_taken = false;\n        \n        // Assign new tasks to idle fingertips\n        for (int fp = 0; fp < num_fingertips && pair_idx < (int)pairs.size(); fp++) {\n            if (fp_task[fp] == -1 && !fp_holding[fp]) {\n                fp_task[fp] = pair_idx++;\n            }\n        }\n        \n        // Process each fingertip\n        for (int fp = 0; fp < num_fingertips; fp++) {\n            if (fp_task[fp] == -1) continue;\n            \n            int si = pairs[fp_task[fp]].first;\n            int ti = pairs[fp_task[fp]].second;\n            Point src = sources[si];\n            Point tgt = targets[ti];\n            \n            if (!fp_holding[fp]) {\n                // Need to pick up from source\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == src && can_pick(src)) {\n                    // Pick up\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = true;\n                    grid[src.x][src.y] = 0;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach source\n                    int target_rx = src.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = src.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == src.x && ty == src.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            } else {\n                // Need to deliver to target\n                Point fp_pos = get_fp_pos(fp);\n                \n                if (fp_pos == tgt && can_place(tgt) && is_target[tgt.x][tgt.y]) {\n                    // Place\n                    cmd[V_prime + fp + 1] = 'P';\n                    fp_holding[fp] = false;\n                    grid[tgt.x][tgt.y] = 1;\n                    fp_task[fp] = -1;\n                    delivered++;\n                    action_taken = true;\n                } else {\n                    // Move root to position where fingertip can reach target\n                    int target_rx = tgt.x - DX[fp_dir[fp]] * edge_len[fp + 1];\n                    int target_ry = tgt.y - DY[fp_dir[fp]] * edge_len[fp + 1];\n                    target_rx = max(0, min(N - 1, target_rx));\n                    target_ry = max(0, min(N - 1, target_ry));\n                    \n                    if (root_x < target_rx) {\n                        cmd[0] = 'D';\n                        root_x++;\n                    } else if (root_x > target_rx) {\n                        cmd[0] = 'U';\n                        root_x--;\n                    } else if (root_y < target_ry) {\n                        cmd[0] = 'R';\n                        root_y++;\n                    } else if (root_y > target_ry) {\n                        cmd[0] = 'L';\n                        root_y--;\n                    }\n                    \n                    // Rotate if needed\n                    int need_dir = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int tx = root_x + DX[d] * edge_len[fp + 1];\n                        int ty = root_y + DY[d] * edge_len[fp + 1];\n                        if (tx == tgt.x && ty == tgt.y) {\n                            need_dir = d;\n                            break;\n                        }\n                    }\n                    if (need_dir >= 0 && need_dir != fp_dir[fp]) {\n                        int diff = (need_dir - fp_dir[fp] + 4) % 4;\n                        cmd[fp + 1] = (diff == 1 ? 'R' : (diff == 3 ? 'L' : '.'));\n                        if (cmd[fp + 1] != '.') {\n                            fp_dir[fp] = need_dir;\n                        }\n                    }\n                    action_taken = true;\n                }\n            }\n        }\n        \n        // If no fingertips active, try to activate more\n        if (!action_taken) {\n            bool found = false;\n            for (int fp = 0; fp < num_fingertips && !found; fp++) {\n                if (fp_task[fp] == -1 && pair_idx < (int)pairs.size()) {\n                    fp_task[fp] = pair_idx++;\n                    found = true;\n                }\n            }\n            if (!found) break;\n            continue;\n        }\n        \n        commands.push_back(cmd);\n        turns++;\n    }\n    \n    // Output all commands\n    for (const string& c : commands) {\n        cout << c << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\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\nstruct GridCell {\n    int m;\n    int s;\n    int score() const { return m - s; }\n};\n\n// Global data\nint GW, GH;\nint CELL_SIZE;\nvector<vector<GridCell>> grid;\nvector<vector<bool>> selected;\nvector<Point> mackerels, sardines;\n\n// Directions\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {-1, 0, 1, 0};\n\nstruct PQElement {\n    int r, c;\n    int score;\n    bool operator<(const PQElement& other) const {\n        return score < other.score;\n    }\n};\n\n// Time tracking\nchrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 1.82;\n\ndouble getElapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\nbool timeRemaining() {\n    return getElapsed() < TIME_LIMIT;\n}\n\n// Initialize grid\nvoid initGrid(int cell_size) {\n    CELL_SIZE = cell_size;\n    GW = MAX_COORD / CELL_SIZE + 1;\n    GH = MAX_COORD / CELL_SIZE + 1;\n    \n    grid.assign(GH, vector<GridCell>(GW, {0, 0}));\n    selected.assign(GH, vector<bool>(GW, false));\n    \n    for (const auto& p : mackerels) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].m++;\n        }\n    }\n    for (const auto& p : sardines) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].s++;\n        }\n    }\n}\n\n// Build polygon from selected cells\nvector<Point> buildPolygonFromCells() {\n    struct Edge {\n        int x1, y1, x2, y2;\n    };\n    \n    vector<Edge> edges;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                int x1 = c * CELL_SIZE;\n                int y1 = r * CELL_SIZE;\n                int x2 = (c + 1) * CELL_SIZE;\n                int y2 = (r + 1) * CELL_SIZE;\n                \n                if (r == 0 || !selected[r-1][c]) edges.push_back({x1, y1, x2, y1});\n                if (r == GH - 1 || !selected[r+1][c]) edges.push_back({x1, y2, x2, y2});\n                if (c == 0 || !selected[r][c-1]) edges.push_back({x1, y1, x1, y2});\n                if (c == GW - 1 || !selected[r][c+1]) edges.push_back({x2, y1, x2, y2});\n            }\n        }\n    }\n    \n    if (edges.empty()) return {};\n    \n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    for (const auto& e : edges) {\n        adj[{e.x1, e.y1}].push_back({e.x2, e.y2});\n        adj[{e.x2, e.y2}].push_back({e.x1, e.y1});\n    }\n    \n    Point start = {edges[0].x1, edges[0].y1};\n    for (const auto& e : edges) {\n        for (int k = 0; k < 2; k++) {\n            Point p = {k == 0 ? e.x1 : e.x2, k == 0 ? e.y1 : e.y2};\n            if (p.y < start.y || (p.y == start.y && p.x < start.x)) {\n                start = p;\n            }\n        }\n    }\n    \n    vector<Point> poly;\n    Point current = start;\n    Point prev = {-1000000, -1000000};\n    \n    for (int iter = 0; iter < (int)edges.size() * 2 + 10; ++iter) {\n        poly.push_back(current);\n        \n        auto it = adj.find({current.x, current.y});\n        if (it == adj.end()) break;\n        \n        Point next = {-1, -1};\n        long long best_cross = (long long)4e18;\n        \n        for (const auto& neighbor : it->second) {\n            Point np = {neighbor.first, neighbor.second};\n            if (np.x == prev.x && np.y == prev.y) continue;\n            \n            long long dx1 = current.x - prev.x;\n            long long dy1 = current.y - prev.y;\n            long long dx2 = np.x - current.x;\n            long long dy2 = np.y - current.y;\n            long long cross = dx1 * dy2 - dy1 * dx2;\n            \n            if (next.x == -1 || cross < best_cross) {\n                next = np;\n                best_cross = cross;\n            }\n        }\n        \n        if (next.x == -1) break;\n        if (next.x == start.x && next.y == start.y && poly.size() > 3) break;\n        \n        prev = current;\n        current = next;\n    }\n    \n    if (poly.size() > 1 && poly.front() == poly.back()) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Simplify polygon\nvector<Point> simplifyPolygon(const vector<Point>& poly) {\n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> result;\n    result.push_back(poly[0]);\n    \n    for (size_t i = 1; i < poly.size() - 1; ++i) {\n        Point p1 = result.back();\n        Point p2 = poly[i];\n        Point p3 = poly[i + 1];\n        \n        bool collinear = (p1.x == p2.x && p2.x == p3.x) || (p1.y == p2.y && p2.y == p3.y);\n        if (!collinear) result.push_back(p2);\n    }\n    \n    result.push_back(poly.back());\n    \n    vector<Point> final_result;\n    for (const auto& p : result) {\n        if (final_result.empty() || final_result.back() != p) {\n            final_result.push_back(p);\n        }\n    }\n    \n    return final_result;\n}\n\n// Calculate score from grid (fast)\nlong long calculateGridScore() {\n    long long score = 0;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                score += grid[r][c].score();\n            }\n        }\n    }\n    return max(0LL, score + 1);\n}\n\n// Calculate exact score using point-in-polygon\nbool isInside(const vector<Point>& poly, int px, int py) {\n    if (poly.size() < 3) return false;\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        \n        if (xi == xj && px == xi && py >= min(yi, yj) && py <= max(yi, yj)) return true;\n        if (yi == yj && py == yi && px >= min(xi, xj) && px <= max(xi, xj)) return true;\n\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\nlong long calculateExactScore(const vector<Point>& poly) {\n    if (poly.size() < 4) return 0;\n    \n    long long a = 0, b = 0;\n    for (const auto& p : mackerels) {\n        if (isInside(poly, p.x, p.y)) a++;\n    }\n    for (const auto& p : sardines) {\n        if (isInside(poly, p.x, p.y)) b++;\n    }\n    return max(0LL, a - b + 1);\n}\n\n// Validate polygon\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4 || poly.size() > MAX_VERTICES) return false;\n    \n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        \n        if (p1.x != p2.x && p1.y != p2.y) return false;\n        if (p1 == p2) return false;\n        if (p1.x < 0 || p1.x > MAX_COORD || p1.y < 0 || p1.y > MAX_COORD) return false;\n    }\n    \n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    \n    return perim <= MAX_PERIMETER;\n}\n\n// Calculate perimeter of selected region\nlong long calculatePerimeter() {\n    long long perim = 0;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                if (r == 0 || !selected[r-1][c]) perim += CELL_SIZE;\n                if (r == GH - 1 || !selected[r+1][c]) perim += CELL_SIZE;\n                if (c == 0 || !selected[r][c-1]) perim += CELL_SIZE;\n                if (c == GW - 1 || !selected[r][c+1]) perim += CELL_SIZE;\n            }\n        }\n    }\n    return perim;\n}\n\n// Fast cell-in-polygon check\nbool cellInsidePolygon(int r, int c, int cell_size, const vector<Point>& poly) {\n    if (poly.size() < 3) return false;\n    int px = c * cell_size + cell_size / 2;\n    int py = r * cell_size + cell_size / 2;\n    \n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Grow region\nvector<Point> growRegion(int start_r, int start_c, int cell_size, int negative_threshold = 0) {\n    initGrid(cell_size);\n    \n    for (int r = 0; r < GH; ++r)\n        for (int c = 0; c < GW; ++c)\n            selected[r][c] = false;\n    \n    if (start_r < 0 || start_r >= GH || start_c < 0 || start_c >= GW) return {};\n    \n    selected[start_r][start_c] = true;\n    \n    priority_queue<PQElement> pq;\n    vector<vector<bool>> in_pq(GH, vector<bool>(GW, false));\n    \n    auto addNeighbors = [&](int r, int c) {\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc] && !in_pq[nr][nc]) {\n                in_pq[nr][nc] = true;\n                pq.push({nr, nc, grid[nr][nc].score()});\n            }\n        }\n    };\n    \n    addNeighbors(start_r, start_c);\n    \n    long long current_perimeter = 4LL * CELL_SIZE;\n    \n    int check_interval = 50;\n    int checks = 0;\n    while (!pq.empty()) {\n        if (++checks % check_interval == 0 && !timeRemaining()) break;\n        \n        PQElement top = pq.top();\n        pq.pop();\n        \n        int r = top.r, c = top.c;\n        if (selected[r][c]) continue;\n        if (grid[r][c].score() < negative_threshold) continue;\n        \n        int shared = 0;\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                shared++;\n            }\n        }\n        long long new_perimeter = current_perimeter + 4LL * CELL_SIZE - 2LL * shared * CELL_SIZE;\n        \n        if (new_perimeter > MAX_PERIMETER - 100) continue;\n        \n        selected[r][c] = true;\n        current_perimeter = new_perimeter;\n        \n        addNeighbors(r, c);\n    }\n    \n    vector<Point> poly = buildPolygonFromCells();\n    poly = simplifyPolygon(poly);\n    \n    return poly;\n}\n\n// Minimal local search\nvector<Point> localSearch(vector<Point> poly, int cell_size, int max_iters) {\n    if (poly.size() < 4 || !timeRemaining() || max_iters <= 0) return poly;\n    \n    initGrid(cell_size);\n    for (int r = 0; r < GH; ++r)\n        for (int c = 0; c < GW; ++c)\n            selected[r][c] = false;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (cellInsidePolygon(r, c, cell_size, poly)) {\n                selected[r][c] = true;\n            }\n        }\n    }\n    \n    long long best_score = calculateGridScore();\n    \n    for (int iter = 0; iter < max_iters; ++iter) {\n        if (!timeRemaining()) break;\n        \n        bool improved = false;\n        \n        // Try adding boundary cells with positive score\n        for (int r = 0; r < GH && !improved; ++r) {\n            for (int c = 0; c < GW && !improved; ++c) {\n                if (selected[r][c]) continue;\n                if (grid[r][c].score() <= 0) continue;\n                \n                bool adjacent = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DY[i];\n                    int nc = c + DX[i];\n                    if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                        adjacent = true;\n                        break;\n                    }\n                }\n                if (!adjacent) continue;\n                \n                selected[r][c] = true;\n                long long new_perim = calculatePerimeter();\n                if (new_perim <= MAX_PERIMETER) {\n                    long long new_score = calculateGridScore();\n                    if (new_score > best_score) {\n                        best_score = new_score;\n                        improved = true;\n                    } else {\n                        selected[r][c] = false;\n                    }\n                } else {\n                    selected[r][c] = false;\n                }\n            }\n        }\n        \n        if (improved) continue;\n        \n        // Try removing boundary cells with negative score\n        for (int r = 0; r < GH && !improved; ++r) {\n            for (int c = 0; c < GW && !improved; ++c) {\n                if (!selected[r][c]) continue;\n                if (grid[r][c].score() >= 0) continue;\n                \n                bool on_boundary = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DY[i];\n                    int nc = c + DX[i];\n                    if (nr < 0 || nr >= GH || nc < 0 || nc >= GW || !selected[nr][nc]) {\n                        on_boundary = true;\n                        break;\n                    }\n                }\n                if (!on_boundary) continue;\n                \n                selected[r][c] = false;\n                long long new_score = calculateGridScore();\n                if (new_score >= best_score) {\n                    best_score = new_score;\n                    improved = true;\n                } else {\n                    selected[r][c] = true;\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    poly = buildPolygonFromCells();\n    poly = simplifyPolygon(poly);\n    \n    return poly;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    start_time = chrono::high_resolution_clock::now();\n\n    int 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    vector<Point> best_poly;\n    long long best_score = 0;\n    \n    // Fewer cell sizes for speed\n    vector<int> cell_sizes = {200, 400, 600, 800, 1000, 1500};\n    \n    for (int cell_size : cell_sizes) {\n        if (!timeRemaining()) break;\n        \n        initGrid(cell_size);\n        \n        // Find candidates\n        vector<pair<int, pair<int, int>>> candidates;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                int sc = grid[r][c].score();\n                if (sc >= 0) {\n                    candidates.push_back({sc, {r, c}});\n                }\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<pair<int, pair<int, int>>>());\n        \n        // Very limited starting points\n        int max_starts = min((int)candidates.size(), 12);\n        \n        for (int i = 0; i < max_starts && timeRemaining(); ++i) {\n            int r = candidates[i].second.first;\n            int c = candidates[i].second.second;\n            \n            vector<Point> poly = growRegion(r, c, cell_size, 0);\n            \n            if (validatePolygon(poly)) {\n                long long score = calculateGridScore();\n                if (score > best_score) {\n                    best_score = score;\n                    best_poly = poly;\n                }\n                \n                // Local search only on top 3 candidates with good score\n                if (i < 3 && score >= max(1LL, best_score * 90 / 100)) {\n                    vector<Point> optimized = localSearch(poly, cell_size, 10);\n                    if (validatePolygon(optimized)) {\n                        long long opt_score = calculateGridScore();\n                        if (opt_score > best_score) {\n                            best_score = opt_score;\n                            best_poly = optimized;\n                        }\n                    }\n                }\n            }\n            \n            // Also try with negative threshold for top candidate\n            if (i == 0 && timeRemaining()) {\n                vector<Point> poly2 = growRegion(r, c, cell_size, -2);\n                if (validatePolygon(poly2)) {\n                    long long score2 = calculateGridScore();\n                    if (score2 > best_score) {\n                        best_score = score2;\n                        best_poly = poly2;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback\n    if (best_poly.size() < 4) {\n        initGrid(500);\n        int best_r = 0, best_c = 0, best_cell_score = -1e9;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                if (grid[r][c].score() > best_cell_score) {\n                    best_cell_score = grid[r][c].score();\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        best_poly = {\n            {best_c * 500, best_r * 500},\n            {(best_c + 1) * 500, best_r * 500},\n            {(best_c + 1) * 500, (best_r + 1) * 500},\n            {best_c * 500, (best_r + 1) * 500}\n        };\n    }\n    \n    if (!validatePolygon(best_poly)) {\n        best_poly = {{0, 0}, {500, 0}, {500, 500}, {0, 500}};\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>\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n    double aspect;\n    long long area;\n};\n\nstruct Placement {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n};\n\nstruct Solution {\n    vector<Placement> placements;\n    long long estimated_score;\n    long long measured_score;\n    int turn_found;\n};\n\nint N;\nvector<Rectangle> rects;\nvector<Placement> placements;\nvector<pair<int, int>> pos;\nvector<pair<int, int>> dim;\n\nstruct TabuEntry {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n    int expire_turn;\n};\nvector<TabuEntry> tabu_list;\nint tabu_tenure = 5;\n\nvoid clear_state() {\n    placements.clear();\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n}\n\nvoid add_placement(int rect_id, int rotation, char direction, int base) {\n    placements.push_back({rect_id, rotation, direction, base});\n}\n\npair<int, int> simulate_fast() {\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n    int max_x = 0, max_y = 0;\n    \n    for (size_t idx = 0; idx < placements.size(); idx++) {\n        const auto& p = placements[idx];\n        int w = rects[p.rect_id].w_obs;\n        int h = rects[p.rect_id].h_obs;\n        \n        if (p.rotation == 1) swap(w, h);\n        dim[p.rect_id] = {w, h};\n        \n        int x = 0, y = 0;\n        \n        if (p.direction == 'U') {\n            if (p.base == -1) {\n                x = 0;\n            } else {\n                x = pos[p.base].first + dim[p.base].first;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            if (p.base == -1) {\n                y = 0;\n            } else {\n                y = pos[p.base].second + dim[p.base].second;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        pos[p.rect_id] = {x, y};\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\nbool is_tabu(int rect_id, int rotation, char direction, int base, int current_turn) {\n    for (const auto& t : tabu_list) {\n        if (t.rect_id == rect_id && t.expire_turn > current_turn) {\n            if (t.rotation == rotation && t.direction == direction && t.base == base) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nvoid add_tabu(int rect_id, int rotation, char direction, int base, int current_turn) {\n    tabu_list.push_back({rect_id, rotation, direction, base, current_turn + tabu_tenure});\n    if (tabu_list.size() > 120) {\n        tabu_list.erase(tabu_list.begin(), tabu_list.begin() + 60);\n    }\n}\n\n// Get boundary rectangles (those touching max_x or max_y)\nvector<int> get_boundary_rects(int max_x, int max_y) {\n    vector<int> boundary;\n    int tolerance = 1000;\n    for (int i = 0; i < N; i++) {\n        if (pos[i].first >= 0) {\n            if (pos[i].first + dim[i].first >= max_x - tolerance ||\n                pos[i].second + dim[i].second >= max_y - tolerance) {\n                boundary.push_back(i);\n            }\n        }\n    }\n    return boundary;\n}\n\nvector<int> get_candidate_bases(int rect_idx, int max_candidates, int strategy = 0, \n                                  int current_max_x = 0, int current_max_y = 0) {\n    vector<int> candidates;\n    candidates.push_back(-1);\n    \n    if (rect_idx == 0) return candidates;\n    \n    vector<pair<long long, int>> scored_bases;\n    for (int i = 0; i < rect_idx && i < N; i++) {\n        if (pos[i].first >= 0) {\n            long long score;\n            if (strategy == 0) {\n                // Corner preference\n                score = (long long)pos[i].first + pos[i].second;\n            } else if (strategy == 1) {\n                // Area preference\n                score = -(long long)dim[i].first * dim[i].second;\n            } else if (strategy == 2) {\n                // Dimension matching\n                int w = rects[rect_idx].w_obs, h = rects[rect_idx].h_obs;\n                score = -abs(dim[i].first - w) - abs(dim[i].second - h);\n            } else {\n                // Boundary preference (prefer rectangles at packaging boundary)\n                bool at_boundary = (pos[i].first + dim[i].first >= current_max_x - 5000) ||\n                                   (pos[i].second + dim[i].second >= current_max_y - 5000);\n                score = at_boundary ? -1000000 : ((long long)pos[i].first + pos[i].second);\n            }\n            scored_bases.push_back({score, i});\n        }\n    }\n    \n    sort(scored_bases.begin(), scored_bases.end());\n    \n    for (int i = 0; i < min((int)scored_bases.size(), max_candidates - 1); i++) {\n        candidates.push_back(scored_bases[i].second);\n    }\n    \n    return candidates;\n}\n\nlong long evaluate_placement() {\n    auto dims = simulate_fast();\n    long long score = (long long)dims.first + dims.second;\n    long long diff = abs(dims.first - dims.second);\n    score += diff / 10;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto get_elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    rects.resize(N);\n    long long total_area = 0;\n    int max_dim = 0;\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n        rects[i].aspect = (double)rects[i].w_obs / rects[i].h_obs;\n        rects[i].area = (long long)rects[i].w_obs * rects[i].h_obs;\n        total_area += rects[i].area;\n        max_dim = max(max_dim, max(rects[i].w_obs, rects[i].h_obs));\n    }\n    \n    vector<Solution> population;\n    Solution best_solution;\n    best_solution.measured_score = LLONG_MAX;\n    best_solution.turn_found = -1;\n    \n    // Multiple random seeds for diversity\n    vector<mt19937> rngs;\n    for (int s = 0; s < 3; s++) {\n        rngs.push_back(mt19937(chrono::steady_clock::now().time_since_epoch().count() + s * 1000));\n    }\n    int rng_index = 0;\n    auto& rng = rngs[rng_index];\n    \n    const double TIME_LIMIT = 2.7;\n    \n    int phase1_end = (int)(T * 0.30);  // Exploration\n    int phase2_end = (int)(T * 0.65);  // Intensive SA\n    // phase3: exploitation (35% of turns)\n    \n    int last_improvement_turn = 0;\n    int consecutive_no_improve = 0;\n    \n    for (int turn = 0; turn < T; turn++) {\n        if (get_elapsed() > TIME_LIMIT) {\n            break;\n        }\n        \n        clear_state();\n        \n        double time_remaining = TIME_LIMIT - get_elapsed();\n        \n        // Switch random seed periodically for diversity\n        if (turn > 0 && turn % 10 == 0) {\n            rng_index = (rng_index + 1) % 3;\n        }\n        \n        // Phase 3: Pure exploitation\n        if (turn >= phase2_end) {\n            if (!best_solution.placements.empty()) {\n                placements = best_solution.placements;\n                cout << \"# Turn \" << turn << \" (exploit) best=\" << best_solution.measured_score << \"\\n\";\n                cout << N << \"\\n\";\n                for (const auto& p : placements) {\n                    cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n                }\n                cout.flush();\n                \n                int W_meas, H_meas;\n                cin >> W_meas >> H_meas;\n                long long measured_score = (long long)W_meas + H_meas;\n                \n                if (measured_score < best_solution.measured_score) {\n                    best_solution.measured_score = measured_score;\n                    cout << \"# Updated best: \" << measured_score << \"\\n\";\n                }\n            }\n            continue;\n        }\n        \n        // Adaptive parameters\n        int strategy;\n        int max_bases;\n        int sa_iters;\n        double initial_temp;\n        double cooling_rate;\n        \n        if (turn < phase1_end) {\n            strategy = turn % 4;\n            max_bases = 12;\n            sa_iters = 40;\n            initial_temp = 1200.0;\n            cooling_rate = 0.91;\n        } else {\n            strategy = (turn - phase1_end) % 4;\n            \n            if (turn - last_improvement_turn <= 3) {\n                max_bases = 14;\n                sa_iters = 80;\n                cooling_rate = 0.96;\n            } else if (turn - last_improvement_turn <= 6) {\n                max_bases = 10;\n                sa_iters = 60;\n                cooling_rate = 0.94;\n            } else {\n                max_bases = 8;\n                sa_iters = 50;\n                cooling_rate = 0.92;\n            }\n            initial_temp = 700.0;\n            \n            // Population restart with rotation\n            if (!population.empty() && turn % 2 == 0) {\n                int selection = uniform_int_distribution<>(0, 100)(rng);\n                if (selection < 50 && population.size() >= 1) {\n                    placements = population[0].placements;  // Best\n                } else if (selection < 80 && population.size() >= 2) {\n                    placements = population[uniform_int_distribution<>(0, 1)(rng)].placements;\n                } else if (population.size() >= 1) {\n                    // Mutated version of best\n                    placements = population[0].placements;\n                    int num_mutations = uniform_int_distribution<>(1, N/4)(rng);\n                    for (int m = 0; m < num_mutations; m++) {\n                        int idx = uniform_int_distribution<>(0, N-1)(rng);\n                        int mut_type = uniform_int_distribution<>(0, 2)(rng);\n                        if (mut_type == 0) {\n                            placements[idx].rotation = 1 - placements[idx].rotation;\n                        } else if (mut_type == 1) {\n                            placements[idx].direction = (placements[idx].direction == 'U') ? 'L' : 'U';\n                        } else {\n                            placements[idx].base = -1;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Greedy construction if not restarting\n        if (placements.empty() || (int)placements.size() != N) {\n            clear_state();\n            for (int i = 0; i < N; i++) {\n                int best_rot = 0;\n                char best_dir = 'U';\n                int best_base = -1;\n                long long best_local = LLONG_MAX;\n                \n                auto dims = simulate_fast();\n                vector<int> bases = get_candidate_bases(i, max_bases, strategy, dims.first, dims.second);\n                \n                for (int rot = 0; rot < 2; rot++) {\n                    for (char dir : {'U', 'L'}) {\n                        for (int base : bases) {\n                            if (is_tabu(i, rot, dir, base, turn)) continue;\n                            \n                            add_placement(i, rot, dir, base);\n                            long long score = evaluate_placement();\n                            \n                            if (score < best_local) {\n                                best_local = score;\n                                best_rot = rot;\n                                best_dir = dir;\n                                best_base = base;\n                            }\n                            \n                            placements.pop_back();\n                        }\n                    }\n                }\n                \n                add_placement(i, best_rot, best_dir, best_base);\n            }\n        }\n        \n        // Get current bounding box for boundary detection\n        auto current_dims = simulate_fast();\n        int current_max_x = current_dims.first;\n        int current_max_y = current_dims.second;\n        \n        // Get boundary rectangles for focused modification\n        vector<int> boundary_rects = get_boundary_rects(current_max_x, current_max_y);\n        \n        // Simulated Annealing with Tabu\n        double temperature = initial_temp;\n        long long current_score = evaluate_placement();\n        int actual_sa_iters = min(sa_iters, (int)(time_remaining * 150));\n        \n        for (int sa_iter = 0; sa_iter < actual_sa_iters; sa_iter++) {\n            temperature *= cooling_rate;\n            \n            // Select rectangle to modify (bias toward boundary)\n            int i;\n            if (!boundary_rects.empty() && uniform_real_distribution<>(0, 1)(rng) < 0.75) {\n                i = boundary_rects[uniform_int_distribution<>(0, (int)boundary_rects.size()-1)(rng)];\n            } else {\n                i = uniform_int_distribution<>(0, N-1)(rng);\n            }\n            \n            int orig_rot = placements[i].rotation;\n            char orig_dir = placements[i].direction;\n            int orig_base = placements[i].base;\n            \n            int move_type = uniform_int_distribution<>(0, 2)(rng);\n            vector<int> test_bases = get_candidate_bases(i, 6, strategy, current_max_x, current_max_y);\n            \n            long long new_score = LLONG_MAX;\n            int new_rot = orig_rot;\n            char new_dir = orig_dir;\n            int new_base = orig_base;\n            \n            if (move_type == 0) {\n                int try_rot = 1 - orig_rot;\n                if (!is_tabu(i, try_rot, orig_dir, orig_base, turn)) {\n                    placements[i].rotation = try_rot;\n                    new_score = evaluate_placement();\n                    new_rot = try_rot;\n                }\n            } else if (move_type == 1) {\n                char try_dir = (orig_dir == 'U') ? 'L' : 'U';\n                if (!is_tabu(i, orig_rot, try_dir, orig_base, turn)) {\n                    placements[i].direction = try_dir;\n                    new_score = evaluate_placement();\n                    new_dir = try_dir;\n                }\n            } else if (!test_bases.empty()) {\n                int try_base = test_bases[uniform_int_distribution<>(0, (int)test_bases.size()-1)(rng)];\n                if (!is_tabu(i, orig_rot, orig_dir, try_base, turn)) {\n                    placements[i].base = try_base;\n                    new_score = evaluate_placement();\n                    new_base = try_base;\n                }\n            }\n            \n            if (new_score < LLONG_MAX) {\n                double delta = new_score - current_score;\n                \n                if (delta < 0 || (temperature > 1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(rng))) {\n                    if (delta < 0) {\n                        current_score = new_score;\n                        placements[i].rotation = new_rot;\n                        placements[i].direction = new_dir;\n                        placements[i].base = new_base;\n                    } else {\n                        placements[i].rotation = orig_rot;\n                        placements[i].direction = orig_dir;\n                        placements[i].base = orig_base;\n                    }\n                    add_tabu(i, orig_rot, orig_dir, orig_base, turn);\n                } else {\n                    placements[i].rotation = orig_rot;\n                    placements[i].direction = orig_dir;\n                    placements[i].base = orig_base;\n                }\n            } else {\n                placements[i].rotation = orig_rot;\n                placements[i].direction = orig_dir;\n                placements[i].base = orig_base;\n            }\n        }\n        \n        auto final_dims = simulate_fast();\n        long long estimated_score = (long long)final_dims.first + final_dims.second;\n        \n        cout << \"# Turn \" << turn << \" strat=\" << strategy << \" est=\" << estimated_score \n             << \" time=\" << get_elapsed() << \" pop=\" << population.size() << \"\\n\";\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n        }\n        cout.flush();\n        \n        int W_meas, H_meas;\n        cin >> W_meas >> H_meas;\n        long long measured_score = (long long)W_meas + H_meas;\n        \n        if (measured_score < best_solution.measured_score) {\n            best_solution.measured_score = measured_score;\n            best_solution.placements = placements;\n            best_solution.turn_found = turn;\n            best_solution.estimated_score = estimated_score;\n            last_improvement_turn = turn;\n            consecutive_no_improve = 0;\n            cout << \"# *** New best: \" << measured_score << \" turn \" << turn << \" ***\\n\";\n        } else {\n            consecutive_no_improve++;\n        }\n        \n        // Reset tabu if stagnating\n        if (consecutive_no_improve > 5 && turn < phase2_end) {\n            tabu_list.clear();\n            consecutive_no_improve = 0;\n            // Switch to different random seed\n            rng_index = (rng_index + 1) % 3;\n            cout << \"# Tabu reset, switching seed\\n\";\n        }\n        \n        // Add to population (top 5)\n        Solution sol;\n        sol.placements = placements;\n        sol.estimated_score = estimated_score;\n        sol.measured_score = measured_score;\n        sol.turn_found = turn;\n        \n        population.push_back(sol);\n        sort(population.begin(), population.end(), [](const Solution& a, const Solution& b) {\n            return a.estimated_score < b.estimated_score;\n        });\n        if (population.size() > 5) {\n            population.resize(5);\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\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\n    // Skip coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Start with all vertices as roots\n    vector<bool> is_root(N, true);\n    vector<int> dist(N, 0);\n    \n    // Fast BFS with early termination\n    auto compute_distances = [&]() -> bool {\n        fill(dist.begin(), dist.end(), -1);\n        queue<int> q;\n        \n        int root_count = 0;\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) {\n                dist[i] = 0;\n                q.push(i);\n                root_count++;\n            }\n        }\n        \n        if (root_count == 0) return false;\n        \n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            if (dist[u] > H) return false;\n            \n            for (int v : adj[u]) {\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            if (dist[i] == -1 || dist[i] > H) return false;\n        }\n        \n        return true;\n    };\n    \n    auto calc_score = [&]() -> long long {\n        long long score = 1;\n        for (int i = 0; i < N; ++i) {\n            score += (long long)(dist[i] + 1) * A[i];\n        }\n        return score;\n    };\n    \n    compute_distances();\n    long long current_score = calc_score();\n    long long best_score = current_score;\n    vector<bool> best_roots = is_root;\n    vector<int> best_dist = dist;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Phase 1: Simple greedy removal (fewer passes, more random)\n    for (int pass = 0; pass < 4; ++pass) {\n        bool changed = false;\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) roots.push_back(i);\n        }\n        \n        // Sort by beauty (prefer removing high beauty - they gain more from depth)\n        sort(roots.begin(), roots.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        \n        // Add randomness to ordering\n        for (size_t i = 0; i < roots.size(); ++i) {\n            size_t j = i + rng() % min((size_t)10, roots.size() - i);\n            swap(roots[i], roots[j]);\n        }\n        \n        for (int u : roots) {\n            if (roots.size() <= 1) break;\n            is_root[u] = false;\n            if (compute_distances()) {\n                long long new_score = calc_score();\n                if (new_score >= current_score) {\n                    current_score = new_score;\n                    changed = true;\n                } else {\n                    is_root[u] = true;\n                }\n            } else {\n                is_root[u] = true;\n            }\n        }\n        \n        if (!changed && pass > 1) break;\n    }\n    \n    if (current_score > best_score) {\n        best_score = current_score;\n        best_roots = is_root;\n        best_dist = dist;\n    }\n    \n    // Phase 2: Simulated Annealing (main optimization phase)\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.90; // Use most of the time for SA\n    \n    double T = 1000.0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        if (elapsed > time_limit) break;\n        \n        // Cooling schedule\n        double progress = elapsed / time_limit;\n        T = max(0.01, 1000.0 * pow(1.0 - progress, 2));\n        \n        int move_type = rng() % 4;\n        \n        if (move_type < 3) {\n            // Remove root (75%)\n            vector<int> roots;\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n            }\n            \n            if (roots.size() > 1) {\n                // Simple random selection with beauty bias\n                int idx;\n                if (rng() % 3 == 0) {\n                    // Prefer high beauty (33% of time)\n                    vector<pair<int, int>> scored;\n                    for (size_t i = 0; i < roots.size(); ++i) {\n                        scored.push_back({-A[roots[i]], (int)i});\n                    }\n                    sort(scored.begin(), scored.end());\n                    idx = scored[min((size_t)rng() % 5, scored.size())].second;\n                } else {\n                    // Random (67% of time)\n                    idx = rng() % roots.size();\n                }\n                \n                int u = roots[idx];\n                is_root[u] = false;\n                \n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                    }\n                } else {\n                    is_root[u] = true;\n                }\n            }\n        } else {\n            // Swap (25%)\n            vector<int> roots, non_roots;\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n                else non_roots.push_back(i);\n            }\n            \n            if (!roots.empty() && !non_roots.empty() && roots.size() > 1) {\n                int u = roots[rng() % roots.size()];\n                int w = non_roots[rng() % non_roots.size()];\n                \n                is_root[u] = false;\n                is_root[w] = true;\n                \n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                        is_root[w] = false;\n                    }\n                } else {\n                    is_root[u] = true;\n                    is_root[w] = false;\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Light refinement on best solution\n    is_root = best_roots;\n    dist = best_dist;\n    current_score = best_score;\n    \n    // Just 2 passes of simple greedy\n    for (int pass = 0; pass < 2; ++pass) {\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) roots.push_back(i);\n        }\n        \n        shuffle(roots.begin(), roots.end(), rng);\n        \n        for (int u : roots) {\n            if (roots.size() <= 1) break;\n            is_root[u] = false;\n            if (compute_distances()) {\n                long long new_score = calc_score();\n                if (new_score > current_score) {\n                    current_score = new_score;\n                    best_score = current_score;\n                    best_roots = is_root;\n                    best_dist = dist;\n                } else {\n                    is_root[u] = true;\n                }\n            } else {\n                is_root[u] = true;\n            }\n        }\n    }\n    \n    // Final validation\n    is_root = best_roots;\n    dist = best_dist;\n    \n    if (!compute_distances()) {\n        fill(is_root.begin(), is_root.end(), true);\n        compute_distances();\n    }\n    \n    bool valid = true;\n    for (int i = 0; i < N; ++i) {\n        if (dist[i] > H || dist[i] < 0) {\n            valid = false;\n            break;\n        }\n    }\n    \n    if (!valid) {\n        fill(is_root.begin(), is_root.end(), true);\n        compute_distances();\n    }\n    \n    // Reconstruct parent pointers\n    vector<int> P(N);\n    for (int v = 0; v < N; ++v) {\n        if (is_root[v]) {\n            P[v] = -1;\n        } else {\n            int d = dist[v];\n            int parent = -1;\n            for (int u : adj[v]) {\n                if (dist[u] == d - 1) {\n                    parent = u;\n                    break;\n                }\n            }\n            if (parent == -1) {\n                P[v] = -1;\n            } else {\n                P[v] = parent;\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nint N;\nvector<string> board;\n\nstruct Operation {\n    char dir;\n    int idx;\n    Operation(char d, int i) : dir(d), idx(i) {}\n};\n\nstruct OniInfo {\n    int r, c, dir, cost;\n    OniInfo(int r_, int c_, int d_, int cost_) : r(r_), c(c_), dir(d_), cost(cost_) {}\n};\n\nstruct BatchItem {\n    int r, c, cost;\n    BatchItem(int r_, int c_, int cost_) : r(r_), c(c_), cost(cost_) {}\n};\n\n// Check if direction is safe for removing piece at (r, c)\n// dir: 0=up, 1=down, 2=left, 3=right\nbool is_safe_direction(int r, int c, int dir, const vector<string>& bd) {\n    if (dir == 0) { // up\n        for (int i = 0; i < r; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 1) { // down\n        for (int i = r + 1; i < N; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 2) { // left\n        for (int j = 0; j < c; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    } else { // right\n        for (int j = c + 1; j < N; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    }\n}\n\n// Apply shift operation to board\nvoid apply_shift(vector<string>& bd, char dir, int idx) {\n    if (dir == 'U') {\n        for (int i = 0; i < N - 1; i++) {\n            bd[i][idx] = bd[i + 1][idx];\n        }\n        bd[N - 1][idx] = '.';\n    } else if (dir == 'D') {\n        for (int i = N - 1; i > 0; i--) {\n            bd[i][idx] = bd[i - 1][idx];\n        }\n        bd[0][idx] = '.';\n    } else if (dir == 'L') {\n        for (int j = 0; j < N - 1; j++) {\n            bd[idx][j] = bd[idx][j + 1];\n        }\n        bd[idx][N - 1] = '.';\n    } else if (dir == 'R') {\n        for (int j = N - 1; j > 0; j--) {\n            bd[idx][j] = bd[idx][j - 1];\n        }\n        bd[idx][0] = '.';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n    }\n    \n    vector<Operation> ops;\n    vector<string> current_board = board;\n    \n    // Count Fukunokami in each row and column\n    vector<int> fuku_in_row(N, 0), fuku_in_col(N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (current_board[i][j] == 'o') {\n                fuku_in_row[i]++;\n                fuku_in_col[j]++;\n            }\n        }\n    }\n    \n    while (true) {\n        // Find all remaining Oni\n        vector<OniInfo> oni_list;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (current_board[i][j] == 'x') {\n                    for (int dir = 0; dir < 4; dir++) {\n                        if (is_safe_direction(i, j, dir, current_board)) {\n                            int cost;\n                            if (dir == 0) cost = i + 1;\n                            else if (dir == 1) cost = N - i;\n                            else if (dir == 2) cost = j + 1;\n                            else cost = N - j;\n                            oni_list.emplace_back(i, j, dir, cost);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (oni_list.empty()) break;\n        \n        // Group by (idx, dir) for batch processing\n        // idx is row for left/right (dir 2,3), col for up/down (dir 0,1)\n        vector<vector<BatchItem>> batches(4 * N);\n        \n        for (const auto& oni : oni_list) {\n            int idx = (oni.dir < 2) ? oni.c : oni.r; // col for up/down, row for left/right\n            batches[oni.dir * N + idx].emplace_back(oni.r, oni.c, oni.cost);\n        }\n        \n        // Find best batch: maximize (oni_count / cost)\n        int best_batch = -1;\n        double best_score = -1;\n        int best_max_shift = 0;\n        \n        for (int b = 0; b < 4 * N; b++) {\n            if (batches[b].empty()) continue;\n            \n            int dir = b / N;\n            int idx = b % N;\n            \n            // Calculate cost for this batch\n            int max_shift = 0;\n            for (const auto& item : batches[b]) {\n                max_shift = max(max_shift, item.cost);\n            }\n            \n            // Check if we need to restore (if there are Fukunokami in this row/col)\n            int restore_cost = 0;\n            if (dir < 2) { // column operation\n                if (fuku_in_col[idx] > 0) restore_cost = max_shift;\n            } else { // row operation\n                if (fuku_in_row[idx] > 0) restore_cost = max_shift;\n            }\n            \n            int total_cost = max_shift + restore_cost;\n            int count = batches[b].size();\n            \n            double score = (double)count / total_cost;\n            if (score > best_score) {\n                best_score = score;\n                best_batch = b;\n                best_max_shift = max_shift;\n            }\n        }\n        \n        if (best_batch == -1) break;\n        \n        int dir = best_batch / N;\n        int idx = best_batch % N;\n        auto& batch = batches[best_batch];\n        \n        // Sort batch by cost (remove closest to edge first)\n        sort(batch.begin(), batch.end(), [](const BatchItem& a, const BatchItem& b) {\n            return a.cost < b.cost;\n        });\n        \n        // Determine shift direction character\n        char shift_dir, restore_dir;\n        if (dir == 0) { shift_dir = 'U'; restore_dir = 'D'; }\n        else if (dir == 1) { shift_dir = 'D'; restore_dir = 'U'; }\n        else if (dir == 2) { shift_dir = 'L'; restore_dir = 'R'; }\n        else { shift_dir = 'R'; restore_dir = 'L'; }\n        \n        // Apply shifts\n        for (int k = 0; k < best_max_shift; k++) {\n            ops.emplace_back(shift_dir, idx);\n            apply_shift(current_board, shift_dir, idx);\n        }\n        \n        // Update Fukunokami counts\n        if (dir < 2) {\n            // Column operation - Fukunokami in this column may have shifted or been removed\n            int new_count = 0;\n            for (int i = 0; i < N; i++) {\n                if (current_board[i][idx] == 'o') new_count++;\n            }\n            fuku_in_col[idx] = new_count;\n        } else {\n            // Row operation\n            int new_count = 0;\n            for (int j = 0; j < N; j++) {\n                if (current_board[idx][j] == 'o') new_count++;\n            }\n            fuku_in_row[idx] = new_count;\n        }\n        \n        // Restore if needed\n        if ((dir < 2 && fuku_in_col[idx] > 0) || (dir >= 2 && fuku_in_row[idx] > 0)) {\n            for (int k = 0; k < best_max_shift; k++) {\n                ops.emplace_back(restore_dir, idx);\n                apply_shift(current_board, restore_dir, idx);\n            }\n        }\n    }\n    \n    // Output operations\n    for (auto& op : ops) {\n        cout << op.dir << \" \" << op.idx << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    long long L;\n    cin >> N >> L;\n    \n    vector<long long> T(N);\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n    \n    // Use fixed seed for reproducibility, or time-based for variety\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Create weighted candidate distribution based on target frequencies\n    vector<int> weighted_candidates;\n    for (int i = 0; i < N; i++) {\n        // Higher target = more likely to be chosen as next cleaner\n        int weight = max(1, (int)(T[i] / 500 + 1));\n        for (int j = 0; j < weight; j++) {\n            weighted_candidates.push_back(i);\n        }\n    }\n    \n    // Initialize a and b arrays\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; i++) {\n        a[i] = weighted_candidates[rng() % weighted_candidates.size()];\n        b[i] = weighted_candidates[rng() % weighted_candidates.size()];\n    }\n    \n    // Simulation function\n    auto simulate = [&]() -> vector<long long> {\n        vector<long long> count(N, 0);\n        int current = 0;\n        \n        for (long long week = 0; week < L; week++) {\n            count[current]++;\n            // t = count[current] is the number of times current has cleaned\n            // If t is odd (1st, 3rd, 5th...), use a[current]\n            // If t is even (2nd, 4th, 6th...), use b[current]\n            if (count[current] % 2 == 1) {\n                current = a[current];\n            } else {\n                current = b[current];\n            }\n        }\n        \n        return count;\n    };\n    \n    // Error calculation\n    auto calcError = [&](const vector<long long>& actual) -> long long {\n        long long error = 0;\n        for (int i = 0; i < N; i++) {\n            error += abs(actual[i] - T[i]);\n        }\n        return error;\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_error = 1e18;\n    vector<int> best_a = a, best_b = b;\n    \n    // Main optimization loop\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Stop with buffer time for output\n        if (elapsed > 1950) break;\n        \n        // Evaluate current solution\n        vector<long long> actual = simulate();\n        long long error = calcError(actual);\n        \n        // Track best solution\n        if (error < best_error) {\n            best_error = error;\n            best_a = a;\n            best_b = b;\n        }\n        \n        // Local search: modify one parameter\n        int i = rng() % N;\n        int choice = rng() % 2;  // 0 = modify a[i], 1 = modify b[i]\n        int old_val = (choice == 0) ? a[i] : b[i];\n        \n        // Try new value from weighted candidates\n        int new_val = weighted_candidates[rng() % weighted_candidates.size()];\n        \n        if (choice == 0) {\n            a[i] = new_val;\n        } else {\n            b[i] = new_val;\n        }\n        \n        // Evaluate new solution\n        vector<long long> new_actual = simulate();\n        long long new_error = calcError(new_actual);\n        \n        // Simulated annealing acceptance criterion\n        if (new_error < error) {\n            // Always accept improvements\n        } else {\n            // Accept worse solutions with decreasing probability over time\n            double progress = (double)elapsed / 2000.0;\n            double temperature = 1000.0 * (1.0 - progress);\n            temperature = max(1.0, temperature);\n            \n            double acceptance_prob = exp(-(double)(new_error - error) / temperature);\n            \n            if ((double)rng() / rng.max() > acceptance_prob) {\n                // Revert change\n                if (choice == 0) {\n                    a[i] = old_val;\n                } else {\n                    b[i] = old_val;\n                }\n            }\n        }\n    }\n    \n    // Output best solution found\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 <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <chrono>\n#include <random>\n#include <iomanip>\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 weight;\n    double confidence; // 1.0 for query edges, <1.0 for estimated\n    bool fromQuery;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(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        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\n// Hilbert curve distance for better spatial locality\nint hilbertDist(int x, int y, int order = 14) {\n    int d = 0;\n    for (int s = 1 << (order - 1); s > 0; s >>= 1) {\n        int rx = (x & s) > 0;\n        int ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (rx == 0) {\n            if (ry == 1) {\n                x = (1 << order) - 1 - x;\n                y = (1 << order) - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// Minimum possible distance between two rectangles\nint minRectDist(const City& a, const City& b) {\n    int dx = 0, dy = 0;\n    if (a.rx < b.lx) dx = b.lx - a.rx;\n    else if (b.rx < a.lx) dx = a.lx - b.rx;\n    \n    if (a.ry < b.ly) dy = b.ly - a.ry;\n    else if (b.ry < a.ly) dy = a.ly - b.ry;\n    \n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Estimated distance using centers (more optimistic)\nint centerDist(const City& a, const City& b) {\n    double dx = a.cx - b.cx;\n    double dy = a.cy - b.cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\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, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    \n    vector<int> G(M);\n    for (int i = 0; i < M; i++) {\n        cin >> G[i];\n    }\n    \n    vector<City> cities(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 Hilbert curve distance for better spatial locality\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int ha = hilbertDist((int)cities[a].cx, (int)cities[a].cy);\n        int hb = hilbertDist((int)cities[b].cx, (int)cities[b].cy);\n        return ha < hb;\n    });\n    \n    // Assign cities to groups based on spatial ordering\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n    \n    // Track all known edges globally\n    map<pair<int,int>, Edge> knownEdges;\n    vector<vector<pair<int,int>>> groupEdges(M);\n    \n    int queriesUsed = 0;\n    \n    // Calculate query priority for each group\n    // Larger groups and groups with higher uncertainty get more queries\n    vector<pair<double, int>> groupPriority(M);\n    for (int i = 0; i < M; i++) {\n        int size = groups[i].size();\n        if (size < 2) {\n            groupPriority[i] = {0.0, i};\n            continue;\n        }\n        // Priority based on: number of edges needed * uncertainty\n        double uncertainty = 0;\n        for (int j = 0; j < size && j < 10; j++) {\n            for (int k = j + 1; k < size && k < 10; k++) {\n                int minD = minRectDist(cities[groups[i][j]], cities[groups[i][k]]);\n                int cenD = centerDist(cities[groups[i][j]], cities[groups[i][k]]);\n                uncertainty += (cenD - minD + 1);\n            }\n        }\n        // More edges needed = higher priority\n        groupPriority[i] = {(size - 1) * (1.0 + uncertainty / 100.0), i};\n    }\n    sort(groupPriority.begin(), groupPriority.end(), greater<pair<double,int>>());\n    \n    // Query each group strategically\n    for (auto& [priority, gi] : groupPriority) {\n        // Time check - leave margin for output\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        if (elapsed > 1850 || queriesUsed >= Q) break;\n        \n        int groupSize = groups[gi].size();\n        if (groupSize < 2) continue;\n        \n        // Calculate how many queries we can use for this group\n        int edgesNeeded = groupSize - 1;\n        int maxQueriesForGroup = min((Q - queriesUsed), (edgesNeeded + L - 2) / (L - 1));\n        \n        // Ensure we cover all cities in the group\n        vector<bool> covered(groupSize, false);\n        int queriesForThisGroup = 0;\n        \n        // First pass: ensure all cities are covered\n        for (int start = 0; start < groupSize && queriesForThisGroup < maxQueriesForGroup && queriesUsed < Q; ) {\n            int remaining = groupSize - start;\n            int chunkSize = min(L, remaining);\n            \n            if (chunkSize < 2) {\n                // Connect remaining city to previous\n                if (start > 0 && start < groupSize) {\n                    int u = groups[gi][start - 1];\n                    int v = groups[gi][start];\n                    if (u > v) swap(u, v);\n                    if (knownEdges.find({u, v}) == knownEdges.end()) {\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 0.5, false};\n                    }\n                }\n                break;\n            }\n            \n            // Make query\n            cout << \"?\" << \" \" << chunkSize;\n            for (int i = 0; i < chunkSize; i++) {\n                cout << \" \" << groups[gi][start + i];\n                covered[start + i] = true;\n            }\n            cout << endl;\n            cout.flush();\n            \n            queriesUsed++;\n            queriesForThisGroup++;\n            \n            // Read MST edges from response\n            for (int i = 0; i < chunkSize - 1; i++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                \n                // Mark as high confidence query edge\n                knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n            }\n            \n            // Move forward, overlap by 1 to ensure connectivity\n            start += chunkSize - 1;\n        }\n        \n        // Second pass: cover any missed cities with small queries\n        for (int i = 0; i < groupSize && queriesUsed < Q; i++) {\n            if (!covered[i]) {\n                // Find nearest covered city to query with\n                int bestJ = -1;\n                int bestDist = 1e9;\n                for (int j = 0; j < groupSize; j++) {\n                    if (covered[j] && j != i) {\n                        int d = centerDist(cities[groups[gi][i]], cities[groups[gi][j]]);\n                        if (d < bestDist) {\n                            bestDist = d;\n                            bestJ = j;\n                        }\n                    }\n                }\n                \n                if (bestJ >= 0) {\n                    int chunkSize = 2;\n                    if (queriesUsed < Q - 1) {\n                        // Try to add one more city if possible\n                        for (int k = 0; k < groupSize && chunkSize < L; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                chunkSize++;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    cout << \"?\" << \" \" << chunkSize << \" \" << groups[gi][i];\n                    int count = 1;\n                    if (count < chunkSize) {\n                        cout << \" \" << groups[gi][bestJ];\n                        count++;\n                        for (int k = 0; k < groupSize && count < chunkSize; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                cout << \" \" << groups[gi][k];\n                                count++;\n                            }\n                        }\n                    }\n                    cout << endl;\n                    cout.flush();\n                    \n                    queriesUsed++;\n                    \n                    for (int e = 0; e < chunkSize - 1; e++) {\n                        int u, v;\n                        cin >> u >> v;\n                        if (u > v) swap(u, v);\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n                    }\n                    covered[i] = true;\n                }\n            }\n        }\n    }\n    \n    // Build complete MST for each group using all available edges\n    for (int g = 0; g < M; g++) {\n        int groupSize = groups[g].size();\n        if (groupSize < 2) continue;\n        \n        vector<Edge> allEdges;\n        set<pair<int,int>> added;\n        \n        // Add all known edges for cities in this group\n        for (auto& [key, edge] : knownEdges) {\n            bool inGroup = false;\n            for (int city : groups[g]) {\n                if (city == edge.u || city == edge.v) {\n                    inGroup = true;\n                    break;\n                }\n            }\n            if (!inGroup) continue;\n            \n            // Check both endpoints are in this group\n            bool uIn = false, vIn = false;\n            for (int city : groups[g]) {\n                if (city == edge.u) uIn = true;\n                if (city == edge.v) vIn = true;\n            }\n            if (!uIn || !vIn) continue;\n            \n            if (added.find({edge.u, edge.v}) == added.end()) {\n                allEdges.push_back(edge);\n                added.insert({edge.u, edge.v});\n            }\n        }\n        \n        // Add estimated edges for missing connections\n        for (int i = 0; i < groupSize; i++) {\n            for (int j = i + 1; j < groupSize; j++) {\n                int u = groups[g][i];\n                int v = groups[g][j];\n                if (u > v) swap(u, v);\n                \n                if (added.find({u, v}) == added.end()) {\n                    int minD = minRectDist(cities[u], cities[v]);\n                    int cenD = centerDist(cities[u], cities[v]);\n                    // Use weighted average of min and center distance\n                    int estD = (minD + cenD) / 2;\n                    allEdges.push_back({u, v, estD, 0.3, false});\n                    added.insert({u, v});\n                }\n            }\n        }\n        \n        // Build MST - prefer query edges (high confidence), then by weight\n        sort(allEdges.begin(), allEdges.end(), [&](const Edge& a, const Edge& b) {\n            if (a.fromQuery != b.fromQuery) return a.fromQuery > b.fromQuery;\n            if (abs(a.confidence - b.confidence) > 0.1) return a.confidence > b.confidence;\n            return a.weight < b.weight;\n        });\n        \n        vector<pair<int,int>> mstEdges;\n        DSU dsu(N);\n        \n        for (auto& e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                mstEdges.push_back({e.u, e.v});\n                if ((int)mstEdges.size() == groupSize - 1) break;\n            }\n        }\n        \n        // Fallback: if MST is incomplete, add any remaining edges\n        if ((int)mstEdges.size() < groupSize - 1) {\n            DSU dsu2(N);\n            for (auto& e : mstEdges) {\n                dsu2.unite(e.first, e.second);\n            }\n            for (auto& e : allEdges) {\n                if (dsu2.unite(e.u, e.v)) {\n                    mstEdges.push_back({e.u, e.v});\n                    if ((int)mstEdges.size() == groupSize - 1) break;\n                }\n            }\n        }\n        \n        groupEdges[g] = mstEdges;\n    }\n    \n    // Output final answer\n    cout << \"!\" << endl;\n    cout.flush();\n    \n    for (int g = 0; g < M; g++) {\n        // Output cities in group\n        for (int i = 0; i < (int)groups[g].size(); i++) {\n            if (i > 0) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : groupEdges[g]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint cur_i, cur_j;\nvector<pair<int, int>> targets;\nset<pair<int, int>> blocks;\n\n// Direction arrays at global scope\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && blocks.find({i, j}) == blocks.end();\n}\n\npair<int, int> getSlideEnd(int i, int j, int di, int dj) {\n    while (true) {\n        int ni = i + di, nj = j + dj;\n        if (!isValid(ni, nj)) break;\n        i = ni;\n        j = nj;\n    }\n    return {i, j};\n}\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nvoid solve() {\n    cin >> N >> M;\n    cin >> cur_i >> cur_j;\n    for (int k = 0; k < M; k++) {\n        int i, j;\n        cin >> i >> j;\n        targets.push_back({i, j});\n    }\n    \n    vector<pair<char, char>> allActions;\n    \n    for (int t = 0; t < M; t++) {\n        int ti = targets[t].first;\n        int tj = targets[t].second;\n        vector<pair<char, char>> targetActions;\n        \n        // Simple BFS to find path to target\n        queue<tuple<int, int, vector<pair<char, char>>>> q;\n        vector<pair<char, char>> emptyPath;\n        q.push({cur_i, cur_j, emptyPath});\n        \n        set<pair<int, int>> visited;\n        visited.insert({cur_i, cur_j});\n        bool found = false;\n        \n        int maxDepth = 200;\n        \n        while (!q.empty() && !found) {\n            auto [pi, pj, path] = q.front();\n            q.pop();\n            \n            if ((int)path.size() > maxDepth) continue;\n            \n            if (pi == ti && pj == tj) {\n                targetActions = path;\n                found = true;\n                break;\n            }\n            \n            // Try moves\n            for (int d = 0; d < 4; d++) {\n                int ni = pi + DI[d], nj = pj + DJ[d];\n                \n                if (isValid(ni, nj) && !visited.count({ni, nj})) {\n                    visited.insert({ni, nj});\n                    auto newPath = path;\n                    newPath.emplace_back('M', DIR_CHAR[d]);\n                    q.push({ni, nj, newPath});\n                }\n                \n                // Try slides\n                auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                if ((si != pi || sj != pj) && !visited.count({si, sj})) {\n                    visited.insert({si, sj});\n                    auto newPath = path;\n                    newPath.emplace_back('S', DIR_CHAR[d]);\n                    q.push({si, sj, newPath});\n                }\n            }\n        }\n        \n        // Fallback: greedy approach if BFS fails\n        if (!found) {\n            int pi = cur_i, pj = cur_j;\n            \n            while (pi != ti || pj != tj) {\n                bool moved = false;\n                \n                // Try slides first\n                for (int d = 0; d < 4; d++) {\n                    auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                    \n                    if (si == ti && sj == tj) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                    \n                    int oldDist = manhattan(pi, pj, ti, tj);\n                    int newDist = manhattan(si, sj, ti, tj);\n                    \n                    if (newDist < oldDist && (si != pi || sj != pj)) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                }\n                \n                if (!moved) {\n                    // Use move\n                    if (pi < ti) {\n                        targetActions.emplace_back('M', 'D');\n                        pi++;\n                    } else if (pi > ti) {\n                        targetActions.emplace_back('M', 'U');\n                        pi--;\n                    } else if (pj < tj) {\n                        targetActions.emplace_back('M', 'R');\n                        pj++;\n                    } else if (pj > tj) {\n                        targetActions.emplace_back('M', 'L');\n                        pj--;\n                    }\n                }\n                \n                if ((int)targetActions.size() > maxDepth) break;\n            }\n        }\n        \n        // Execute actions and update blocks\n        for (auto& action : targetActions) {\n            char act = action.first;\n            char dir = action.second;\n            \n            if (act == 'M') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        cur_i += DI[d];\n                        cur_j += DJ[d];\n                        break;\n                    }\n                }\n            } else if (act == 'S') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        tie(cur_i, cur_j) = getSlideEnd(cur_i, cur_j, DI[d], DJ[d]);\n                        break;\n                    }\n                }\n            } else if (act == 'A') {\n                int bi = cur_i, bj = cur_j;\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        bi += DI[d];\n                        bj += DJ[d];\n                        break;\n                    }\n                }\n                if (blocks.count({bi, bj})) blocks.erase({bi, bj});\n                else blocks.insert({bi, bj});\n            }\n            allActions.emplace_back(act, dir);\n        }\n    }\n    \n    for (auto& action : allActions) {\n        cout << action.first << \" \" << action.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\ndouble calc_satisfaction(int r, int s, bool contains) {\n    if (!contains || r == 0 || s == 0) return 0.0;\n    double ratio = min(r, s) / (double)max(r, s);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\ndouble rect_satisfaction(const Rect& r, const Company& c) {\n    return calc_satisfaction(c.r, r.area(), r.contains(c.x, c.y));\n}\n\ndouble total_satisfaction(const vector<Rect>& rects, const vector<Company>& companies) {\n    double total = 0.0;\n    for (size_t i = 0; i < companies.size(); i++) {\n        total += rect_satisfaction(rects[i], companies[i]);\n    }\n    return total;\n}\n\ninline bool rectangles_overlap(const Rect& a, const Rect& b) {\n    return max(0, min(a.x2, b.x2) - max(a.x1, b.x1)) > 0 &&\n           max(0, min(a.y2, b.y2) - max(a.y1, b.y1)) > 0;\n}\n\nbool validate_layout(const vector<Rect>& rects) {\n    size_t n = rects.size();\n    for (size_t i = 0; i < n; i++) {\n        if (rects[i].x1 >= rects[i].x2 || rects[i].y1 >= rects[i].y2) return false;\n        if (rects[i].x1 < 0 || rects[i].y1 < 0) return false;\n        if (rects[i].x2 > 10000 || rects[i].y2 > 10000) return false;\n        for (size_t j = i + 1; j < n; j++) {\n            if (rectangles_overlap(rects[i], rects[j])) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\nlong long morton_index(int x, int y) {\n    long long result = 0;\n    for (int i = 0; i < 14; i++) {\n        result |= ((long long)(x & (1 << i)) << i) | ((long long)(y & (1 << i)) << (i + 1));\n    }\n    return result;\n}\n\nlong long hilbert_index(int x, int y) {\n    int n = 14;\n    long long rx, ry, s, d = 0;\n    for (s = n - 1; s >= 0; s--) {\n        rx = (x >> s) & 1;\n        ry = (y >> s) & 1;\n        d += (1LL << (2 * s)) * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << (s + 1)) - 1) - x;\n                y = ((1 << (s + 1)) - 1) - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\nvoid partition(vector<int>& indices, const vector<Company>& companies, \n               Rect region, vector<Rect>& result) {\n    if (indices.empty()) return;\n    \n    if (indices.size() == 1) {\n        result[companies[indices[0]].id] = region;\n        return;\n    }\n    \n    long long total_area = 0;\n    int min_x = 10001, max_x = -1, min_y = 10001, max_y = -1;\n    for (int idx : indices) {\n        total_area += companies[idx].r;\n        min_x = min(min_x, companies[idx].x);\n        max_x = max(max_x, companies[idx].x);\n        min_y = min(min_y, companies[idx].y);\n        max_y = max(max_y, companies[idx].y);\n    }\n    \n    int region_w = region.x2 - region.x1;\n    int region_h = region.y2 - region.y1;\n    bool split_vertical = region_w >= region_h;\n    \n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        if (split_vertical) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        } else {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        }\n    });\n    \n    long long left_area = 0;\n    int split_idx = 1;\n    long long best_diff = LLONG_MAX;\n    \n    for (size_t i = 0; i < indices.size() - 1; i++) {\n        left_area += companies[indices[i]].r;\n        long long diff = abs(2 * left_area - total_area);\n        if (diff < best_diff) {\n            best_diff = diff;\n            split_idx = i + 1;\n        }\n    }\n    \n    long long left_sum = 0;\n    for (int i = 0; i < split_idx; i++) {\n        left_sum += companies[indices[i]].r;\n    }\n    \n    vector<int> left_indices(indices.begin(), indices.begin() + split_idx);\n    vector<int> right_indices(indices.begin() + split_idx, indices.end());\n    \n    Rect left_region = region, right_region = region;\n    \n    if (split_vertical) {\n        int left_max_x = -1, right_min_x = 10001;\n        for (int idx : left_indices) left_max_x = max(left_max_x, companies[idx].x);\n        for (int idx : right_indices) right_min_x = min(right_min_x, companies[idx].x);\n        \n        int split_x = region.x1 + (int)((left_sum * region_w + total_area/2) / total_area);\n        if (left_max_x < right_min_x) {\n            split_x = max(region.x1 + 1, min(region.x2 - 1, (left_max_x + 1 + right_min_x) / 2));\n        } else {\n            split_x = max(region.x1 + 1, min(region.x2 - 1, split_x));\n        }\n        \n        left_region.x2 = split_x;\n        right_region.x1 = split_x;\n    } else {\n        int left_max_y = -1, right_min_y = 10001;\n        for (int idx : left_indices) left_max_y = max(left_max_y, companies[idx].y);\n        for (int idx : right_indices) right_min_y = min(right_min_y, companies[idx].y);\n        \n        int split_y = region.y1 + (int)((left_sum * region_h + total_area/2) / total_area);\n        if (left_max_y < right_min_y) {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, (left_max_y + 1 + right_min_y) / 2));\n        } else {\n            split_y = max(region.y1 + 1, min(region.y2 - 1, split_y));\n        }\n        \n        left_region.y2 = split_y;\n        right_region.y1 = split_y;\n    }\n    \n    if (left_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x1 + 1;\n            right_region.x1 = region.x1 + 1;\n        } else {\n            left_region.y2 = region.y1 + 1;\n            right_region.y1 = region.y1 + 1;\n        }\n    }\n    if (right_region.area() <= 0) {\n        if (split_vertical) {\n            left_region.x2 = region.x2 - 1;\n            right_region.x1 = region.x2 - 1;\n        } else {\n            left_region.y2 = region.y2 - 1;\n            right_region.y1 = region.y2 - 1;\n        }\n    }\n    \n    partition(left_indices, companies, left_region, result);\n    partition(right_indices, companies, right_region, result);\n}\n\ninline bool are_adjacent(const Rect& a, const Rect& b) {\n    if (a.x2 == b.x1 || b.x2 == a.x1) {\n        return max(a.y1, b.y1) < min(a.y2, b.y2);\n    }\n    if (a.y2 == b.y1 || b.y2 == a.y1) {\n        return max(a.x1, b.x1) < min(a.x2, b.x2);\n    }\n    return false;\n}\n\n// Fast overlap check with early bounding box rejection\ninline bool check_no_overlap(const Rect& r, const vector<Rect>& rects, int skip1, int skip2) {\n    for (size_t k = 0; k < rects.size(); k++) {\n        if ((int)k == skip1 || (int)k == skip2) continue;\n        // Quick bounding box rejection\n        if (r.x2 <= rects[k].x1 || r.x1 >= rects[k].x2 || \n            r.y2 <= rects[k].y1 || r.y1 >= rects[k].y2) continue;\n        if (rectangles_overlap(r, rects[k])) return false;\n    }\n    return true;\n}\n\nbool safe_optimize_pair(vector<Rect>& rects, const vector<Company>& companies, \n                       int i, int j, int delta_range) {\n    Rect& ri = rects[i];\n    Rect& rj = rects[j];\n    \n    if (!are_adjacent(ri, rj)) return false;\n    \n    double current_score = rect_satisfaction(ri, companies[i]) + rect_satisfaction(rj, companies[j]);\n    \n    double best_score = current_score;\n    Rect best_ri = ri, best_rj = rj;\n    bool found_improvement = false;\n    \n    // Try deltas in order: small adjustments first (more likely to help)\n    for (int d = 1; d <= delta_range; d++) {\n        for (int sign : {-1, 1}) {\n            int delta = sign * d;\n            Rect test_ri = ri, test_rj = rj;\n            bool valid_bounds = false;\n            \n            if (ri.x2 == rj.x1) {\n                test_ri.x2 += delta;\n                test_rj.x1 += delta;\n                if (test_ri.x1 < test_ri.x2 && test_rj.x1 < test_rj.x2 &&\n                    test_ri.x1 >= 0 && test_ri.x2 <= 10000 &&\n                    test_rj.x1 >= 0 && test_rj.x2 <= 10000) {\n                    valid_bounds = true;\n                }\n            } else if (rj.x2 == ri.x1) {\n                test_rj.x2 += delta;\n                test_ri.x1 += delta;\n                if (test_ri.x1 < test_ri.x2 && test_rj.x1 < test_rj.x2 &&\n                    test_ri.x1 >= 0 && test_ri.x2 <= 10000 &&\n                    test_rj.x1 >= 0 && test_rj.x2 <= 10000) {\n                    valid_bounds = true;\n                }\n            } else if (ri.y2 == rj.y1) {\n                test_ri.y2 += delta;\n                test_rj.y1 += delta;\n                if (test_ri.y1 < test_ri.y2 && test_rj.y1 < test_rj.y2 &&\n                    test_ri.y1 >= 0 && test_ri.y2 <= 10000 &&\n                    test_rj.y1 >= 0 && test_rj.y2 <= 10000) {\n                    valid_bounds = true;\n                }\n            } else if (rj.y2 == ri.y1) {\n                test_rj.y2 += delta;\n                test_ri.y1 += delta;\n                if (test_ri.y1 < test_ri.y2 && test_rj.y1 < test_rj.y2 &&\n                    test_ri.y1 >= 0 && test_ri.y2 <= 10000 &&\n                    test_rj.y1 >= 0 && test_rj.y2 <= 10000) {\n                    valid_bounds = true;\n                }\n            }\n            \n            if (!valid_bounds) continue;\n            if (rectangles_overlap(test_ri, test_rj)) continue;\n            \n            // Fast overlap check\n            if (!check_no_overlap(test_ri, rects, i, j)) continue;\n            if (!check_no_overlap(test_rj, rects, i, j)) continue;\n            \n            double new_score = rect_satisfaction(test_ri, companies[i]) + rect_satisfaction(test_rj, companies[j]);\n            \n            if (new_score > best_score) {\n                best_score = new_score;\n                best_ri = test_ri;\n                best_rj = test_rj;\n                found_improvement = true;\n            }\n        }\n    }\n    \n    if (found_improvement) {\n        ri = best_ri;\n        rj = best_rj;\n        return true;\n    }\n    return false;\n}\n\nvoid optimize_with_validation(vector<Rect>& rects, const vector<Company>& companies, \n                             int max_passes, int delta_range) {\n    size_t n = companies.size();\n    int no_improve_count = 0;\n    \n    // Pre-allocate adjacency list\n    vector<pair<int, int>> adjacent_pairs;\n    adjacent_pairs.reserve(n * 4);\n    \n    for (int pass = 0; pass < max_passes && no_improve_count < 2; pass++) {\n        bool any_improved = false;\n        adjacent_pairs.clear();\n        \n        for (size_t i = 0; i < n; i++) {\n            for (size_t j = i + 1; j < n; j++) {\n                if (are_adjacent(rects[i], rects[j])) {\n                    adjacent_pairs.emplace_back(i, j);\n                }\n            }\n        }\n        \n        sort(adjacent_pairs.begin(), adjacent_pairs.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n            double score_a = rect_satisfaction(rects[a.first], companies[a.first]) + \n                           rect_satisfaction(rects[a.second], companies[a.second]);\n            double score_b = rect_satisfaction(rects[b.first], companies[b.first]) + \n                           rect_satisfaction(rects[b.second], companies[b.second]);\n            return score_a < score_b;\n        });\n        \n        for (auto& p : adjacent_pairs) {\n            if (safe_optimize_pair(rects, companies, p.first, p.second, delta_range)) {\n                any_improved = true;\n            }\n        }\n        \n        if (!validate_layout(rects)) break;\n        \n        no_improve_count = any_improved ? 0 : no_improve_count + 1;\n    }\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    const double TIME_LIMIT = 4.9;\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    long long total_r = 0;\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        total_r += companies[i].r;\n    }\n    \n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n    \n    vector<vector<int>> orderings;\n    orderings.reserve(120);\n    \n    // Deterministic orderings (5)\n    {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return morton_index(companies[i].x, companies[i].y) < \n                   morton_index(companies[j].x, companies[j].y);\n        });\n        orderings.push_back(move(order));\n    }\n    {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return hilbert_index(companies[i].x, companies[i].y) < \n                   hilbert_index(companies[j].x, companies[j].y);\n        });\n        orderings.push_back(move(order));\n    }\n    {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            return companies[i].x + companies[i].y < companies[j].x + companies[j].y;\n        });\n        orderings.push_back(move(order));\n    }\n    {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (companies[i].x != companies[j].x)\n                return companies[i].x < companies[j].x;\n            return companies[i].y < companies[j].y;\n        });\n        orderings.push_back(move(order));\n    }\n    {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (companies[i].y != companies[j].y)\n                return companies[i].y < companies[j].y;\n            return companies[i].x < companies[j].x;\n        });\n        orderings.push_back(move(order));\n    }\n    \n    // Random orderings (115 more for total of 120)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int seed = 0; seed < 115; seed++) {\n        vector<int> order(n);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        orderings.push_back(move(order));\n    }\n    \n    // Phase 1: Quick evaluation of all orderings\n    vector<pair<double, int>> ordering_scores;\n    ordering_scores.reserve(orderings.size());\n    \n    for (size_t idx = 0; idx < orderings.size(); idx++) {\n        vector<Rect> rects(n);\n        Rect full_region = {0, 0, 10000, 10000};\n        partition(orderings[idx], companies, full_region, rects);\n        double score = total_satisfaction(rects, companies);\n        ordering_scores.emplace_back(score, idx);\n        \n        if (idx % 30 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT * 0.4) break;\n        }\n    }\n    \n    sort(ordering_scores.begin(), ordering_scores.end(), greater<pair<double, int>>());\n    \n    // Phase 2: Three-tier optimization\n    size_t top_tier = min(size_t(20), ordering_scores.size());\n    size_t mid_tier = min(size_t(60), ordering_scores.size());\n    \n    // Top 20: Most aggressive (8 passes, delta \u00b110)\n    for (size_t rank = 0; rank < top_tier; rank++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        int idx = ordering_scores[rank].second;\n        vector<Rect> rects(n);\n        Rect full_region = {0, 0, 10000, 10000};\n        partition(orderings[idx], companies, full_region, rects);\n        \n        optimize_with_validation(rects, companies, 8, 10);\n        \n        double score = total_satisfaction(rects, companies);\n        if (score > best_score && validate_layout(rects)) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n    \n    // Next 40: Moderate (5 passes, delta \u00b17)\n    for (size_t rank = top_tier; rank < mid_tier; rank++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        int idx = ordering_scores[rank].second;\n        vector<Rect> rects(n);\n        Rect full_region = {0, 0, 10000, 10000};\n        partition(orderings[idx], companies, full_region, rects);\n        \n        optimize_with_validation(rects, companies, 5, 7);\n        \n        double score = total_satisfaction(rects, companies);\n        if (score > best_score && validate_layout(rects)) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n    \n    // Fallback if nothing worked\n    if (best_score < 0 || !validate_layout(best_rects)) {\n        vector<Rect> fallback_rects(n);\n        Rect full_region = {0, 0, 10000, 10000};\n        partition(orderings[0], companies, full_region, fallback_rects);\n        for (int i = 0; i < n; i++) {\n            cout << fallback_rects[i].x1 << \" \" << fallback_rects[i].y1 << \" \" \n                 << fallback_rects[i].x2 << \" \" << fallback_rects[i].y2 << \"\\n\";\n        }\n    } else {\n        for (int i = 0; i < n; i++) {\n            cout << best_rects[i].x1 << \" \" << best_rects[i].y1 << \" \" \n                 << best_rects[i].x2 << \" \" << best_rects[i].y2 << \"\\n\";\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\nusing namespace std;\n\nconst int H = 50;\nconst int W = 50;\nvector<vector<int>> tile_id;\nvector<vector<int>> score_val;\nint max_tile = 0;\n\nvector<char> visited_tiles;\nmt19937 rng;\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\n\n// Evaluation with 2-step lookahead (proven effective)\ninline int evaluate_cell(int r, int c) {\n    int tid = tile_id[r][c];\n    if (visited_tiles[tid]) return -1000000;\n    \n    int base_score = score_val[r][c];\n    int future_score = 0;\n    int available_exits = 0;\n    \n    for (int i = 0; i < 4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n            int ntid = tile_id[nr][nc];\n            if (!visited_tiles[ntid]) {\n                available_exits++;\n                future_score += score_val[nr][nc];\n                \n                // Second level lookahead\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j];\n                    int nnc = nc + dc[j];\n                    if (nnr >= 0 && nnr < H && nnc >= 0 && nnc < W) {\n                        int nntid = tile_id[nnr][nnc];\n                        if (!visited_tiles[nntid]) {\n                            future_score += score_val[nnr][nnc] / 4;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (available_exits == 0) return -500000;\n    \n    return base_score * 10 + future_score / 2 + available_exits * 500;\n}\n\n// Path extension with weighted selection (proven effective)\ninline void extend_path(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    while (true) {\n        struct Cand {\n            int r, c, eval;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    cands[count++] = {nr, nc, evaluate_cell(nr, nc)};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort by evaluation (descending)\n        for (int i = 0; i < count - 1; ++i) {\n            for (int j = i + 1; j < count; ++j) {\n                if (cands[j].eval > cands[i].eval) {\n                    swap(cands[i], cands[j]);\n                }\n            }\n        }\n        \n        // Weighted selection from top candidates\n        int top_k = (count < 3) ? count : 3;\n        double weights[3];\n        double total_weight = 0;\n        for (int i = 0; i < top_k; ++i) {\n            weights[i] = pow(0.6, (double)i);\n            total_weight += weights[i];\n        }\n        \n        uniform_real_distribution<double> dist(0.0, total_weight);\n        double roll = dist(rng);\n        double cum = 0;\n        int idx = 0;\n        for (int i = 0; i < top_k; ++i) {\n            cum += weights[i];\n            if (roll <= cum) {\n                idx = i;\n                break;\n            }\n        }\n        \n        int nr = cands[idx].r;\n        int nc = cands[idx].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\n// Greedy extension (always pick best) - for final optimization\ninline void greedy_extend(vector<pair<int, int>>& path, long long& current_score) {\n    int r = path.back().first;\n    int c = path.back().second;\n    \n    while (true) {\n        struct Cand {\n            int r, c, eval;\n        };\n        Cand cands[4];\n        int count = 0;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                int tid = tile_id[nr][nc];\n                if (!visited_tiles[tid]) {\n                    cands[count++] = {nr, nc, evaluate_cell(nr, nc)};\n                }\n            }\n        }\n        \n        if (count == 0) break;\n        \n        // Sort and pick best\n        for (int i = 0; i < count - 1; ++i) {\n            for (int j = i + 1; j < count; ++j) {\n                if (cands[j].eval > cands[i].eval) {\n                    swap(cands[i], cands[j]);\n                }\n            }\n        }\n        \n        int nr = cands[0].r;\n        int nc = cands[0].c;\n        int tid = tile_id[nr][nc];\n        \n        visited_tiles[tid] = 1;\n        path.emplace_back(nr, nc);\n        current_score += score_val[nr][nc];\n        r = nr;\n        c = nc;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    tile_id.assign(H, vector<int>(W));\n    max_tile = 0;\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> tile_id[i][j];\n            if (tile_id[i][j] > max_tile) max_tile = tile_id[i][j];\n        }\n    }\n    \n    score_val.assign(H, vector<int>(W));\n    for(int i=0; i<H; ++i) {\n        for(int j=0; j<W; ++j) {\n            cin >> score_val[i][j];\n        }\n    }\n    \n    visited_tiles.assign(max_tile + 1, 0);\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time\n        ).count();\n    };\n    \n    // Single initial solution (maximize optimization time)\n    vector<pair<int, int>> current_path;\n    current_path.reserve(2500);\n    current_path.push_back({si, sj});\n    visited_tiles[tile_id[si][sj]] = 1;\n    long long current_score = score_val[si][sj];\n    \n    extend_path(current_path, current_score);\n    \n    vector<pair<int, int>> best_path = current_path;\n    long long best_score = current_score;\n    \n    // Main SA loop - simple and fast (proven parameters)\n    double temperature = 500.0;\n    int no_improve = 0;\n    int iteration = 0;\n    \n    while (get_elapsed_ms() < 1950) {\n        iteration++;\n        \n        // Simple exponential cooling (proven effective)\n        temperature *= 0.9995;\n        if (temperature < 1.0) temperature = 1.0;\n        \n        // Backup state\n        vector<pair<int, int>> path_backup = current_path;\n        long long score_backup = current_score;\n        vector<char> visited_backup = visited_tiles;\n        \n        // Simple cut point selection\n        int cut_idx = (int)(rng() % current_path.size());\n        \n        // Rollback visited tiles after cut point\n        int path_len = (int)current_path.size();\n        for (int i = path_len - 1; i > cut_idx; --i) {\n            int r = current_path[i].first;\n            int c = current_path[i].second;\n            visited_tiles[tile_id[r][c]] = 0;\n        }\n        current_path.resize(cut_idx + 1);\n        \n        // Recalculate prefix score\n        long long temp_score = 0;\n        for (const auto& p : current_path) {\n            temp_score += score_val[p.first][p.second];\n        }\n        \n        // Extend path from cut point\n        extend_path(current_path, temp_score);\n        \n        // SA acceptance criterion\n        bool accept = false;\n        if (temp_score >= current_score) {\n            accept = true;\n        } else {\n            double diff = (double)(temp_score - current_score);\n            double prob = exp(diff / temperature);\n            uniform_real_distribution<double> dist(0.0, 1.0);\n            if (dist(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = temp_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n                no_improve = 0;\n            }\n        } else {\n            // Revert to backup state\n            for (int i = (int)current_path.size() - 1; i > cut_idx; --i) {\n                int r = current_path[i].first;\n                int c = current_path[i].second;\n                visited_tiles[tile_id[r][c]] = 0;\n            }\n            current_path = path_backup;\n            current_score = score_backup;\n            visited_tiles = visited_backup;\n            no_improve++;\n        }\n        \n        // Restart if stuck\n        if (no_improve > 300 && get_elapsed_ms() < 1600) {\n            fill(visited_tiles.begin(), visited_tiles.end(), 0);\n            current_path.clear();\n            current_path.push_back({si, sj});\n            visited_tiles[tile_id[si][sj]] = 1;\n            current_score = score_val[si][sj];\n            extend_path(current_path, current_score);\n            no_improve = 0;\n            temperature = 500.0;\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path = current_path;\n            }\n        }\n    }\n    \n    // Final greedy optimization: try extending from various cut points\n    if (get_elapsed_ms() < 1980) {\n        // Try greedy extension from different cut points of best_path\n        for (int attempt = 0; attempt < 3 && get_elapsed_ms() < 1980; ++attempt) {\n            int cut_point;\n            if (attempt == 0) {\n                cut_point = (int)best_path.size() - 1;  // From end\n            } else if (attempt == 1) {\n                cut_point = (int)(best_path.size() * 0.7);  // From 70%\n            } else {\n                cut_point = (int)(best_path.size() * 0.5);  // From 50%\n            }\n            cut_point = max(0, min(cut_point, (int)best_path.size() - 1));\n            \n            // Setup visited tiles for prefix\n            fill(visited_tiles.begin(), visited_tiles.end(), 0);\n            vector<pair<int, int>> test_path;\n            test_path.reserve(best_path.size());\n            long long test_score = 0;\n            \n            for (int i = 0; i <= cut_point; ++i) {\n                test_path.push_back(best_path[i]);\n                visited_tiles[tile_id[best_path[i].first][best_path[i].second]] = 1;\n                test_score += score_val[best_path[i].first][best_path[i].second];\n            }\n            \n            // Greedy extend from cut point\n            greedy_extend(test_path, test_score);\n            \n            if (test_score > best_score) {\n                best_score = test_score;\n                best_path = test_path;\n            }\n        }\n    }\n    \n    // Construct output string\n    string res;\n    if (best_path.size() > 1) {\n        res.reserve(best_path.size() - 1);\n        for (size_t i = 1; i < best_path.size(); ++i) {\n            int dr_val = best_path[i].first - best_path[i-1].first;\n            int dc_val = best_path[i].second - best_path[i-1].second;\n            if (dr_val == -1) res += 'U';\n            else if (dr_val == 1) res += 'D';\n            else if (dc_val == -1) res += 'L';\n            else if (dc_val == 1) res += 'R';\n        }\n    }\n    cout << res << endl;\n    \n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Solver {\n    double h[N][N-1];  // horizontal edges: h[i][j] = edge from (i,j) to (i,j+1)\n    double v[N-1][N];  // vertical edges: v[i][j] = edge from (i,j) to (i+1,j)\n    int h_cnt[N][N-1];\n    int v_cnt[N-1][N];\n    \n    Solver() {\n        for(int i = 0; i < N; i++) {\n            for(int j = 0; j < N-1; j++) {\n                h[i][j] = 5000.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for(int i = 0; i < N-1; i++) {\n            for(int j = 0; j < N; j++) {\n                v[i][j] = 5000.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n    \n    // Get edge weight with bounds checking\n    double get_weight(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v[i-1][j] : 1e9;\n        if(dir == 'D') return (i < N-1) ? v[i][j] : 1e9;\n        if(dir == 'L') return (j > 0) ? h[i][j-1] : 1e9;\n        if(dir == 'R') return (j < N-1) ? h[i][j] : 1e9;\n        return 1e9;\n    }\n    \n    // Get visit count for an edge\n    int get_count(int i, int j, char dir) const {\n        if(dir == 'U') return (i > 0) ? v_cnt[i-1][j] : 0;\n        if(dir == 'D') return (i < N-1) ? v_cnt[i][j] : 0;\n        if(dir == 'L') return (j > 0) ? h_cnt[i][j-1] : 0;\n        if(dir == 'R') return (j < N-1) ? h_cnt[i][j] : 0;\n        return 0;\n    }\n    \n    pair<string, double> dijkstra(int si, int sj, int ti, int tj, double temp) {\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        vector<vector<double>> dist(N, vector<double>(N, 1e18));\n        vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<char>> move(N, vector<char>(N, 0));\n        \n        dist[si][sj] = 0;\n        pq.push({0.0, si, sj});\n        \n        const char dirs[] = {'U', 'D', 'L', 'R'};\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while(!pq.empty()) {\n            auto [d, i, j] = pq.top();\n            pq.pop();\n            \n            if(d > dist[i][j] + 1e-9) continue;\n            if(i == ti && j == tj) break;\n            \n            for(int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                \n                if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double w = get_weight(i, j, dirs[dir]);\n                if(w >= 1e9) continue;\n                \n                // Exploration bonus: prefer less-visited edges\n                int cnt = get_count(i, j, dirs[dir]);\n                double bonus = temp / (cnt + 1);\n                double new_dist = d + w + bonus;\n                \n                if(new_dist < dist[ni][nj]) {\n                    dist[ni][nj] = new_dist;\n                    prev[ni][nj] = {i, j};\n                    move[ni][nj] = dirs[dir];\n                    pq.push({new_dist, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path;\n        int ci = ti, cj = tj;\n        while(ci != si || cj != sj) {\n            path += move[ci][cj];\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        \n        return {path, dist[ti][tj]};\n    }\n    \n    void update(const string& path, int si, int sj, int observed, int query_num) {\n        if(path.empty()) return;\n        \n        // Calculate estimated cost and track vertices\n        double estimated = 0;\n        int ci = si, cj = sj;\n        vector<tuple<int, int, char>> edges;\n        \n        for(char c : path) {\n            double w = get_weight(ci, cj, c);\n            estimated += w;\n            edges.push_back({ci, cj, c});\n            \n            if(c == 'U') ci--;\n            else if(c == 'D') ci++;\n            else if(c == 'L') cj--;\n            else if(c == 'R') cj++;\n        }\n        \n        if(estimated < 1) estimated = 1;\n        double ratio = (double)observed / estimated;\n        \n        // Learning rate decreases over time\n        double lr = 0.30 * pow(0.992, query_num);\n        lr = max(lr, 0.01);\n        \n        // Update edges on path\n        for(auto& [i, j, c] : edges) {\n            if(c == 'U') {\n                v[i-1][j] = (1-lr) * v[i-1][j] + lr * v[i-1][j] * ratio;\n                v_cnt[i-1][j]++;\n            } else if(c == 'D') {\n                v[i][j] = (1-lr) * v[i][j] + lr * v[i][j] * ratio;\n                v_cnt[i][j]++;\n            } else if(c == 'L') {\n                h[i][j-1] = (1-lr) * h[i][j-1] + lr * h[i][j-1] * ratio;\n                h_cnt[i][j-1]++;\n            } else if(c == 'R') {\n                h[i][j] = (1-lr) * h[i][j] + lr * h[i][j] * ratio;\n                h_cnt[i][j]++;\n            }\n        }\n        \n        // Smoothing: propagate information to same row/column\n        smooth(query_num);\n    }\n    \n    void smooth(int query_num) {\n        double smooth_lr = 0.05 * pow(0.995, query_num);\n        \n        // Smooth horizontal edges within each row\n        for(int i = 0; i < N; i++) {\n            double row_avg = 0;\n            int row_cnt = 0;\n            for(int j = 0; j < N-1; j++) {\n                if(h_cnt[i][j] > 0) {\n                    row_avg += h[i][j];\n                    row_cnt++;\n                }\n            }\n            if(row_cnt > 0) {\n                row_avg /= row_cnt;\n                for(int j = 0; j < N-1; j++) {\n                    if(h_cnt[i][j] > 0) {\n                        h[i][j] = (1-smooth_lr) * h[i][j] + smooth_lr * row_avg;\n                    }\n                }\n            }\n        }\n        \n        // Smooth vertical edges within each column\n        for(int j = 0; j < N; j++) {\n            double col_avg = 0;\n            int col_cnt = 0;\n            for(int i = 0; i < N-1; i++) {\n                if(v_cnt[i][j] > 0) {\n                    col_avg += v[i][j];\n                    col_cnt++;\n                }\n            }\n            if(col_cnt > 0) {\n                col_avg /= col_cnt;\n                for(int i = 0; i < N-1; i++) {\n                    if(v_cnt[i][j] > 0) {\n                        v[i][j] = (1-smooth_lr) * v[i][j] + smooth_lr * col_avg;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    mt19937 rng(42);\n    Solver solver;\n    \n    for(int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Exploration temperature decreases over time\n        // Higher early for exploration, lower later for exploitation\n        double temp = 300.0 * pow(0.994, k);\n        \n        auto [path, est_cost] = solver.dijkstra(si, sj, ti, tj, temp);\n        \n        cout << path << \"\\n\";\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        solver.update(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> S[i];\n    }\n    \n    vector<string> best_grid(N, string(N, '.'));\n    int best_matched = 0;\n    int best_empty = N * N;\n    \n    auto getScore = [&](int matched, int empty_cells) -> double {\n        if (matched < M) {\n            return 1e8 * (double)matched / M;\n        } else {\n            return 1e8 * (2.0 * N * N) / (2.0 * N * N - empty_cells);\n        }\n    };\n    \n    auto checkString = [&](const vector<string>& grid, const string& s) -> bool {\n        int k = (int)s.size();\n        int n = (int)grid.size();\n        if (k > n) return false;\n        \n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                bool match = true;\n                for (int p = 0; p < k; ++p) {\n                    if (grid[i][(j + p) % n] != s[p]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) return true;\n            }\n        }\n        \n        for (int j = 0; j < n; ++j) {\n            for (int i = 0; i < n; ++i) {\n                bool match = true;\n                for (int p = 0; p < k; ++p) {\n                    if (grid[(i + p) % n][j] != s[p]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) return true;\n            }\n        }\n        \n        return false;\n    };\n    \n    auto solve = [&](int seed) -> pair<vector<string>, int> {\n        mt19937 rng(seed);\n        vector<string> grid(N, string(N, '.'));\n        vector<int> indices(M);\n        for (int i = 0; i < M; ++i) indices[i] = i;\n        \n        shuffle(indices.begin(), indices.end(), rng);\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            return S[a].size() > S[b].size();\n        });\n        \n        vector<bool> placed(M, false);\n        \n        for (int idx : indices) {\n            const string& s = S[idx];\n            int k = (int)s.size();\n            int best_orient = -1;\n            int best_i = -1, best_j = -1;\n            int best_score = -1;\n            \n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    int dot_count = 0;\n                    bool ok = true;\n                    for (int p = 0; p < k; ++p) {\n                        int col = (j + p) % N;\n                        if (grid[i][col] != '.' && grid[i][col] != s[p]) {\n                            ok = false;\n                            break;\n                        }\n                        if (grid[i][col] == '.') dot_count++;\n                    }\n                    if (ok) {\n                        int score = dot_count * 1000 + (rng() % 100);\n                        if (score > best_score) {\n                            best_score = score;\n                            best_orient = 0;\n                            best_i = i;\n                            best_j = j;\n                        }\n                    }\n                }\n            }\n            \n            for (int j = 0; j < N; ++j) {\n                for (int i = 0; i < N; ++i) {\n                    int dot_count = 0;\n                    bool ok = true;\n                    for (int p = 0; p < k; ++p) {\n                        int row = (i + p) % N;\n                        if (grid[row][j] != '.' && grid[row][j] != s[p]) {\n                            ok = false;\n                            break;\n                        }\n                        if (grid[row][j] == '.') dot_count++;\n                    }\n                    if (ok) {\n                        int score = dot_count * 1000 + (rng() % 100);\n                        if (score > best_score) {\n                            best_score = score;\n                            best_orient = 1;\n                            best_i = i;\n                            best_j = j;\n                        }\n                    }\n                }\n            }\n            \n            if (best_score >= 0) {\n                placed[idx] = true;\n                for (int p = 0; p < k; ++p) {\n                    int r, c;\n                    if (best_orient == 0) {\n                        r = best_i;\n                        c = (best_j + p) % N;\n                    } else {\n                        r = (best_i + p) % N;\n                        c = best_j;\n                    }\n                    if (grid[r][c] == '.') {\n                        grid[r][c] = s[p];\n                    }\n                }\n            }\n        }\n        \n        vector<int> cnt(256, 0);\n        for (int i = 0; i < M; ++i) {\n            if (!placed[i]) {\n                for (char c : S[i]) cnt[(unsigned char)c]++;\n            }\n        }\n        \n        char fill_char = 'A';\n        int max_cnt = 0;\n        for (char c : string(\"ABCDEFGH\")) {\n            if (cnt[(unsigned char)c] > max_cnt) {\n                max_cnt = cnt[(unsigned char)c];\n                fill_char = c;\n            }\n        }\n        \n        if (max_cnt == 0) {\n            fill_char = 'A';\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == '.') grid[i][j] = fill_char;\n            }\n        }\n        \n        int matched = 0;\n        for (int i = 0; i < M; ++i) {\n            if (checkString(grid, S[i])) matched++;\n        }\n        \n        return {grid, matched};\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    int time_limit_ms = 2800;\n    int trial = 0;\n    \n    while (true) {\n        auto check_time = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(check_time - start_time).count();\n        if (elapsed > time_limit_ms) break;\n        \n        auto [grid, matched] = solve(trial * 12345 + 67890);\n        \n        int empty_cells = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == '.') empty_cells++;\n            }\n        }\n        \n        double score = getScore(matched, empty_cells);\n        double best_score = getScore(best_matched, best_empty);\n        \n        if (score > best_score || (matched > best_matched && score == best_score)) {\n            best_matched = matched;\n            best_empty = empty_cells;\n            best_grid = grid;\n        }\n        \n        if (matched == M && empty_cells == 0) break;\n        \n        trial++;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << best_grid[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <map>\n#include <functional>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nchrono::steady_clock::time_point start_time;\n\n// Get remaining time in milliseconds\nlong long timeRemaining() {\n    auto now = chrono::steady_clock::now();\n    return max(0LL, 2900LL - (long long)chrono::duration_cast<chrono::milliseconds>(now - start_time).count());\n}\n\nint flatten(int r, int c) {\n    return r * N + c;\n}\n\nPoint unflatten(int idx) {\n    return {idx / N, idx % N};\n}\n\nint get_cost(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N || grid[r][c] == '#') return 1e9;\n    return grid[r][c] - '0';\n}\n\n// Get all road squares\nvector<Point> getAllRoads() {\n    vector<Point> roads;\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    return roads;\n}\n\n// Check if road square (tr, tc) is visible from (sr, sc)\nbool isVisible(int sr, int sc, int tr, int tc) {\n    if (grid[sr][sc] == '#' || grid[tr][tc] == '#') return false;\n    \n    if (sr == tr) {\n        int min_c = min(sc, tc), max_c = max(sc, tc);\n        for (int c = min_c; c <= max_c; ++c) {\n            if (grid[sr][c] == '#') return false;\n        }\n        return true;\n    }\n    if (sc == tc) {\n        int min_r = min(sr, tr), max_r = max(sr, tr);\n        for (int r = min_r; r <= max_r; ++r) {\n            if (grid[r][sc] == '#') return false;\n        }\n        return true;\n    }\n    return false;\n}\n\n// Get all visible road squares from a point\nvector<int> getVisibleFrom(int r, int c, const vector<Point>& all_roads) {\n    vector<int> visible;\n    if (grid[r][c] == '#') return visible;\n    \n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        if (isVisible(r, c, all_roads[i].r, all_roads[i].c)) {\n            visible.push_back(i);\n        }\n    }\n    return visible;\n}\n\n// Reconstruct path from parents\nstring reconstruct_path(int start_node, int end_node, const vector<int>& parent) {\n    if (start_node == end_node) return \"\";\n    vector<int> path;\n    int curr = end_node;\n    while (curr != start_node) {\n        if (curr == -1) return \"\";\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    \n    string res = \"\";\n    int curr_r = start_node / N;\n    int curr_c = start_node % N;\n    \n    for (int node : path) {\n        int nr = node / N;\n        int nc = node % N;\n        if (nr < curr_r) res += 'U';\n        else if (nr > curr_r) res += 'D';\n        else if (nc < curr_c) res += 'L';\n        else if (nc > curr_c) res += 'R';\n        curr_r = nr;\n        curr_c = nc;\n    }\n    return res;\n}\n\n// Dijkstra from a point\npair<vector<long long>, vector<int>> dijkstra(int sr, int sc) {\n    int start_node = flatten(sr, sc);\n    vector<long long> d(N * N, -1);\n    vector<int> p(N * N, -1);\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n\n    d[start_node] = 0;\n    pq.push({0, start_node});\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        auto [dist_val, u] = pq.top();\n        pq.pop();\n\n        if (d[u] != -1 && dist_val > d[u]) continue;\n\n        Point pu = unflatten(u);\n        for (int k = 0; k < 4; ++k) {\n            int nr = pu.r + dr[k];\n            int nc = pu.c + dc[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int v = flatten(nr, nc);\n                long long new_dist = dist_val + get_cost(nr, nc);\n                if (d[v] == -1 || new_dist < d[v]) {\n                    d[v] = new_dist;\n                    p[v] = u;\n                    pq.push({new_dist, v});\n                }\n            }\n        }\n    }\n    return {d, p};\n}\n\n// Calculate tour cost\nlong long calc_tour_cost(const vector<int>& tour, const vector<vector<long long>>& dist_mat) {\n    long long cost = 0;\n    int K = (int)tour.size();\n    for (int i = 0; i < K; ++i) {\n        int u = tour[i];\n        int v = tour[(i + 1) % K];\n        if (dist_mat[u][v] == -1) return 1e18;\n        cost += dist_mat[u][v];\n    }\n    return cost;\n}\n\n// Check if tour covers all roads\nbool checkCoverage(const vector<int>& tour, const vector<int>& selected_indices,\n                   const vector<vector<int>>& visibility, int total_roads) {\n    vector<bool> covered(total_roads, false);\n    int count = 0;\n    for (int idx : tour) {\n        int road_idx = selected_indices[idx];\n        for (int vis : visibility[road_idx]) {\n            if (!covered[vis]) {\n                covered[vis] = true;\n                count++;\n            }\n        }\n    }\n    return count == total_roads;\n}\n\n// 2-opt optimization with time awareness\nvoid two_opt(vector<int>& tour, const vector<vector<long long>>& dist_mat) {\n    int K = (int)tour.size();\n    if (K < 3) return;\n    \n    bool improved = true;\n    while (improved && timeRemaining() > 100) {\n        improved = false;\n        for (int i = 0; i < K - 1; ++i) {\n            for (int j = i + 1; j < K; ++j) {\n                if (i + 1 >= j) continue;\n                \n                int u = tour[i];\n                int v = tour[i+1];\n                int x = tour[j];\n                int y = tour[(j+1)%K];\n                \n                if (dist_mat[u][x] == -1 || dist_mat[v][y] == -1) continue;\n                if (dist_mat[u][v] == -1 || dist_mat[x][y] == -1) continue;\n\n                long long old_cost = dist_mat[u][v] + dist_mat[x][y];\n                long long new_cost = dist_mat[u][x] + dist_mat[v][y];\n                \n                if (new_cost < old_cost) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n            if (timeRemaining() < 50) break;\n        }\n    }\n}\n\n// Greedy checkpoint selection with different ordering strategies\nvector<int> greedySelect(const vector<Point>& all_roads, \n                         const vector<vector<int>>& visibility,\n                         const map<Point, int>& road_index,\n                         Point start_p,\n                         int strategy,\n                         mt19937& rng) {\n    int total_roads = (int)all_roads.size();\n    vector<int> selected_indices;\n    vector<bool> covered(total_roads, false);\n    int covered_count = 0;\n    \n    int start_road_idx = road_index.at(start_p);\n    selected_indices.push_back(start_road_idx);\n    for (int idx : visibility[start_road_idx]) {\n        if (!covered[idx]) {\n            covered[idx] = true;\n            covered_count++;\n        }\n    }\n\n    while (covered_count < total_roads && timeRemaining() > 100) {\n        vector<pair<double, int>> candidates;\n        \n        for (int i = 0; i < (int)all_roads.size(); ++i) {\n            bool already_selected = false;\n            for (int idx : selected_indices) {\n                if (idx == i) {\n                    already_selected = true;\n                    break;\n                }\n            }\n            if (already_selected) continue;\n            \n            int new_covered = 0;\n            for (int idx : visibility[i]) {\n                if (!covered[idx]) new_covered++;\n            }\n            \n            if (new_covered > 0 || strategy == 2) {\n                double score = new_covered;\n                \n                // Strategy 0: Pure coverage (original)\n                // Strategy 1: Coverage with slight randomization\n                // Strategy 2: Force adding some points even with 0 new coverage\n                \n                if (strategy == 1 && candidates.size() > 0) {\n                    score += (rng() % 100) * 0.01;\n                }\n                \n                if (new_covered > 0) {\n                    candidates.push_back({score, i});\n                }\n            }\n        }\n        \n        if (candidates.empty()) {\n            // Fallback: add any unselected road\n            for (int i = 0; i < (int)all_roads.size(); ++i) {\n                bool already = false;\n                for (int idx : selected_indices) {\n                    if (idx == i) { already = true; break; }\n                }\n                if (!already) {\n                    candidates.push_back({0, i});\n                    break;\n                }\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        sort(candidates.rbegin(), candidates.rend());\n        \n        int pick_idx = 0;\n        if (strategy == 1 && candidates.size() > 1) {\n            pick_idx = (int)(rng() % min((size_t)candidates.size(), (size_t)5));\n        }\n        \n        int best_point = candidates[pick_idx].second;\n        selected_indices.push_back(best_point);\n        for (int idx : visibility[best_point]) {\n            if (!covered[idx]) {\n                covered[idx] = true;\n                covered_count++;\n            }\n        }\n    }\n    \n    return selected_indices;\n}\n\n// Try to prune tour aggressively\nvector<int> pruneTour(vector<int> tour, \n                      const vector<int>& selected_indices,\n                      const vector<vector<int>>& visibility,\n                      const vector<vector<long long>>& dist_mat,\n                      int total_roads,\n                      int start_idx) {\n    if ((int)tour.size() <= 2) return tour;\n    \n    bool changed = true;\n    while (changed && timeRemaining() > 200) {\n        changed = false;\n        \n        // Try removing single checkpoints\n        for (size_t i = 0; i < tour.size(); ++i) {\n            if (tour[i] == start_idx) continue;\n            \n            vector<int> test_tour;\n            for (size_t j = 0; j < tour.size(); ++j) {\n                if (j != i) test_tour.push_back(tour[j]);\n            }\n            \n            if (checkCoverage(test_tour, selected_indices, visibility, total_roads)) {\n                long long test_cost = calc_tour_cost(test_tour, dist_mat);\n                long long orig_cost = calc_tour_cost(tour, dist_mat);\n                if (test_cost < orig_cost) {\n                    tour = test_tour;\n                    changed = true;\n                    break;\n                }\n            }\n            if (timeRemaining() < 100) break;\n        }\n        \n        if (changed) continue;\n        \n        // Try removing pairs\n        if ((int)tour.size() > 3) {\n            for (size_t i = 0; i < tour.size(); ++i) {\n                if (tour[i] == start_idx) continue;\n                for (size_t j = i + 1; j < tour.size(); ++j) {\n                    if (tour[j] == start_idx) continue;\n                    \n                    vector<int> test_tour;\n                    for (size_t k = 0; k < tour.size(); ++k) {\n                        if (k != i && k != j) test_tour.push_back(tour[k]);\n                    }\n                    \n                    if ((int)test_tour.size() >= 2 && \n                        checkCoverage(test_tour, selected_indices, visibility, total_roads)) {\n                        long long test_cost = calc_tour_cost(test_tour, dist_mat);\n                        long long orig_cost = calc_tour_cost(tour, dist_mat);\n                        if (test_cost < orig_cost) {\n                            tour = test_tour;\n                            changed = true;\n                            break;\n                        }\n                    }\n                    if (timeRemaining() < 100) break;\n                }\n                if (changed) break;\n                if (timeRemaining() < 100) break;\n            }\n        }\n    }\n    \n    return tour;\n}\n\nstruct Solution {\n    vector<int> tour;\n    vector<int> selected_indices;\n    vector<Point> selected_points;\n    vector<vector<int>> all_parents;\n    long long cost;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    start_time = chrono::steady_clock::now();\n\n    if (!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    vector<Point> all_roads = getAllRoads();\n    int total_roads = (int)all_roads.size();\n    \n    Point start_p = {si, sj};\n    \n    // Precompute visibility\n    vector<vector<int>> visibility(all_roads.size());\n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        visibility[i] = getVisibleFrom(all_roads[i].r, all_roads[i].c, all_roads);\n    }\n    \n    map<Point, int> road_index;\n    for (int i = 0; i < (int)all_roads.size(); ++i) {\n        road_index[all_roads[i]] = i;\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Generate multiple checkpoint sets\n    vector<vector<int>> all_selected;\n    \n    // Strategy 0: Pure greedy (most reliable)\n    {\n        mt19937 local_rng(rng());\n        all_selected.push_back(greedySelect(all_roads, visibility, road_index, start_p, 0, local_rng));\n    }\n    \n    // Strategy 1: With randomization (try 3 variants)\n    for (int seed = 0; seed < 3 && timeRemaining() > 500; ++seed) {\n        mt19937 local_rng(rng() + seed + 1000);\n        all_selected.push_back(greedySelect(all_roads, visibility, road_index, start_p, 1, local_rng));\n    }\n    \n    Solution best_solution;\n    best_solution.cost = 1e18;\n    \n    // Process each checkpoint set\n    for (auto& selected_indices : all_selected) {\n        if (timeRemaining() < 300) break;\n        \n        vector<Point> selected_points;\n        for (int idx : selected_indices) {\n            selected_points.push_back(all_roads[idx]);\n        }\n\n        int K = (int)selected_points.size();\n        int start_idx = 0;\n        \n        for (int i = 0; i < K; ++i) {\n            if (selected_points[i] == start_p) {\n                start_idx = i;\n                break;\n            }\n        }\n        \n        // All-Pairs Shortest Paths\n        vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n        vector<vector<int>> all_parents(K);\n\n        for (int i = 0; i < K; ++i) {\n            auto [d, p] = dijkstra(selected_points[i].r, selected_points[i].c);\n            all_parents[i] = p;\n            for (int j = 0; j < K; ++j) {\n                int t_node = flatten(selected_points[j].r, selected_points[j].c);\n                dist_mat[i][j] = d[t_node];\n            }\n        }\n\n        // TSP with multiple restarts based on remaining time\n        int num_restarts = min(60, (int)(timeRemaining() / 40 / max(1, K)));\n        for (int restart = 0; restart < num_restarts && timeRemaining() > 100; ++restart) {\n            vector<int> tour;\n            vector<bool> visited(K, false);\n            int curr = start_idx;\n            tour.push_back(curr);\n            visited[curr] = true;\n            \n            for (int i = 0; i < K - 1; ++i) {\n                vector<pair<long long, int>> candidates;\n                for (int j = 0; j < K; ++j) {\n                    if (!visited[j] && dist_mat[curr][j] != -1) {\n                        candidates.push_back({dist_mat[curr][j], j});\n                    }\n                }\n                if (candidates.empty()) break;\n                \n                sort(candidates.begin(), candidates.end());\n                int pick_idx = 0;\n                if (restart > 0 && (int)candidates.size() > 1) {\n                    pick_idx = (int)(rng() % min((size_t)candidates.size(), (size_t)5));\n                }\n                int next = candidates[pick_idx].second;\n                \n                tour.push_back(next);\n                visited[next] = true;\n                curr = next;\n            }\n            \n            two_opt(tour, dist_mat);\n            \n            // Prune on first few iterations\n            if (restart < 3 && timeRemaining() > 400) {\n                tour = pruneTour(tour, selected_indices, visibility, dist_mat, total_roads, start_idx);\n                two_opt(tour, dist_mat);\n            }\n            \n            long long cost = calc_tour_cost(tour, dist_mat);\n            if (cost < best_solution.cost && checkCoverage(tour, selected_indices, visibility, total_roads)) {\n                best_solution.cost = cost;\n                best_solution.tour = tour;\n                best_solution.selected_indices = selected_indices;\n                best_solution.selected_points = selected_points;\n                best_solution.all_parents = all_parents;\n            }\n        }\n    }\n\n    // Fallback if nothing found\n    if (best_solution.tour.empty()) {\n        best_solution.tour = {0};\n        best_solution.selected_indices = {road_index[start_p]};\n        best_solution.selected_points = {start_p};\n        auto [d, p] = dijkstra(si, sj);\n        best_solution.all_parents = {p};\n    }\n    \n    // Final optimization pass with remaining time\n    if (timeRemaining() > 500 && best_solution.selected_points.size() >= 2) {\n        int K = (int)best_solution.selected_points.size();\n        vector<vector<long long>> dist_mat(K, vector<long long>(K, 0));\n        \n        for (int i = 0; i < K; ++i) {\n            for (int j = 0; j < K; ++j) {\n                int t_node = flatten(best_solution.selected_points[j].r, best_solution.selected_points[j].c);\n                auto [d, p] = dijkstra(best_solution.selected_points[i].r, best_solution.selected_points[i].c);\n                dist_mat[i][j] = d[t_node];\n            }\n        }\n        \n        int start_idx = 0;\n        for (int i = 0; i < K; ++i) {\n            if (best_solution.selected_points[i] == start_p) {\n                start_idx = i;\n                break;\n            }\n        }\n        \n        // More aggressive 2-opt\n        two_opt(best_solution.tour, dist_mat);\n        \n        // Final prune\n        best_solution.tour = pruneTour(best_solution.tour, best_solution.selected_indices, \n                                        visibility, dist_mat, total_roads, start_idx);\n        two_opt(best_solution.tour, dist_mat);\n        \n        best_solution.cost = calc_tour_cost(best_solution.tour, dist_mat);\n    }\n\n    // Reconstruct Full Path\n    string final_path = \"\";\n    for (size_t i = 0; i < best_solution.tour.size(); ++i) {\n        int u = best_solution.tour[i];\n        int v = best_solution.tour[(i + 1) % best_solution.tour.size()];\n        string segment = reconstruct_path(flatten(best_solution.selected_points[u].r, best_solution.selected_points[u].c), \n                                          flatten(best_solution.selected_points[v].r, best_solution.selected_points[v].c), \n                                          best_solution.all_parents[u]);\n        final_path += segment;\n    }\n\n    cout << final_path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <iomanip>\n#include <queue>\n\nusing namespace std;\n\nconst int MAX_N = 1005;\nconst int MAX_DAY = 2000;\n\nstruct Task {\n    int id;\n    vector<int> d;\n    int in_degree = 0;\n    vector<int> dependents;\n    vector<int> dependencies;\n    int priority = 0;\n    int status = -1;\n    int assigned_member = -1;\n    int start_day = 0;\n    int difficulty = 0;\n    int critical_path_length = 0;\n    int depth = 0;\n};\n\nstruct Member {\n    int id;\n    vector<int> s;\n    vector<int> s_sum;\n    vector<int> s_count;\n    int busy_until = 0;\n    int current_task = -1;\n    int start_day = 0;\n    int tasks_completed = 0;\n    bool has_active_task = false;\n    double total_work = 0;\n    int total_error = 0;\n    int total_predicted = 0;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, K, R;\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    vector<Task> tasks(N + 1);\n    int max_task_difficulty = 0;\n    int total_difficulty = 0;\n    vector<int> max_skill_requirement(K, 0);\n    vector<int> avg_skill_requirement(K, 0);\n    \n    for (int i = 1; i <= N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        int task_sum = 0;\n        for (int j = 0; j < K; ++j) {\n            cin >> tasks[i].d[j];\n            task_sum += tasks[i].d[j];\n            max_skill_requirement[j] = max(max_skill_requirement[j], tasks[i].d[j]);\n            avg_skill_requirement[j] += tasks[i].d[j];\n        }\n        tasks[i].difficulty = task_sum;\n        total_difficulty += task_sum;\n        max_task_difficulty = max(max_task_difficulty, task_sum);\n    }\n    \n    for (int j = 0; j < K; ++j) {\n        avg_skill_requirement[j] /= N;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        tasks[v].in_degree++;\n        tasks[u].dependents.push_back(v);\n        tasks[v].dependencies.push_back(u);\n    }\n\n    // Compute depth (longest path from root)\n    queue<int> q;\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            tasks[i].depth = 0;\n            q.push(i);\n        }\n    }\n    \n    vector<int> topo_order;\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        topo_order.push_back(u);\n        for (int v : tasks[u].dependents) {\n            tasks[v].depth = max(tasks[v].depth, tasks[u].depth + 1);\n            tasks[v].in_degree--;\n            if (tasks[v].in_degree == 0) {\n                q.push(v);\n            }\n        }\n    }\n\n    // Compute critical path length (longest path to end)\n    vector<int> longest_path(N + 1, 0);\n    for (int i = N; i >= 1; --i) {\n        int u = topo_order[i-1];\n        longest_path[u] = tasks[u].difficulty;\n        for (int v : tasks[u].dependents) {\n            longest_path[u] = max(longest_path[u], tasks[u].difficulty + longest_path[v]);\n        }\n        tasks[u].critical_path_length = longest_path[u];\n    }\n\n    // Compute priority (number of reachable tasks)\n    vector<bitset<MAX_N>> reach(N + 1);\n    for (int i = N; i >= 1; --i) {\n        int u = topo_order[i-1];\n        reach[u][u] = 1;\n        for (int v : tasks[u].dependents) {\n            reach[u] |= reach[v];\n        }\n        tasks[u].priority = (int)reach[u].count();\n    }\n\n    // Reset in_degree for actual scheduling\n    for (int i = 1; i <= N; ++i) {\n        tasks[i].in_degree = (int)tasks[i].dependencies.size();\n    }\n\n    vector<Member> members(M + 1);\n    for (int j = 1; j <= M; ++j) {\n        members[j].id = j;\n        members[j].s.assign(K, 0);\n        members[j].s_sum.assign(K, 0);\n        members[j].s_count.assign(K, 0);\n        members[j].busy_until = 0;\n        members[j].has_active_task = false;\n    }\n\n    vector<int> ready_tasks;\n    ready_tasks.reserve(N);\n    for (int i = 1; i <= N; ++i) {\n        if (tasks[i].in_degree == 0) {\n            ready_tasks.push_back(i);\n        }\n    }\n\n    int current_day = 0;\n    const double ALPHA_BASE = 0.8;\n    int completed_count = 0;\n    int active_member_count = 0;\n    int remaining_tasks = N;\n    \n    // Track prediction accuracy for buffer adjustment\n    vector<double> prediction_errors;\n    prediction_errors.reserve(200);\n    double avg_error_ratio = 1.0;\n\n    while (true) {\n        current_day++;\n        \n        // Very conservative stop day - we want to finish early anyway\n        int dynamic_stop_day = MAX_DAY - 150;\n        bool can_assign = (current_day <= dynamic_stop_day);\n        \n        vector<pair<int, int>> assignments;\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int j = 1; j <= M; ++j) {\n            if (!members[j].has_active_task) {\n                free_members.push_back(j);\n            }\n        }\n\n        if (can_assign && !free_members.empty() && !ready_tasks.empty()) {\n            vector<int> candidates;\n            candidates.reserve(ready_tasks.size());\n            for (int t_idx : ready_tasks) {\n                if (tasks[t_idx].status == -1) {\n                    candidates.push_back(t_idx);\n                }\n            }\n            \n            // Sort by critical path (most important first), then by depth\n            sort(candidates.begin(), candidates.end(), [&](int a, int b) {\n                if (tasks[a].critical_path_length != tasks[b].critical_path_length)\n                    return tasks[a].critical_path_length > tasks[b].critical_path_length;\n                if (tasks[a].priority != tasks[b].priority)\n                    return tasks[a].priority > tasks[b].priority;\n                return tasks[a].depth < tasks[b].depth; // Prefer earlier depth first\n            });\n\n            for (int t_idx : candidates) {\n                if (tasks[t_idx].status != -1) continue;\n                if (free_members.empty()) break;\n\n                int best_m = -1;\n                int min_t = 2000000000;\n                double best_score = 1e18;\n                \n                for (int m_idx : free_members) {\n                    int w = 0;\n                    double skill_coverage = 0;\n                    \n                    for (int k = 0; k < K; ++k) {\n                        int deficit = max(0, tasks[t_idx].d[k] - members[m_idx].s[k]);\n                        w += deficit;\n                        if (tasks[t_idx].d[k] > 0) {\n                            skill_coverage += min(1.0, (double)members[m_idx].s[k] / tasks[t_idx].d[k]);\n                        }\n                    }\n                    skill_coverage /= K;\n                    \n                    // Very aggressive buffer reduction based on experience\n                    int buffer = 5;\n                    if (members[m_idx].tasks_completed >= 3) buffer = 3;\n                    if (members[m_idx].tasks_completed >= 8) buffer = 2;\n                    if (members[m_idx].tasks_completed >= 15) buffer = 1;\n                    if (members[m_idx].tasks_completed >= 25) buffer = 0;\n                    \n                    // Adjust buffer based on prediction accuracy\n                    if (!prediction_errors.empty()) {\n                        buffer = max(0, buffer + (int)(avg_error_ratio * 2));\n                    }\n                    \n                    int t_est = max(1, w + buffer);\n                    \n                    // Ensure task completes before limit\n                    if (current_day + t_est - 1 >= MAX_DAY - 5) continue;\n                    \n                    // Score: minimize time, balance load, maximize skill match\n                    double load_ratio = (members[m_idx].tasks_completed == 0) ? 0 : \n                                       members[m_idx].total_work / members[m_idx].tasks_completed;\n                    double score = t_est * 1000 + load_ratio * 10 - skill_coverage * 100;\n                    \n                    if (t_est < min_t || (t_est == min_t && score < best_score)) {\n                        min_t = t_est;\n                        best_m = m_idx;\n                        best_score = score;\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_idx});\n                    tasks[t_idx].status = 0;\n                    tasks[t_idx].assigned_member = best_m;\n                    tasks[t_idx].start_day = current_day;\n                    \n                    members[best_m].busy_until = current_day + min_t - 1;\n                    members[best_m].current_task = t_idx;\n                    members[best_m].start_day = current_day;\n                    members[best_m].has_active_task = true;\n                    members[best_m].total_work += min_t;\n                    active_member_count++;\n                    \n                    for (auto it = free_members.begin(); it != free_members.end(); ++it) {\n                        if (*it == best_m) {\n                            free_members.erase(it);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << \"\\n\";\n        \n        // Output skill predictions\n        if (current_day % 200 == 1) {\n            for (int j = 1; j <= M; ++j) {\n                if (members[j].tasks_completed > 0) {\n                    cout << \"#s \" << j;\n                    for (int k = 0; k < K; ++k) {\n                        cout << \" \" << members[j].s[k];\n                    }\n                    cout << \"\\n\";\n                }\n            }\n        }\n        cout.flush();\n\n        // Read completion info\n        int n_fin;\n        cin >> n_fin;\n        if (n_fin == -1) {\n            break;\n        }\n\n        vector<int> finished_members(n_fin);\n        for (int i = 0; i < n_fin; ++i) {\n            cin >> finished_members[i];\n        }\n\n        for (int m_idx : finished_members) {\n            int t_idx = members[m_idx].current_task;\n            if (t_idx == -1) continue;\n\n            int duration = current_day - members[m_idx].start_day + 1;\n            int t_obs = duration;\n            \n            // Calculate predicted duration for error tracking\n            int w_pred = 0;\n            vector<int> active_dims;\n            active_dims.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (tasks[t_idx].d[k] > members[m_idx].s[k]) {\n                    w_pred += tasks[t_idx].d[k] - members[m_idx].s[k];\n                    active_dims.push_back(k);\n                }\n            }\n            int t_pred = (w_pred == 0) ? 1 : w_pred;\n            members[m_idx].total_predicted += t_pred;\n            \n            // Track prediction error\n            if (t_pred > 0) {\n                double error_ratio = (double)t_obs / t_pred;\n                prediction_errors.push_back(error_ratio);\n                if (prediction_errors.size() > 50) {\n                    prediction_errors.erase(prediction_errors.begin());\n                }\n                double sum_errors = 0;\n                for (double e : prediction_errors) sum_errors += e;\n                avg_error_ratio = sum_errors / prediction_errors.size();\n            }\n            \n            // Skill Update - More aggressive early learning\n            double error = (double)t_obs - t_pred;\n            members[m_idx].total_error += abs((int)error);\n            \n            if (!active_dims.empty()) {\n                // Much more aggressive learning early on\n                double alpha = ALPHA_BASE;\n                int exp = members[m_idx].tasks_completed;\n                \n                if (exp < 3) alpha = 1.0;       // Very aggressive first 3 tasks\n                else if (exp < 8) alpha = 0.7;  // Aggressive next 5\n                else if (exp < 15) alpha = 0.5; // Moderate\n                else if (exp < 30) alpha = 0.3; // Conservative\n                else alpha = 0.2;                // Very conservative\n                \n                alpha = max(0.15, min(1.0, alpha));\n                \n                double update_per_dim = alpha * error / active_dims.size();\n                \n                for (int k : active_dims) {\n                    double new_s = members[m_idx].s[k] - update_per_dim;\n                    new_s = max(0.0, new_s);\n                    // Cap at max observed requirement + margin\n                    new_s = min((double)max_skill_requirement[k] + 20, new_s);\n                    \n                    // Incremental average for skill estimation\n                    members[m_idx].s_count[k]++;\n                    members[m_idx].s_sum[k] += (int)round(new_s);\n                    members[m_idx].s[k] = (int)round(new_s);\n                }\n            }\n\n            tasks[t_idx].status = 1;\n            completed_count++;\n            remaining_tasks--;\n            members[m_idx].current_task = -1;\n            members[m_idx].has_active_task = false;\n            members[m_idx].tasks_completed++;\n            active_member_count--;\n\n            // Update Dependencies\n            for (int v : tasks[t_idx].dependents) {\n                tasks[v].in_degree--;\n                if (tasks[v].in_degree == 0) {\n                    ready_tasks.push_back(v);\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n};\n\ninline int manhattan(const Point& p1, const Point& p2) {\n    return abs(p1.x - p2.x) + abs(p1.y - p2.y);\n}\n\nconst Point CENTER = {400, 400};\nvector<Order> orders(1000);\nPoint pickups[1000], deliveries[1000];\n\n// Path: sequence of 100 nodes (50 pickups + 50 deliveries)\n// Each node: (order_id, type) where type 0=pickup, 1=delivery\nstruct Node {\n    int order_id;\n    int type; // 0=pickup, 1=delivery\n};\n\nvector<Node> path;\nbool selected[1000];\n\nint calc_cost(const vector<Node>& p) {\n    int cost = 0;\n    Point prev = CENTER;\n    for (const auto& node : p) {\n        Point curr = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cost += manhattan(prev, curr);\n        prev = curr;\n    }\n    cost += manhattan(prev, CENTER);\n    return cost;\n}\n\n// Validate path: each selected order has pickup before delivery\nbool validate_path(const vector<Node>& p, const bool* sel) {\n    int pickup_pos[1000];\n    fill(pickup_pos, pickup_pos + 1000, -1);\n    \n    for (int i = 0; i < 100; ++i) {\n        if (p[i].type == 0) {\n            pickup_pos[p[i].order_id] = i;\n        } else {\n            if (pickup_pos[p[i].order_id] == -1) return false;\n            if (pickup_pos[p[i].order_id] >= i) return false;\n        }\n    }\n    \n    // Check all selected orders are in path\n    for (int i = 0; i < 1000; ++i) {\n        if (sel[i]) {\n            if (pickup_pos[i] == -1) return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Read input\n    for (int i = 0; i < 1000; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        pickups[i] = {orders[i].ax, orders[i].ay};\n        deliveries[i] = {orders[i].cx, orders[i].cy};\n    }\n    \n    mt19937 rng(1337);\n    \n    // Initial selection: pick 50 orders with smallest round-trip cost\n    vector<pair<int, int>> scores;\n    scores.reserve(1000);\n    for (int i = 0; i < 1000; ++i) {\n        int score = manhattan(CENTER, pickups[i]) + \n                    manhattan(pickups[i], deliveries[i]) + \n                    manhattan(deliveries[i], CENTER);\n        scores.push_back({score, i});\n    }\n    sort(scores.begin(), scores.end());\n    \n    fill(selected, selected + 1000, false);\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected[scores[i].second] = true;\n        selected_orders.push_back(scores[i].second);\n    }\n    \n    // Initial path: sort by angle from center, pickup then delivery for each\n    vector<pair<double, int>> angled;\n    angled.reserve(50);\n    for (int oid : selected_orders) {\n        int mx = (pickups[oid].x + deliveries[oid].x) / 2;\n        int my = (pickups[oid].y + deliveries[oid].y) / 2;\n        double angle = atan2(my - 400, mx - 400);\n        angled.push_back({angle, oid});\n    }\n    sort(angled.begin(), angled.end());\n    \n    path.clear();\n    path.reserve(100);\n    for (const auto& p : angled) {\n        path.push_back({p.second, 0}); // pickup\n        path.push_back({p.second, 1}); // delivery\n    }\n    \n    int best_cost = calc_cost(path);\n    vector<Node> best_path = path;\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.90;\n    \n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    uniform_int_distribution<int> dist_idx(0, 98);\n    \n    double temp = 5000.0;\n    int iter = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        temp *= 0.99995;\n        if (temp < 0.5) temp = 0.5;\n        \n        // Operation: swap two nodes while maintaining constraints\n        int i = dist_idx(rng);\n        int j = dist_idx(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        \n        // Ensure j > i\n        if (j <= i) { j = i + 1; if (j >= 100) { i = 98; j = 99; } }\n        \n        Node ni = path[i];\n        Node nj = path[j];\n        \n        // Find positions of complementary nodes\n        int ni_comp = -1, nj_comp = -1;\n        for (int k = 0; k < 100; ++k) {\n            if (k == i || k == j) continue;\n            if (path[k].order_id == ni.order_id) ni_comp = k;\n            if (path[k].order_id == nj.order_id) nj_comp = k;\n        }\n        \n        // Check if swap is valid\n        bool valid = true;\n        \n        // After swap: ni goes to position j, nj goes to position i\n        // For ni: if it's pickup (0), need comp (delivery) to be after j\n        //         if it's delivery (1), need comp (pickup) to be before j\n        if (ni.type == 0) { // pickup moving to j\n            if (ni_comp != -1 && ni_comp < j) valid = false;\n        } else { // delivery moving to j\n            if (ni_comp != -1 && ni_comp > j) valid = false;\n        }\n        \n        if (valid && nj.type == 0) { // pickup moving to i\n            if (nj_comp != -1 && nj_comp < i) valid = false;\n        } else if (valid) { // delivery moving to i\n            if (nj_comp != -1 && nj_comp > i) valid = false;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate delta cost (only affected edges)\n        auto get_point = [&](int idx, const vector<Node>& p) -> Point {\n            if (idx < 0 || idx >= 100) return CENTER;\n            if (p[idx].type == 0) return pickups[p[idx].order_id];\n            return deliveries[p[idx].order_id];\n        };\n        \n        int delta = 0;\n        \n        // Edges affected: (i-1,i), (i,i+1), (j-1,j), (j,j+1)\n        // But need to handle adjacency carefully\n        \n        vector<int> affected;\n        if (i > 0) affected.push_back(i - 1);\n        affected.push_back(i);\n        if (i < 99) affected.push_back(i + 1);\n        if (j > 0 && j - 1 != i) affected.push_back(j - 1);\n        if (j < 99 && j != i + 1) affected.push_back(j);\n        if (j < 99) affected.push_back(j + 1);\n        \n        // Remove duplicates and sort\n        sort(affected.begin(), affected.end());\n        affected.erase(unique(affected.begin(), affected.end()), affected.end());\n        \n        // Calculate old cost for affected edges\n        int old_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, path);\n                Point p2 = get_point(k + 1, path);\n                old_cost += manhattan(p1, p2);\n            }\n        }\n        \n        // Create new path (just for these positions)\n        vector<Node> new_path = path;\n        swap(new_path[i], new_path[j]);\n        \n        // Calculate new cost for affected edges\n        int new_cost = 0;\n        for (int k : affected) {\n            if (k >= 0 && k < 99) {\n                Point p1 = get_point(k, new_path);\n                Point p2 = get_point(k + 1, new_path);\n                new_cost += manhattan(p1, p2);\n            }\n        }\n        \n        delta = new_cost - old_cost;\n        \n        if (delta < 0 || dist_01(rng) < exp(-delta / temp)) {\n            swap(path[i], path[j]);\n            int cur_cost = calc_cost(path);\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_path = path;\n            }\n        }\n        \n        iter++;\n        if (iter % 10000 == 0) {\n            // Occasionally try a different initialization\n            if (dist_01(rng) < 0.1) {\n                // Shuffle and rebuild\n                shuffle(selected_orders.begin(), selected_orders.end(), rng);\n                path.clear();\n                for (int oid : selected_orders) {\n                    path.push_back({oid, 0});\n                    path.push_back({oid, 1});\n                }\n                int c = calc_cost(path);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_path = path;\n                }\n            }\n        }\n    }\n    \n    // Final validation\n    if (!validate_path(best_path, selected)) {\n        // Rebuild path from selected orders\n        path.clear();\n        for (int i = 0; i < 1000; ++i) {\n            if (selected[i]) {\n                path.push_back({i, 0});\n                path.push_back({i, 1});\n            }\n        }\n        best_path = path;\n        best_cost = calc_cost(best_path);\n    }\n    \n    // Output\n    cout << 50;\n    for (int i = 0; i < 1000; ++i) {\n        if (selected[i]) cout << \" \" << (i + 1);\n    }\n    cout << \"\\n\";\n    \n    cout << 102;\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    for (const auto& node : best_path) {\n        Point p = (node.type == 0) ? pickups[node.order_id] : deliveries[node.order_id];\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << \" \" << CENTER.x << \" \" << CENTER.y;\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Disjoint Set Union with path compression and union by rank\nstruct DSU {\n    vector<int> parent, rank_, size_;\n    int components;\n    \n    DSU(int n) : parent(n), rank_(n, 0), size_(n, 1), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    \n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        size_[x] += size_[y];\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        components--;\n        return true;\n    }\n    \n    int getSize(int x) {\n        return size_[find(x)];\n    }\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    // Read vertex coordinates\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    // Read edge endpoints and precompute expected distances\n    vector<pair<int, int>> edges(M);\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n        int u = edges[i].first, v = edges[i].second;\n        double dist = hypot(coords[u].first - coords[v].first, \n                           coords[u].second - coords[v].second);\n        d[i] = (int)round(dist);\n    }\n    \n    DSU dsu(N);\n    \n    // Process each edge online\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first, v = edges[i].second;\n        int remaining = M - 1 - i;  // Edges after this one (including current = remaining + 1)\n        int needed = dsu.components - 1;  // Minimum edges needed for connectivity\n        \n        bool connects = (dsu.find(u) != dsu.find(v));\n        bool accept = false;\n        \n        if (connects) {\n            // Edge quality ratio (actual length / minimum possible length)\n            double ratio = (double)l / max(1, d[i]);\n            \n            // Connectivity urgency: how critical is it to accept connecting edges?\n            // Use remaining + 1 to include current edge in available count\n            int available = remaining + 1;\n            double urgency = (double)needed / max(1, available);\n            \n            // Progress through the edge stream (0.0 to 1.0)\n            double progress = (double)i / (M - 1);\n            \n            // Base threshold: expected value is 2.0, max is 3.0\n            // We want to accept edges with ratio <= threshold\n            double threshold = 2.3;\n            \n            // Phase 1: Early phase (first 30%) - be selective but not too aggressive\n            if (progress < 0.3) {\n                threshold = 2.0 + urgency * 0.5;\n            }\n            // Phase 2: Middle phase (30-60%) - moderate selectivity\n            else if (progress < 0.6) {\n                threshold = 2.2 + urgency * 0.6;\n            }\n            // Phase 3: Late phase (60-80%) - prioritize connectivity\n            else if (progress < 0.8) {\n                threshold = 2.5 + urgency * 0.5;\n            }\n            // Phase 4: Critical phase (80%+) - very aggressive on connectivity\n            else {\n                threshold = 2.8 + urgency * 0.2;\n            }\n            \n            // Safety mechanism 1: Large buffer when running low on edges\n            // With M=1995 and N=400, we need 399 edges minimum\n            // But many edges will be redundant, so we need significant buffer\n            int safety_margin = 80;\n            if (available <= needed + safety_margin) {\n                threshold = 3.0;  // Accept any connecting edge\n            }\n            \n            // Safety mechanism 2: Critical zone - must accept all connecting edges\n            if (available <= needed + 30) {\n                accept = true;\n            }\n            // Safety mechanism 3: Very urgent - almost always accept\n            else if (urgency > 0.6) {\n                threshold = 3.0;\n            }\n            // Safety mechanism 4: Moderate urgency\n            else if (urgency > 0.4) {\n                threshold = max(threshold, 2.7);\n            }\n            \n            // Apply threshold if not already forced to accept\n            if (!accept && ratio <= threshold) {\n                accept = true;\n            }\n            \n            // Component size bonus: prefer edges connecting larger components\n            // This helps reduce components faster\n            if (!accept && connects) {\n                int combined_size = dsu.getSize(u) + dsu.getSize(v);\n                if (combined_size > N / 2 && ratio <= threshold + 0.3) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept && connects) {\n            dsu.unite(u, v);\n            cout << 1 << \"\\n\";\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        cout.flush();  // Ensure output is sent immediately\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\nconst int PET_SAFETY_MARGIN = 3;  // Very conservative\nconst int STOP_BLOCKING_TURN = 200;  // Stop blocking after this turn\n\nstruct Position {\n    int x, y;\n};\n\nclass Solver {\nprivate:\n    int N, M;\n    vector<Position> petPos;\n    vector<int> petType;\n    vector<Position> humanPos;\n    vector<vector<bool>> impassable;\n    \n    bool isValid(int x, int y) const {\n        return x >= 1 && x <= GRID_SIZE && y >= 1 && y <= GRID_SIZE;\n    }\n    \n    bool isPassable(int x, int y) const {\n        if (!isValid(x, y)) return false;\n        return !impassable[x-1][y-1];\n    }\n    \n    // Multiple redundant pet position checks\n    bool hasPetAt(int x, int y) const {\n        for (int i = 0; i < N; i++) {\n            if (petPos[i].x == x && petPos[i].y == y) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    bool hasHumanAt(int x, int y, int excludeIdx = -1) const {\n        for (int i = 0; i < M; i++) {\n            if (i == excludeIdx) continue;\n            if (humanPos[i].x == x && humanPos[i].y == y) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    bool hasPetAdjacent(int x, int y) const {\n        const int dx[4] = {-1, 1, 0, 0};\n        const int dy[4] = {0, 0, -1, 1};\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) && hasPetAt(nx, ny)) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    bool isNearPet(int x, int y, int margin = PET_SAFETY_MARGIN) const {\n        for (int i = 0; i < N; i++) {\n            int dist = abs(petPos[i].x - x) + abs(petPos[i].y - y);\n            if (dist <= margin) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // Ultra-paranoid block validation\n    bool canBlockSafe(int humanIdx, int targetX, int targetY,\n                      const vector<Position>& plannedBlocks) const {\n        if (!isValid(targetX, targetY)) return false;\n        if (impassable[targetX-1][targetY-1]) return false;\n        \n        // Triple-check for pets\n        if (hasPetAt(targetX, targetY)) return false;\n        if (hasPetAdjacent(targetX, targetY)) return false;\n        if (isNearPet(targetX, targetY)) return false;\n        \n        // Extra explicit pet check\n        for (int i = 0; i < N; i++) {\n            if (petPos[i].x == targetX && petPos[i].y == targetY) return false;\n            int dist = abs(petPos[i].x - targetX) + abs(petPos[i].y - targetY);\n            if (dist <= PET_SAFETY_MARGIN) return false;\n        }\n        \n        if (hasHumanAt(targetX, targetY, humanIdx)) return false;\n        \n        for (int i = 0; i < M; i++) {\n            if (i != humanIdx && plannedBlocks[i].x != -1) {\n                if (plannedBlocks[i].x == targetX && plannedBlocks[i].y == targetY) {\n                    return false;\n                }\n            }\n        }\n        \n        return true;\n    }\n    \n    bool canMove(int humanIdx, int toX, int toY,\n                 const vector<Position>& plannedMoves,\n                 const vector<Position>& plannedBlocks) const {\n        if (!isValid(toX, toY)) return false;\n        if (!isPassable(toX, toY)) return false;\n        \n        for (int i = 0; i < M; i++) {\n            if (i != humanIdx && plannedMoves[i].x != -1) {\n                if (plannedMoves[i].x == toX && plannedMoves[i].y == toY) {\n                    return false;\n                }\n            }\n        }\n        \n        for (int i = 0; i < M; i++) {\n            if (plannedBlocks[i].x != -1) {\n                if (plannedBlocks[i].x == toX && plannedBlocks[i].y == toY) {\n                    return false;\n                }\n            }\n        }\n        \n        return true;\n    }\n    \n    int minPetDistance(int x, int y) const {\n        int minDist = 10000;\n        for (int i = 0; i < N; i++) {\n            int dist = abs(petPos[i].x - x) + abs(petPos[i].y - y);\n            minDist = min(minDist, dist);\n        }\n        return minDist;\n    }\n    \npublic:\n    void readInput() {\n        cin >> N;\n        petPos.resize(N);\n        petType.resize(N);\n        for (int i = 0; i < N; i++) {\n            cin >> petPos[i].x >> petPos[i].y >> petType[i];\n        }\n        \n        cin >> M;\n        humanPos.resize(M);\n        for (int i = 0; i < M; i++) {\n            cin >> humanPos[i].x >> humanPos[i].y;\n        }\n        \n        impassable.assign(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    }\n    \n    void readPetMoves() {\n        // Update pet positions from judge input\n        vector<Position> newPetPos = petPos;\n        \n        for (int i = 0; i < N; i++) {\n            string move;\n            cin >> move;\n            if (move != \".\") {\n                int x = petPos[i].x, y = petPos[i].y;\n                for (char c : move) {\n                    int nx = x, ny = y;\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    \n                    if (isValid(nx, ny) && isPassable(nx, ny)) {\n                        bool conflict = false;\n                        for (int j = 0; j < N; j++) {\n                            if (i != j && newPetPos[j].x == nx && newPetPos[j].y == ny) {\n                                conflict = true;\n                                break;\n                            }\n                        }\n                        for (int j = 0; j < M; j++) {\n                            if (humanPos[j].x == nx && humanPos[j].y == ny) {\n                                conflict = true;\n                                break;\n                            }\n                        }\n                        if (!conflict) {\n                            x = nx;\n                            y = ny;\n                        }\n                    }\n                }\n                newPetPos[i] = {x, y};\n            }\n        }\n        \n        petPos = newPetPos;\n    }\n    \n    string decideActions(int turn) {\n        string actions(M, '.');\n        const int dx[4] = {-1, 1, 0, 0};\n        const int dy[4] = {0, 0, -1, 1};\n        const char blockChars[4] = {'u', 'd', 'l', 'r'};\n        const char moveChars[4] = {'U', 'D', 'L', 'R'};\n        \n        vector<Position> plannedMoves(M, {-1, -1});\n        vector<Position> plannedBlocks(M, {-1, -1});\n        \n        // CRITICAL: Stop blocking after certain turn to avoid late-game errors\n        bool allowBlocking = (turn < STOP_BLOCKING_TURN);\n        \n        if (allowBlocking) {\n            // First pass: evaluate blocking opportunities\n            vector<pair<int, int>> humanScores(M);\n            for (int i = 0; i < M; i++) {\n                int x = humanPos[i].x;\n                int y = humanPos[i].y;\n                int bestScore = -1;\n                int bestD = -1;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nx = x + dx[d];\n                    int ny = y + dy[d];\n                    \n                    if (canBlockSafe(i, nx, ny, plannedBlocks)) {\n                        int score = minPetDistance(nx, ny) * 10;\n                        \n                        const int wx[4] = {-1, 1, 0, 0};\n                        const int wy[4] = {0, 0, -1, 1};\n                        for (int w = 0; w < 4; w++) {\n                            int wx2 = nx + wx[w];\n                            int wy2 = ny + wy[w];\n                            if (isValid(wx2, wy2) && impassable[wx2-1][wy2-1]) {\n                                score += 20;\n                            }\n                        }\n                        \n                        if (nx == 1 || nx == GRID_SIZE || ny == 1 || ny == GRID_SIZE) {\n                            score += 15;\n                        }\n                        \n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestD = d;\n                        }\n                    }\n                }\n                \n                humanScores[i] = {bestScore, bestD};\n            }\n            \n            vector<int> order(M);\n            iota(order.begin(), order.end(), 0);\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return humanScores[a].first > humanScores[b].first;\n            });\n            \n            // Second pass: assign block actions\n            for (int idx : order) {\n                int i = idx;\n                int x = humanPos[i].x;\n                int y = humanPos[i].y;\n                int bestD = humanScores[i].second;\n                int bestScore = humanScores[i].first;\n                \n                if (bestD >= 0 && bestScore > 50) {  // Higher threshold\n                    int nx = x + dx[bestD];\n                    int ny = y + dy[bestD];\n                    \n                    if (canBlockSafe(i, nx, ny, plannedBlocks)) {\n                        actions[i] = blockChars[bestD];\n                        plannedBlocks[i] = {nx, ny};\n                        impassable[nx-1][ny-1] = true;\n                        continue;\n                    }\n                }\n            }\n        }\n        \n        // Movement phase (always allowed)\n        for (int i = 0; i < M; i++) {\n            if (actions[i] != '.') continue;  // Already has an action\n            \n            int x = humanPos[i].x;\n            int y = humanPos[i].y;\n            \n            int bestMoveD = -1;\n            int bestMoveScore = -1;\n            \n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                \n                if (canMove(i, nx, ny, plannedMoves, plannedBlocks)) {\n                    int score = minPetDistance(nx, ny) * 5;\n                    \n                    int blockOpts = 0;\n                    if (allowBlocking) {\n                        for (int bd = 0; bd < 4; bd++) {\n                            int bx = nx + dx[bd];\n                            int by = ny + dy[bd];\n                            if (isValid(bx, by) && !impassable[bx-1][by-1] && \n                                !hasPetAt(bx, by) && !isNearPet(bx, by)) {\n                                blockOpts++;\n                            }\n                        }\n                    }\n                    score += blockOpts * 5;\n                    \n                    if (score > bestMoveScore) {\n                        bestMoveScore = score;\n                        bestMoveD = d;\n                    }\n                }\n            }\n            \n            if (bestMoveD >= 0 && bestMoveScore > 30) {\n                actions[i] = moveChars[bestMoveD];\n                plannedMoves[i] = {x + dx[bestMoveD], y + dy[bestMoveD]};\n            }\n        }\n        \n        // FINAL PARANOID VALIDATION\n        for (int i = 0; i < M; i++) {\n            if (actions[i] == 'u' || actions[i] == 'd' || \n                actions[i] == 'l' || actions[i] == 'r') {\n                int x = humanPos[i].x;\n                int y = humanPos[i].y;\n                int tx = x, ty = y;\n                \n                if (actions[i] == 'u') tx--;\n                else if (actions[i] == 'd') tx++;\n                else if (actions[i] == 'l') ty--;\n                else if (actions[i] == 'r') ty++;\n                \n                bool safe = true;\n                \n                if (!isValid(tx, ty)) safe = false;\n                if (impassable[tx-1][ty-1]) safe = false;\n                \n                // Multiple pet checks\n                if (hasPetAt(tx, ty)) safe = false;\n                if (hasPetAdjacent(tx, ty)) safe = false;\n                if (isNearPet(tx, ty)) safe = false;\n                \n                for (int pi = 0; pi < N && safe; pi++) {\n                    if (petPos[pi].x == tx && petPos[pi].y == ty) safe = false;\n                    int pdist = abs(petPos[pi].x - tx) + abs(petPos[pi].y - ty);\n                    if (pdist <= PET_SAFETY_MARGIN) safe = false;\n                }\n                \n                if (!safe) {\n                    actions[i] = '.';\n                    // Note: We already updated impassable, but this is ok\n                    // as it will be consistent for next turn\n                }\n            }\n        }\n        \n        // Update human positions for next turn\n        for (int i = 0; i < M; i++) {\n            if (actions[i] == 'U' || actions[i] == 'D' || \n                actions[i] == 'L' || actions[i] == 'R') {\n                if (plannedMoves[i].x != -1) {\n                    humanPos[i] = plannedMoves[i];\n                }\n            }\n        }\n        \n        return actions;\n    }\n    \n    void solve() {\n        readInput();\n        \n        for (int turn = 0; turn < MAX_TURNS; turn++) {\n            string actions = decideActions(turn);\n            cout << actions << endl;\n            cout.flush();\n            \n            if (turn < MAX_TURNS - 1) {\n                readPetMoves();\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}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <functional>\n#include <queue>\n\nusing namespace std;\n\nconst int GRID_SIZE = 20;\nconst int MAX_STEPS = 200;\n\nstruct Problem {\n    int si, sj, ti, tj;\n    double p;\n    vector<string> h;\n    vector<string> v;\n};\n\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dirChar[4] = {'U', 'D', 'L', 'R'};\nconst int oppositeDir[4] = {1, 0, 3, 2};\n\ninline bool canMove(const Problem& prob, int i, int j, int dir) {\n    int ni = i + di[dir];\n    int nj = j + dj[dir];\n    \n    if (ni < 0 || ni >= GRID_SIZE || nj < 0 || nj >= GRID_SIZE) return false;\n    \n    if (dir == 0) {\n        if (prob.v[ni][j] == '1') return false;\n    } else if (dir == 1) {\n        if (prob.v[i][j] == '1') return false;\n    } else if (dir == 2) {\n        if (prob.h[i][nj] == '1') return false;\n    } else {\n        if (prob.h[i][j] == '1') return false;\n    }\n    return true;\n}\n\nbool pathReachesTarget(const Problem& prob, const string& path) {\n    int i = prob.si, j = prob.sj;\n    \n    for (char c : path) {\n        if (i == prob.ti && j == prob.tj) return true;\n        \n        int dir;\n        if (c == 'U') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        \n        if (canMove(prob, i, j, dir)) {\n            i += di[dir];\n            j += dj[dir];\n        }\n    }\n    \n    return (i == prob.ti && j == prob.tj);\n}\n\ndouble evaluatePathDP(const Problem& prob, const string& path) {\n    int L = path.size();\n    \n    vector<vector<double>> prob_grid(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    prob_grid[prob.si][prob.sj] = 1.0;\n    \n    double expectedScore = 0.0;\n    double arrivedProb = 0.0;\n    \n    for (int t = 0; t < L; t++) {\n        int dir;\n        if (path[t] == 'U') dir = 0;\n        else if (path[t] == 'D') dir = 1;\n        else if (path[t] == 'L') dir = 2;\n        else dir = 3;\n        \n        vector<vector<double>> next_prob(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n        \n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (prob_grid[i][j] < 1e-12) continue;\n                \n                if (i == prob.ti && j == prob.tj) {\n                    next_prob[i][j] += prob_grid[i][j];\n                    continue;\n                }\n                \n                next_prob[i][j] += prob.p * prob_grid[i][j];\n                \n                if (canMove(prob, i, j, dir)) {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    next_prob[ni][nj] += (1.0 - prob.p) * prob_grid[i][j];\n                } else {\n                    next_prob[i][j] += (1.0 - prob.p) * prob_grid[i][j];\n                }\n            }\n        }\n        \n        double newProb = next_prob[prob.ti][prob.tj] - arrivedProb;\n        if (newProb > 0) {\n            expectedScore += newProb * (401.0 - (t + 1));\n        }\n        arrivedProb = next_prob[prob.ti][prob.tj];\n        \n        prob_grid = next_prob;\n    }\n    \n    return expectedScore;\n}\n\nstring bfsPath(const Problem& prob, const vector<int>& dirOrder = {0, 1, 2, 3}) {\n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n    vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    queue<pair<int, int>> q;\n    \n    q.push({prob.si, prob.sj});\n    visited[prob.si][prob.sj] = true;\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == prob.ti && cj == prob.tj) break;\n        \n        for (int dir : dirOrder) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {ci, cj};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (!visited[prob.ti][prob.tj]) return \"\";\n    \n    string path = \"\";\n    int ci = prob.ti, cj = prob.tj;\n    while (ci != prob.si || cj != prob.sj) {\n        int dir = parentDir[ci][cj];\n        path += dirChar[dir];\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    return path;\n}\n\nstring bfsPathWeighted(const Problem& prob) {\n    vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, 1e18));\n    vector<vector<pair<int, int>>> parent(GRID_SIZE, vector<pair<int, int>>(GRID_SIZE, {-1, -1}));\n    vector<vector<int>> parentDir(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    \n    using State = pair<double, pair<int, int>>;\n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[prob.si][prob.sj] = 0;\n    pq.push({0, {prob.si, prob.sj}});\n    \n    while (!pq.empty()) {\n        auto [d, pos] = pq.top();\n        auto [ci, cj] = pos;\n        pq.pop();\n        \n        if (d > dist[ci][cj]) continue;\n        if (ci == prob.ti && cj == prob.tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                double weight = 1.0 + 0.01 * (abs(ni - prob.ti) + abs(nj - prob.tj));\n                \n                if (dist[ci][cj] + weight < dist[ni][nj]) {\n                    dist[ni][nj] = dist[ci][cj] + weight;\n                    parent[ni][nj] = {ci, cj};\n                    parentDir[ni][nj] = dir;\n                    pq.push({dist[ni][nj], {ni, nj}});\n                }\n            }\n        }\n    }\n    \n    if (dist[prob.ti][prob.tj] > 1e17) return \"\";\n    \n    string path = \"\";\n    int ci = prob.ti, cj = prob.tj;\n    while (ci != prob.si || cj != prob.sj) {\n        int dir = parentDir[ci][cj];\n        path += dirChar[dir];\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    return path;\n}\n\nstring dpPath(const Problem& prob, int pathLen) {\n    vector<vector<double>> V_cur(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    vector<vector<double>> V_next(GRID_SIZE, vector<double>(GRID_SIZE, 0.0));\n    \n    for (int k = 1; k <= pathLen; k++) {\n        for (int i = 0; i < GRID_SIZE; i++) {\n            for (int j = 0; j < GRID_SIZE; j++) {\n                if (i == prob.ti && j == prob.tj) {\n                    V_next[i][j] = 401.0 - (pathLen - k);\n                    continue;\n                }\n                \n                double bestVal = 0.0;\n                for (int dir = 0; dir < 4; dir++) {\n                    double val = prob.p * V_cur[i][j];\n                    \n                    if (canMove(prob, i, j, dir)) {\n                        val += (1.0 - prob.p) * V_cur[i + di[dir]][j + dj[dir]];\n                    } else {\n                        val += (1.0 - prob.p) * V_cur[i][j];\n                    }\n                    \n                    if (val > bestVal) bestVal = val;\n                }\n                V_next[i][j] = bestVal;\n            }\n        }\n        swap(V_cur, V_next);\n    }\n    \n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    int arrivalStep = -1;\n    \n    for (int k = pathLen; k > 0; k--) {\n        if (ci == prob.ti && cj == prob.tj) {\n            arrivalStep = pathLen - k;\n        }\n        \n        if (k > 0 && (ci != prob.ti || cj != prob.tj)) {\n            int bestDir = 1;\n            double bestVal = -1e18;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                double val = prob.p * V_cur[ci][cj];\n                if (canMove(prob, ci, cj, dir)) {\n                    val += (1.0 - prob.p) * V_cur[ci + di[dir]][cj + dj[dir]];\n                } else {\n                    val += (1.0 - prob.p) * V_cur[ci][cj];\n                }\n                \n                if (val > bestVal) {\n                    bestVal = val;\n                    bestDir = dir;\n                }\n            }\n            \n            path += dirChar[bestDir];\n            if (canMove(prob, ci, cj, bestDir)) {\n                ci += di[bestDir];\n                cj += dj[bestDir];\n            }\n        } else {\n            // Already at target - add moves that keep us there\n            bool found = false;\n            for (int dir = 0; dir < 4; dir++) {\n                if (!canMove(prob, ci, cj, dir)) {\n                    path += dirChar[dir];\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                // All moves possible - prefer moves that cycle back\n                path += dirChar[0]; // U - will likely bounce around target\n            }\n        }\n    }\n    \n    return path;\n}\n\nstring explorePath(const Problem& prob, int maxLen, mt19937& rng) {\n    string path = \"\";\n    int ci = prob.si, cj = prob.sj;\n    vector<vector<int>> visitCount(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n    \n    while ((int)path.size() < maxLen && (ci != prob.ti || cj != prob.tj)) {\n        visitCount[ci][cj]++;\n        \n        vector<pair<int, int>> candidates;\n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(prob, ci, cj, dir)) {\n                int ni = ci + di[dir];\n                int nj = cj + dj[dir];\n                int dist = abs(ni - prob.ti) + abs(nj - prob.tj);\n                int visits = visitCount[ni][nj];\n                candidates.push_back({dir, dist * 10 + visits});\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        sort(candidates.begin(), candidates.end(), \n             [](const pair<int,int>& a, const pair<int,int>& b) {\n                 return a.second < b.second;\n             });\n        \n        uniform_real_distribution<double> dist(0.0, 1.0);\n        int idx = (dist(rng) < 0.7) ? 0 : min((int)candidates.size() - 1, 1 + (int)(dist(rng) * (candidates.size() - 1)));\n        int bestDir = candidates[idx].first;\n        \n        path += dirChar[bestDir];\n        ci += di[bestDir];\n        cj += dj[bestDir];\n    }\n    \n    // Pad at target\n    while ((int)path.size() < maxLen) {\n        bool found = false;\n        for (int dir = 0; dir < 4; dir++) {\n            if (!canMove(prob, ci, cj, dir)) {\n                path += dirChar[dir];\n                found = true;\n                break;\n            }\n        }\n        if (!found) path += dirChar[0];\n    }\n    \n    return path;\n}\n\n// Enhanced simulated annealing with multiple move types\nstring simulatedAnnealing(const Problem& prob, string path, int iterations, mt19937& rng) {\n    if (path.empty()) return path;\n    \n    double currentScore = evaluatePathDP(prob, path);\n    double bestScore = currentScore;\n    string bestPath = path;\n    \n    uniform_real_distribution<double> probDist(0.0, 1.0);\n    uniform_int_distribution<int> posDist(0, max(0, (int)path.size() - 1));\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    double temperature = prob.p > 0.35 ? 2000.0 : 1000.0;\n    double coolingRate = prob.p > 0.35 ? 0.97 : 0.95;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int moveType = iter % 4;\n        string candidate = path;\n        \n        if (moveType == 0) {\n            // Single move change\n            int pos = posDist(rng);\n            int newDir = dirDist(rng);\n            candidate[pos] = dirChar[newDir];\n        } else if (moveType == 1 && path.size() >= 2) {\n            // Swap two moves\n            uniform_int_distribution<int> posDist2(0, max(0, (int)path.size() - 2));\n            int pos1 = posDist2(rng);\n            int pos2 = pos1 + 1 + (rng() % max(1, (int)path.size() - pos1 - 1));\n            swap(candidate[pos1], candidate[pos2]);\n        } else if (moveType == 2 && path.size() < MAX_STEPS - 5) {\n            // Insert a move\n            uniform_int_distribution<int> insertPos(0, (int)path.size());\n            int newDir = dirDist(rng);\n            candidate.insert(candidate.begin() + insertPos(rng), dirChar[newDir]);\n        } else if (path.size() > 10) {\n            // Delete a move\n            uniform_int_distribution<int> delPos(0, (int)path.size() - 1);\n            candidate.erase(candidate.begin() + delPos(rng));\n        }\n        \n        if (pathReachesTarget(prob, candidate) && (int)candidate.size() <= MAX_STEPS) {\n            double newScore = evaluatePathDP(prob, candidate);\n            double delta = newScore - currentScore;\n            \n            if (delta > 0 || probDist(rng) < exp(delta / temperature)) {\n                path = candidate;\n                currentScore = newScore;\n                \n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    bestPath = candidate;\n                }\n            }\n        }\n        \n        temperature *= coolingRate;\n    }\n    \n    return bestPath;\n}\n\nstring optimizeForP(const Problem& prob, const string& basePath, mt19937& rng) {\n    if (basePath.empty()) return basePath;\n    \n    string path = basePath;\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    // Find where we reach target\n    int ci = prob.si, cj = prob.sj;\n    int arrivalIdx = -1;\n    for (int i = 0; i < (int)path.size(); i++) {\n        if (ci == prob.ti && cj == prob.tj) {\n            arrivalIdx = i;\n            break;\n        }\n        int dir = (path[i] == 'U' ? 0 : path[i] == 'D' ? 1 : path[i] == 'L' ? 2 : 3);\n        if (canMove(prob, ci, cj, dir)) {\n            ci += di[dir];\n            cj += dj[dir];\n        }\n    }\n    \n    // High p: add redundancy before arrival\n    if (prob.p > 0.35 && arrivalIdx > 0) {\n        for (int i = arrivalIdx - 1; i > 0 && (int)path.size() < MAX_STEPS - 10; i--) {\n            if (dist(rng) < 0.25) {\n                path.insert(path.begin() + i, path[i]);\n            }\n        }\n    }\n    \n    // Low p: trim excess after arrival\n    if (prob.p < 0.2 && arrivalIdx > 0 && (int)path.size() > arrivalIdx + 30) {\n        path = path.substr(0, arrivalIdx + 20);\n    }\n    \n    return path;\n}\n\nstring robustFallback(const Problem& prob) {\n    vector<vector<int>> orderings = {\n        {1, 3, 0, 2}, {3, 1, 2, 0}, {1, 3, 2, 0},\n        {3, 1, 0, 2}, {0, 1, 2, 3}, {1, 0, 3, 2},\n        {3, 0, 1, 2}, {1, 2, 3, 0}\n    };\n    \n    for (const auto& order : orderings) {\n        string path = bfsPath(prob, order);\n        if (!path.empty() && pathReachesTarget(prob, path)) {\n            return path;\n        }\n    }\n    \n    return \"\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    Problem prob;\n    cin >> prob.si >> prob.sj >> prob.ti >> prob.tj >> prob.p;\n    \n    prob.h.resize(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; i++) cin >> prob.h[i];\n    \n    prob.v.resize(GRID_SIZE - 1);\n    for (int i = 0; i < GRID_SIZE - 1; i++) cin >> prob.v[i];\n    \n    string bestPath = \"\";\n    double bestScore = 0.0;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto startTime = chrono::steady_clock::now();\n    \n    // Strategy 1: BFS with multiple orderings and padding\n    vector<vector<int>> bfsOrders = {\n        {1, 3, 0, 2}, {3, 1, 0, 2}, {1, 3, 2, 0},\n        {3, 1, 2, 0}, {0, 1, 2, 3}, {1, 0, 3, 2},\n        {1, 3, 0, 2}, {3, 0, 1, 2}\n    };\n    \n    for (const auto& order : bfsOrders) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - startTime).count() > 1300) break;\n        \n        string bfs = bfsPath(prob, order);\n        if (!bfs.empty() && pathReachesTarget(prob, bfs)) {\n            for (int totalLen = (int)bfs.size(); totalLen <= min(MAX_STEPS, (int)bfs.size() + 50); totalLen += 5) {\n                string padded = bfs;\n                int ci = prob.si, cj = prob.sj;\n                int arrivalIdx = -1;\n                for (int i = 0; i < (int)bfs.size(); i++) {\n                    int dir = (bfs[i] == 'U' ? 0 : bfs[i] == 'D' ? 1 : bfs[i] == 'L' ? 2 : 3);\n                    if (canMove(prob, ci, cj, dir)) {\n                        ci += di[dir];\n                        cj += dj[dir];\n                    }\n                    if (ci == prob.ti && cj == prob.tj) {\n                        arrivalIdx = i + 1;\n                        break;\n                    }\n                }\n                while ((int)padded.size() < totalLen) {\n                    if (ci == prob.ti && cj == prob.tj) {\n                        bool found = false;\n                        for (int dir = 0; dir < 4; dir++) {\n                            if (!canMove(prob, ci, cj, dir)) {\n                                padded += dirChar[dir];\n                                found = true;\n                                break;\n                            }\n                        }\n                        if (!found) padded += dirChar[0];\n                    } else {\n                        padded += 'R';\n                    }\n                }\n                \n                if ((int)padded.size() <= MAX_STEPS) {\n                    double score = evaluatePathDP(prob, padded);\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestPath = padded;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Strategy 2: Weighted BFS\n    string weighted = bfsPathWeighted(prob);\n    if (!weighted.empty() && pathReachesTarget(prob, weighted)) {\n        double score = evaluatePathDP(prob, weighted);\n        if (score > bestScore) {\n            bestScore = score;\n            bestPath = weighted;\n        }\n    }\n    \n    // Strategy 3: DP-based paths\n    for (int pathLen = 30; pathLen <= 180; pathLen += 5) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - startTime).count() > 1500) break;\n        \n        string path = dpPath(prob, pathLen);\n        if (pathReachesTarget(prob, path) && (int)path.size() <= MAX_STEPS) {\n            double score = evaluatePathDP(prob, path);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = path;\n            }\n        }\n    }\n    \n    // Strategy 4: More exploration with different seeds\n    for (int i = 0; i < 15; i++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - startTime).count() > 1700) break;\n        \n        string path = explorePath(prob, MAX_STEPS, rng);\n        if (pathReachesTarget(prob, path)) {\n            double score = evaluatePathDP(prob, path);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = path;\n            }\n        }\n    }\n    \n    // Strategy 5: Multiple simulated annealing runs from different starting points\n    if (!bestPath.empty()) {\n        vector<string> startingPaths;\n        startingPaths.push_back(bestPath);\n        \n        string bfs = bfsPath(prob);\n        if (!bfs.empty() && pathReachesTarget(prob, bfs)) startingPaths.push_back(bfs);\n        if (!weighted.empty() && pathReachesTarget(prob, weighted)) startingPaths.push_back(weighted);\n        \n        int saIterations = prob.p > 0.35 ? 250 : 180;\n        \n        for (const auto& startPath : startingPaths) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - startTime).count() > 1900) break;\n            \n            string improved = simulatedAnnealing(prob, startPath, saIterations, rng);\n            double score = evaluatePathDP(prob, improved);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = improved;\n            }\n        }\n    }\n    \n    // Strategy 6: P-aware optimization\n    if (!bestPath.empty()) {\n        string pOptimized = optimizeForP(prob, bestPath, rng);\n        if (pathReachesTarget(prob, pOptimized)) {\n            double score = evaluatePathDP(prob, pOptimized);\n            if (score > bestScore) {\n                bestScore = score;\n                bestPath = pOptimized;\n            }\n        }\n    }\n    \n    // Strategy 7: Robust fallback\n    if (bestPath.empty() || !pathReachesTarget(prob, bestPath)) {\n        string fallback = robustFallback(prob);\n        if (!fallback.empty() && pathReachesTarget(prob, fallback)) {\n            double score = evaluatePathDP(prob, fallback);\n            if (score > bestScore || bestPath.empty()) {\n                bestScore = score;\n                bestPath = fallback;\n            }\n        }\n    }\n    \n    // Final validation\n    if (bestPath.empty() || !pathReachesTarget(prob, bestPath)) {\n        bestPath = robustFallback(prob);\n    }\n    \n    // Ensure valid output\n    if ((int)bestPath.size() > MAX_STEPS) {\n        bestPath = bestPath.substr(0, MAX_STEPS);\n    }\n    if (bestPath.empty()) {\n        bestPath = \"R\";\n    }\n    \n    cout << bestPath << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entering_direction] = exiting_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0: curve\n    {3, -1, -1, 0},  // 1: curve\n    {-1, -1, 3, 2},  // 2: curve\n    {-1, 2, 1, -1},  // 3: curve\n    {1, 0, 3, 2},    // 4: double curve\n    {3, 2, 1, 0},    // 5: double curve\n    {2, -1, 0, -1},  // 6: straight\n    {-1, 3, -1, 1},  // 7: straight\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint grid[N][N];\nint rot[N][N];\n\ninline int rotate_tile(int t, int r) {\n    if (t <= 3) return (t + r) % 4;\n    else if (t <= 5) return 4 + ((t - 4 + r) % 2);\n    else return 6 + ((t - 6 + r) % 2);\n}\n\ninline int get_tile(int i, int j) {\n    return rotate_tile(grid[i][j], rot[i][j]);\n}\n\n// Fast loop tracing with step limit\nint trace_loop(int si, int sj, int sd, int max_steps = 500) {\n    int i = si, j = sj, d = sd;\n    for (int len = 1; len <= max_steps; len++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 == -1) return 0;\n        i += di[d2];\n        j += dj[d2];\n        d = (d2 + 2) % 4;\n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        if (i == si && j == sj && d == sd) return len;\n    }\n    return 0;\n}\n\n// Sample-based loop detection (faster than full scan)\npair<long long, long long> sample_loops(mt19937& rng, int samples = 200) {\n    vector<int> loops;\n    \n    for (int s = 0; s < samples; s++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        int d = rng() % 4;\n        \n        int len = trace_loop(i, j, d, 600);\n        if (len > 1) {\n            loops.push_back(len);\n        }\n    }\n    \n    // Also check strategic points (edges, corners)\n    for (int i = 0; i < N; i += 5) {\n        for (int j = 0; j < N; j += 5) {\n            for (int d = 0; d < 4; d++) {\n                int len = trace_loop(i, j, d, 600);\n                if (len > 1) loops.push_back(len);\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    // Get unique top 2\n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Full scan for final evaluation\npair<long long, long long> full_scan_loops() {\n    vector<int> loops;\n    static bool vis[N][N][4];\n    memset(vis, 0, sizeof(vis));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                if (vis[i][j][d]) continue;\n                \n                vector<tuple<int,int,int>> path;\n                int ci = i, cj = j, cd = d;\n                \n                while (ci >= 0 && ci < N && cj >= 0 && cj < N && !vis[ci][cj][cd]) {\n                    vis[ci][cj][cd] = true;\n                    path.push_back({ci, cj, cd});\n                    \n                    int t = get_tile(ci, cj);\n                    int d2 = to[t][cd];\n                    if (d2 == -1) break;\n                    \n                    ci += di[d2];\n                    cj += dj[d2];\n                    cd = (d2 + 2) % 4;\n                }\n                \n                if (ci >= 0 && ci < N && cj >= 0 && cj < N) {\n                    for (int k = 0; k < (int)path.size(); k++) {\n                        if (get<0>(path[k]) == ci && \n                            get<1>(path[k]) == cj && \n                            get<2>(path[k]) == cd) {\n                            int loop_len = path.size() - k;\n                            if (loop_len > 1) {\n                                loops.push_back(loop_len);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() < 2) return {0, 0};\n    sort(loops.rbegin(), loops.rend());\n    \n    vector<int> uniq;\n    for (int l : loops) {\n        if (uniq.empty() || l != uniq.back()) {\n            uniq.push_back(l);\n        }\n        if (uniq.size() >= 2) break;\n    }\n    \n    if (uniq.size() < 2) return {0, 0};\n    return {(long long)uniq[0], (long long)uniq[1]};\n}\n\n// Evaluate connectivity score for a tile (heuristic)\nint connectivity_score(int i, int j, int r) {\n    int score = 0;\n    int old_rot = rot[i][j];\n    rot[i][j] = r;\n    \n    // Check all 4 directions\n    for (int d = 0; d < 4; d++) {\n        int t = get_tile(i, j);\n        int d2 = to[t][d];\n        if (d2 != -1) {\n            int ni = i + di[d2];\n            int nj = j + dj[d2];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nt = get_tile(ni, nj);\n                int back_d = (d2 + 2) % 4;\n                if (to[nt][back_d] != -1) {\n                    score += 10;\n                }\n            }\n        }\n    }\n    \n    rot[i][j] = old_rot;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Multiple restarts with different seeds\n    long long global_best = 0;\n    int best_rot[N][N];\n    memset(best_rot, 0, sizeof(best_rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    int restart = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Leave 150ms for final output\n        if (elapsed >= 1850) break;\n        \n        // Initialize rotations\n        memset(rot, 0, sizeof(rot));\n        \n        // Smart initialization: try to create connections\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int best_r = 0;\n                int best_score = -1;\n                for (int r = 0; r < 4; r++) {\n                    int score = connectivity_score(i, j, r);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n        \n        // Add some randomness to initial configuration\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (rng() % 3 == 0) {\n                    rot[i][j] = rng() % 4;\n                }\n            }\n        }\n        \n        // Get initial score\n        auto [l1, l2] = sample_loops(rng, 100);\n        long long current_score = l1 * l2;\n        long long local_best = current_score;\n        \n        // Simulated annealing with adaptive temperature\n        double temp = 500.0;\n        int iterations = 0;\n        int no_improve = 0;\n        \n        while (elapsed < 1850) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1850) break;\n            \n            // Adaptive temperature based on time remaining\n            double time_ratio = (1850.0 - elapsed) / 1850.0;\n            temp = 500.0 * pow(time_ratio, 2.0) + 1.0;\n            \n            // Number of tiles to change (increases with temperature)\n            int num_changes = 1 + (int)(3.0 * temp / 500.0);\n            num_changes = min(num_changes, 5);\n            \n            vector<pair<int,int>> changes;\n            vector<int> old_rots;\n            \n            for (int c = 0; c < num_changes; c++) {\n                int i = rng() % N;\n                int j = rng() % N;\n                changes.push_back({i, j});\n                old_rots.push_back(rot[i][j]);\n                rot[i][j] = (old_rots.back() + 1 + rng() % 3) % 4;\n            }\n            \n            auto [nl1, nl2] = sample_loops(rng, 80);\n            long long new_score = nl1 * nl2;\n            \n            bool accept = false;\n            if (new_score >= current_score) {\n                accept = true;\n                if (new_score > local_best) {\n                    local_best = new_score;\n                    no_improve = 0;\n                    memcpy(best_rot, rot, sizeof(rot));\n                }\n            } else if (temp > 0.5) {\n                double prob = exp((double)(new_score - current_score) / temp);\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (!accept) {\n                for (int c = 0; c < num_changes; c++) {\n                    rot[changes[c].first][changes[c].second] = old_rots[c];\n                }\n            } else {\n                current_score = new_score;\n            }\n            \n            iterations++;\n            no_improve++;\n            \n            // Restart if stuck\n            if (no_improve > 5000 && restart < 3) {\n                break;\n            }\n        }\n        \n        if (local_best > global_best) {\n            global_best = local_best;\n        }\n        \n        restart++;\n    }\n    \n    // Restore best configuration\n    memcpy(rot, best_rot, sizeof(rot));\n    \n    // Final full evaluation\n    auto [fl1, fl2] = full_scan_loops();\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << rot[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int LEFT = 1, UP = 2, RIGHT = 4, DOWN = 8;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dirs[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\nint N;\nlong long T;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct State {\n    vector<vector<int>> board;\n    int emptyR, emptyC;\n    string ops;\n};\n\ninline bool connects(int r1, int c1, int r2, int c2, const vector<vector<int>>& b) {\n    if (b[r1][c1] == 0 || b[r2][c2] == 0) return false;\n    if (r2 == r1 + 1) return (b[r1][c1] & DOWN) && (b[r2][c2] & UP);\n    if (r2 == r1 - 1) return (b[r1][c1] & UP) && (b[r2][c2] & DOWN);\n    if (c2 == c1 + 1) return (b[r1][c1] & RIGHT) && (b[r2][c2] & LEFT);\n    if (c2 == c1 - 1) return (b[r1][c1] & LEFT) && (b[r2][c2] & RIGHT);\n    return false;\n}\n\nint computeMaxTree(const vector<vector<int>>& b) {\n    int n = b.size();\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    int maxTree = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (b[i][j] != 0 && !visited[i][j]) {\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                while (!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    size++;\n                    for (int d = 0; d < 4; d++) {\n                        int nr = r + dr[d], nc = c + dc[d];\n                        if (nr >= 0 && nr < n && nc >= 0 && nc < n &&\n                            b[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc, b)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                maxTree = max(maxTree, size);\n            }\n        }\n    }\n    return maxTree;\n}\n\nint countEdges(const vector<vector<int>>& b) {\n    int n = b.size();\n    int count = 0;\n    for (int i = 0; i < n - 1; i++)\n        for (int j = 0; j < n; j++)\n            if (connects(i, j, i + 1, j, b)) count++;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n - 1; j++)\n            if (connects(i, j, i, j + 1, b)) count++;\n    return count;\n}\n\nint numComponents(const vector<vector<int>>& b) {\n    int n = b.size();\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (b[i][j] != 0 && !visited[i][j]) {\n                count++;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                while (!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    for (int d = 0; d < 4; d++) {\n                        int nr = r + dr[d], nc = c + dc[d];\n                        if (nr >= 0 && nr < n && nc >= 0 && nc < n &&\n                            b[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc, b)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return count;\n}\n\ndouble evaluate(const vector<vector<int>>& b) {\n    int treeSize = computeMaxTree(b);\n    int edges = countEdges(b);\n    int comps = numComponents(b);\n    \n    double score = treeSize * 100.0;\n    score += edges * 40.0;\n    score -= comps * 200.0;\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<int> compSizes;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] != 0 && !visited[i][j]) {\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                while (!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    size++;\n                    for (int d = 0; d < 4; d++) {\n                        int nr = r + dr[d], nc = c + dc[d];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                            b[nr][nc] != 0 && !visited[nr][nc] &&\n                            connects(r, c, nr, nc, b)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                compSizes.push_back(size);\n            }\n        }\n    }\n    for (int s : compSizes) score += (double)s * s * 1.0;\n    \n    if (treeSize == N * N - 1) {\n        score += 1000000.0 - edges * 1.0;\n    }\n    \n    return score;\n}\n\nbool executeMove(State& s, int dir) {\n    int nr = s.emptyR + dr[dir];\n    int nc = s.emptyC + dc[dir];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n    if (s.board[nr][nc] == 0) return false;\n    if (s.ops.size() >= (size_t)T) return false;\n    \n    s.board[s.emptyR][s.emptyC] = s.board[nr][nc];\n    s.board[nr][nc] = 0;\n    s.emptyR = nr;\n    s.emptyC = nc;\n    s.ops += dirs[dir];\n    return true;\n}\n\nvector<int> getValidMoves(const State& s, int lastMove = -1) {\n    vector<int> moves;\n    for (int d = 0; d < 4; d++) {\n        if (lastMove >= 0 && d == opp[lastMove]) continue;\n        int nr = s.emptyR + dr[d];\n        int nc = s.emptyC + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N && s.board[nr][nc] != 0) {\n            moves.push_back(d);\n        }\n    }\n    return moves;\n}\n\nstruct TabuState {\n    vector<vector<int>> board;\n    int emptyR, emptyC;\n    \n    bool operator==(const TabuState& other) const {\n        if (emptyR != other.emptyR || emptyC != other.emptyC) return false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (board[i][j] != other.board[i][j]) return false;\n        return true;\n    }\n};\n\n// Enhanced SA with hard case detection\nState searchSA(const State& initial, long long seed, int timeBudget, int strategy, bool isHardCase) {\n    mt19937 localRng(seed);\n    State s = initial;\n    \n    State bestState = s;\n    int bestTree = computeMaxTree(s.board);\n    double bestScore = evaluate(s.board);\n    int bestComps = numComponents(s.board);\n    \n    deque<TabuState> tabuList;\n    const int TABU_SIZE = 200;\n    \n    // Different strategies use different temperatures\n    double baseTemp = (strategy == 0) ? 1500.0 : (strategy == 1) ? 800.0 : \n                      (strategy == 2) ? 1000.0 : 600.0;\n    if (isHardCase) baseTemp *= 1.5;  // Higher temp for hard cases\n    \n    double temperature = baseTemp;\n    int lastMove = -1;\n    int noImprovement = 0;\n    auto searchStart = chrono::steady_clock::now();\n    \n    // Track progress for hard case detection\n    vector<int> treeSizeAt(N * N + 1, -1);\n    treeSizeAt[bestTree] = 0;\n    \n    while (s.ops.size() < (size_t)T) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - searchStart).count();\n        if (elapsed > timeBudget - 30) break;\n        if (bestTree == N * N - 1) break;\n        \n        // Hard case detection: if no tree improvement for too long\n        if (bestTree > 1 && bestTree < N * N - 1) {\n            int timeSinceLastTree = elapsed - treeSizeAt[bestTree];\n            if (timeSinceLastTree > timeBudget / 4) {\n                temperature = min(2000.0, temperature * 2.0);  // Heat up\n            }\n        }\n        \n        vector<int> moves = getValidMoves(s, lastMove);\n        if (moves.empty()) moves = getValidMoves(s, -1);\n        if (moves.empty()) break;\n        \n        // 2-ply lookahead evaluation\n        vector<pair<double, int>> scores;\n        int currentComps = numComponents(s.board);\n        \n        for (int d : moves) {\n            State temp = s;\n            if (executeMove(temp, d)) {\n                TabuState ts{temp.board, temp.emptyR, temp.emptyC};\n                bool isTabu = false;\n                for (const auto& tabu : tabuList) {\n                    if (tabu == ts) { isTabu = true; break; }\n                }\n                \n                double score = evaluate(temp.board);\n                int newComps = numComponents(temp.board);\n                \n                if (newComps < currentComps) {\n                    score += (currentComps - newComps) * 1200.0;\n                }\n                \n                // 2-ply lookahead on top candidates\n                if (scores.size() < 5) {\n                    vector<int> nextMoves = getValidMoves(temp, d);\n                    if (!nextMoves.empty()) {\n                        double bestNextScore = score;\n                        for (int nd : nextMoves) {\n                            State temp2 = temp;\n                            if (executeMove(temp2, nd)) {\n                                bestNextScore = max(bestNextScore, evaluate(temp2.board));\n                            }\n                        }\n                        score = (score * 0.6 + bestNextScore * 0.4);\n                    }\n                }\n                \n                if (isTabu) score -= 100.0;\n                scores.push_back({score, d});\n            }\n        }\n        \n        if (scores.empty()) break;\n        sort(scores.begin(), scores.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        \n        // SA selection\n        int selected = scores[0].second;\n        int numConsider = min((int)scores.size(), 10 + strategy * 2);\n        \n        for (int i = 0; i < numConsider; i++) {\n            double delta = scores[i].first - bestScore;\n            if (delta >= 0) {\n                selected = scores[i].second;\n                break;\n            } else {\n                double prob = exp(delta / temperature);\n                if (uniform_real_distribution<double>(0,1)(localRng) < prob) {\n                    selected = scores[i].second;\n                    break;\n                }\n            }\n        }\n        \n        executeMove(s, selected);\n        lastMove = selected;\n        \n        TabuState ts{s.board, s.emptyR, s.emptyC};\n        tabuList.push_back(ts);\n        if ((int)tabuList.size() > TABU_SIZE) tabuList.pop_front();\n        \n        double newScore = evaluate(s.board);\n        int newTree = computeMaxTree(s.board);\n        int newComps = numComponents(s.board);\n        \n        if (newTree > bestTree) {\n            bestTree = newTree;\n            bestComps = newComps;\n            bestScore = newScore;\n            bestState = s;\n            noImprovement = 0;\n            treeSizeAt[bestTree] = chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - searchStart).count();\n            temperature = max(50.0, temperature * 0.99);\n        } else if (newTree == bestTree && newComps < bestComps) {\n            bestComps = newComps;\n            bestScore = newScore;\n            bestState = s;\n            noImprovement = 0;\n        } else if (newTree == bestTree && newComps == bestComps && newScore > bestScore) {\n            bestScore = newScore;\n            bestState = s;\n            noImprovement = 0;\n        } else {\n            noImprovement++;\n        }\n        \n        // More aggressive heating when stuck\n        if (noImprovement > 200) {\n            temperature = min(2000.0, temperature * 3.0);\n            noImprovement = 0;\n        }\n        \n        elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - searchStart).count();\n        double ratio = (double)elapsed / timeBudget;\n        temperature = max(1.0, baseTemp * (1.0 - ratio * 0.95));\n    }\n    \n    return bestState;\n}\n\n// Greedy with component focus\nState searchGreedy(const State& initial, long long seed, int timeBudget) {\n    mt19937 localRng(seed);\n    State s = initial;\n    \n    State bestState = s;\n    int bestTree = computeMaxTree(s.board);\n    int lastMove = -1;\n    auto searchStart = chrono::steady_clock::now();\n    \n    while (s.ops.size() < (size_t)T) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - searchStart).count();\n        if (elapsed > timeBudget - 30) break;\n        if (bestTree == N * N - 1) break;\n        \n        vector<pair<int, int>> moves;\n        for (int d = 0; d < 4; d++) {\n            if (lastMove >= 0 && d == opp[lastMove]) continue;\n            State temp = s;\n            if (executeMove(temp, d)) {\n                int oldTree = computeMaxTree(s.board);\n                int newTree = computeMaxTree(temp.board);\n                int oldComps = numComponents(s.board);\n                int newComps = numComponents(temp.board);\n                int oldEdges = countEdges(s.board);\n                int newEdges = countEdges(temp.board);\n                \n                int priority = (newTree - oldTree) * 20000 + \n                              (oldComps - newComps) * 5000 + \n                              (newEdges - oldEdges) * 200;\n                moves.push_back({priority, d});\n            }\n        }\n        \n        if (moves.empty()) break;\n        sort(moves.begin(), moves.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        \n        int idx = 0;\n        if (moves.size() > 3 && uniform_real_distribution<double>(0,1)(localRng) < 0.12) {\n            idx = uniform_int_distribution<int>(1, min((int)moves.size()-1, 4))(localRng);\n        }\n        \n        executeMove(s, moves[idx].second);\n        lastMove = moves[idx].second;\n        \n        int newTree = computeMaxTree(s.board);\n        if (newTree > bestTree) {\n            bestTree = newTree;\n            bestState = s;\n        }\n    }\n    \n    return bestState;\n}\n\n// Aggressive random walk\nState searchRandom(const State& initial, long long seed, int timeBudget) {\n    mt19937 localRng(seed);\n    State bestState = initial;\n    int bestTree = computeMaxTree(initial.board);\n    \n    auto searchStart = chrono::steady_clock::now();\n    \n    for (int restart = 0; restart < 30; restart++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - searchStart).count();\n        if (elapsed > timeBudget - 30) break;\n        if (bestTree == N * N - 1) break;\n        \n        State s = initial;\n        int lastMove = -1;\n        \n        while (s.ops.size() < (size_t)T) {\n            elapsed = chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - searchStart).count();\n            if (elapsed > timeBudget - 30) break;\n            \n            vector<int> moves = getValidMoves(s, lastMove);\n            if (moves.empty()) moves = getValidMoves(s, -1);\n            if (moves.empty()) break;\n            \n            int selected = moves[uniform_int_distribution<int>(0, moves.size()-1)(localRng)];\n            executeMove(s, selected);\n            lastMove = selected;\n            \n            int tree = computeMaxTree(s.board);\n            if (tree > bestTree) {\n                bestTree = tree;\n                bestState = s;\n            }\n            if (tree == N * N - 1) break;\n        }\n        \n        if (bestTree == N * N - 1) break;\n    }\n    \n    return bestState;\n}\n\n// Aggressive path optimization\nstring optimizePath(const State& initial, string ops) {\n    if (ops.size() < 50) return ops;\n    \n    bool changed = true;\n    int maxIter = 100;\n    \n    while (changed && maxIter > 0 && ops.size() > 20) {\n        changed = false;\n        maxIter--;\n        string newOps = \"\";\n        \n        for (size_t i = 0; i < ops.size(); i++) {\n            if (i + 1 < ops.size()) {\n                char c1 = ops[i], c2 = ops[i+1];\n                bool isRedundant = ((c1 == 'U' && c2 == 'D') || (c1 == 'D' && c2 == 'U') ||\n                                   (c1 == 'L' && c2 == 'R') || (c1 == 'R' && c2 == 'L'));\n                if (isRedundant) {\n                    i++;\n                    changed = true;\n                    continue;\n                }\n            }\n            newOps += ops[i];\n        }\n        \n        if (changed && newOps.size() < ops.size()) {\n            State verify = initial;\n            bool valid = true;\n            for (char c : newOps) {\n                int d;\n                if (c == 'U') d = 0; else if (c == 'D') d = 1;\n                else if (c == 'L') d = 2; else d = 3;\n                if (!executeMove(verify, d)) { valid = false; break; }\n            }\n            \n            if (valid && computeMaxTree(verify.board) == N * N - 1) {\n                ops = newOps;\n            } else {\n                break;\n            }\n        }\n    }\n    \n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> T;\n    \n    State initialState;\n    initialState.board.resize(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') {\n                initialState.board[i][j] = c - '0';\n            } else {\n                initialState.board[i][j] = c - 'a' + 10;\n            }\n            if (initialState.board[i][j] == 0) {\n                initialState.emptyR = i;\n                initialState.emptyC = j;\n            }\n        }\n    }\n    initialState.ops = \"\";\n    \n    State globalBest = initialState;\n    int globalBestTree = computeMaxTree(initialState.board);\n    double globalBestScore = evaluate(initialState.board);\n    int globalBestComps = numComponents(initialState.board);\n    \n    vector<long long> seeds;\n    for (int i = 0; i < 35; i++) seeds.push_back(rng());\n    \n    int searchIdx = 0;\n    auto lastProgressCheck = startTime;\n    int lastProgressTree = globalBestTree;\n    \n    // Detect if this is a hard case (no progress in first 500ms)\n    bool isHardCase = false;\n    \n    // Phase 1: SA with different strategies\n    while (searchIdx < 18 && globalBestTree < N * N - 1) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        \n        // Check for hard case\n        if (elapsed > 500 && globalBestTree == lastProgressTree) {\n            isHardCase = true;\n        }\n        if (globalBestTree > lastProgressTree) {\n            lastProgressTree = globalBestTree;\n            lastProgressCheck = now;\n        }\n        \n        if (elapsed > 2800) break;\n        \n        int remainingTime = 2800 - elapsed;\n        int actualBudget = isHardCase ? min(200, remainingTime - 50) : min(140, remainingTime - 50);\n        if (actualBudget < 60) break;\n        \n        int strategy = searchIdx % 4;\n        State result = searchSA(initialState, seeds[searchIdx], actualBudget, strategy, isHardCase);\n        int tree = computeMaxTree(result.board);\n        int comps = numComponents(result.board);\n        double score = evaluate(result.board);\n        \n        if (tree > globalBestTree || \n            (tree == globalBestTree && comps < globalBestComps) ||\n            (tree == globalBestTree && comps == globalBestComps && score > globalBestScore)) {\n            globalBestTree = tree;\n            globalBestComps = comps;\n            globalBestScore = score;\n            globalBest = result;\n        }\n        searchIdx++;\n    }\n    \n    // Phase 2: Greedy\n    while (searchIdx < 26 && globalBestTree < N * N - 1) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        if (elapsed > 2800) break;\n        \n        int remainingTime = 2800 - elapsed;\n        int actualBudget = min(100, remainingTime - 50);\n        if (actualBudget < 60) break;\n        \n        State result = searchGreedy(initialState, seeds[searchIdx], actualBudget);\n        int tree = computeMaxTree(result.board);\n        int comps = numComponents(result.board);\n        double score = evaluate(result.board);\n        \n        if (tree > globalBestTree || \n            (tree == globalBestTree && comps < globalBestComps) ||\n            (tree == globalBestTree && comps == globalBestComps && score > globalBestScore)) {\n            globalBestTree = tree;\n            globalBestComps = comps;\n            globalBestScore = score;\n            globalBest = result;\n        }\n        searchIdx++;\n    }\n    \n    // Phase 3: Random\n    while (searchIdx < 35 && globalBestTree < N * N - 1) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        if (elapsed > 2800) break;\n        \n        int remainingTime = 2800 - elapsed;\n        int actualBudget = min(100, remainingTime - 50);\n        if (actualBudget < 60) break;\n        \n        State result = searchRandom(initialState, seeds[searchIdx], actualBudget);\n        int tree = computeMaxTree(result.board);\n        int comps = numComponents(result.board);\n        double score = evaluate(result.board);\n        \n        if (tree > globalBestTree || \n            (tree == globalBestTree && comps < globalBestComps) ||\n            (tree == globalBestTree && comps == globalBestComps && score > globalBestScore)) {\n            globalBestTree = tree;\n            globalBestComps = comps;\n            globalBestScore = score;\n            globalBest = result;\n        }\n        searchIdx++;\n    }\n    \n    // Phase 4: Optimize path if we have complete tree\n    if (globalBestTree == N * N - 1) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        \n        if (elapsed < 2900) {\n            string optimized = optimizePath(initialState, globalBest.ops);\n            if (optimized.size() < globalBest.ops.size()) {\n                State verify = initialState;\n                bool valid = true;\n                for (char c : optimized) {\n                    int d;\n                    if (c == 'U') d = 0; else if (c == 'D') d = 1;\n                    else if (c == 'L') d = 2; else d = 3;\n                    if (!executeMove(verify, d)) { valid = false; break; }\n                }\n                \n                if (valid && computeMaxTree(verify.board) == N * N - 1) {\n                    globalBest.ops = optimized;\n                }\n            }\n        }\n    }\n    \n    // Final validation\n    State verify = initialState;\n    bool allValid = true;\n    for (char c : globalBest.ops) {\n        int d;\n        if (c == 'U') d = 0; else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2; else d = 3;\n        if (!executeMove(verify, d)) {\n            allValid = false;\n            break;\n        }\n    }\n    \n    if (!allValid || globalBest.ops.size() > (size_t)T) {\n        cout << \"\" << endl;\n    } else {\n        cout << globalBest.ops << endl;\n    }\n    \n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <set>\n\nusing namespace std;\n\nstruct Strawberry {\n    long long x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n    \n    long long side(long long x, long long y) const {\n        return (qx - px) * (y - py) - (qy - py) * (x - px);\n    }\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> cuts;\nmt19937 rng(12345);\n\nbool lineHitsStrawberry(const Line& line) {\n    for (int i = 0; i < N; i++) {\n        if (line.side(strawberries[i].x, strawberries[i].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\nbool tryFindLine(long long px, long long py, long long qx, long long qy, Line& outLine) {\n    for (int dx = -5; dx <= 5; dx++) {\n        for (int dy = -5; dy <= 5; dy++) {\n            Line test = {px + dx, py + dy, qx + dx, qy + dy};\n            if (!lineHitsStrawberry(test)) {\n                outLine = test;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    int spacing = 150;  // Dense spacing for small regions\n    int margin = 9500;\n    \n    vector<Line> allCandidates;\n    \n    // Strategy 1: Dense vertical lines\n    for (int i = 0; i < 60; i++) {\n        long long x = -margin + i * spacing + (rng() % 60);\n        Line line;\n        if (tryFindLine(x, -15000, x, 15000, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Strategy 2: Dense horizontal lines\n    for (int i = 0; i < 60; i++) {\n        long long y = -margin + i * spacing + (rng() % 60);\n        Line line;\n        if (tryFindLine(-15000, y, 15000, y, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Strategy 3: Multiple diagonal angles\n    for (int angleIdx = 1; angleIdx <= 16; angleIdx++) {\n        double angle = angleIdx * 3.14159265359 / 17;\n        long long dx = (long long)(cos(angle) * 20000);\n        long long dy = (long long)(sin(angle) * 20000);\n        \n        for (int offset = 0; offset < 20; offset++) {\n            long long perp = offset * 500 - 5000 + (rng() % 80);\n            long long px = (long long)(perp * cos(angle + 3.14159265359/2));\n            long long py = (long long)(perp * sin(angle + 3.14159265359/2));\n            long long qx = px + dx;\n            long long qy = py + dy;\n            \n            Line line;\n            if (tryFindLine(px, py, qx, qy, line)) {\n                allCandidates.push_back(line);\n            }\n        }\n    }\n    \n    // Strategy 4: Random lines for additional coverage\n    for (int i = 0; i < 80; i++) {\n        double angle = rng() % 360 * 3.14159265359 / 180.0;\n        long long dx = (long long)(cos(angle) * 20000);\n        long long dy = (long long)(sin(angle) * 20000);\n        long long offset = (rng() % 20001) - 10000;\n        long long px = (long long)(offset * cos(angle + 3.14159265359/2));\n        long long py = (long long)(offset * sin(angle + 3.14159265359/2));\n        long long qx = px + dx;\n        long long qy = py + dy;\n        \n        Line line;\n        if (tryFindLine(px, py, qx, qy, line)) {\n            allCandidates.push_back(line);\n        }\n    }\n    \n    // Select cuts: prioritize axis-aligned for grid structure\n    cuts.clear();\n    \n    // First: vertical and horizontal (grid backbone) - take up to K/2\n    for (const auto& line : allCandidates) {\n        if ((int)cuts.size() >= K / 2) break;\n        long long dx = abs(line.qx - line.px);\n        long long dy = abs(line.qy - line.py);\n        if (dx < 1000 || dy < 1000) {\n            // Check not duplicate\n            bool dup = false;\n            for (const auto& c : cuts) {\n                if (abs(c.px - line.px) < 50 && abs(c.py - line.py) < 50) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) {\n                cuts.push_back(line);\n            }\n        }\n    }\n    \n    // Then: diagonals to fill remaining\n    for (const auto& line : allCandidates) {\n        if ((int)cuts.size() >= K) break;\n        long long dx = abs(line.qx - line.px);\n        long long dy = abs(line.qy - line.py);\n        if (dx >= 1000 && dy >= 1000) {\n            bool dup = false;\n            for (const auto& c : cuts) {\n                if (c.px == line.px && c.py == line.py && c.qx == line.qx && c.qy == line.qy) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) {\n                cuts.push_back(line);\n            }\n        }\n    }\n    \n    // Fill any remaining slots\n    for (const auto& line : allCandidates) {\n        if ((int)cuts.size() >= K) break;\n        bool dup = false;\n        for (const auto& c : cuts) {\n            if (c.px == line.px && c.py == line.py && c.qx == line.qx && c.qy == line.qy) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) {\n            cuts.push_back(line);\n        }\n    }\n    \n    // Final safety check\n    vector<Line> validCuts;\n    for (const auto& line : cuts) {\n        if (!lineHitsStrawberry(line)) {\n            validCuts.push_back(line);\n        }\n    }\n    cuts = validCuts;\n    \n    // Fallback if too few cuts\n    if (cuts.size() < 20) {\n        cuts.clear();\n        for (int i = 0; i < K && i < 50; i++) {\n            long long x = -9500 + i * 400;\n            for (int adj = 0; adj < 100; adj++) {\n                Line line = {x + adj, -15000, x + adj, 15000};\n                if (!lineHitsStrawberry(line)) {\n                    cuts.push_back(line);\n                    break;\n                }\n            }\n        }\n    }\n    \n    cout << cuts.size() << \"\\n\";\n    for (const auto& line : cuts) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Global variables\nint N, M;\nbool has_dot[65][65];\nbool used_edge[65][65][4];\nvector<int> dots_in_row[65];\nvector<int> dots_in_col[65];\n\nstruct Point {\n    int x, y;\n    long long w;\n    int valid_rect_count;\n};\n\nvector<Point> sorted_points;\nvector<array<int, 8>> result_moves;\n\nauto start_time = chrono::steady_clock::now();\nconst double TIME_LIMIT = 4.75;\n\nstruct Rectangle {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    vector<pair<int,int>> rect_pts;\n    int edge_count;\n    int area; // Approximate area for tie-breaking\n};\n\n// Mark a single unit edge\nvoid mark_unit_edge(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y2 == y1 + 1) {\n        used_edge[x1][y1][1] = true;\n    } else if (y1 == y2 && x2 == x1 + 1) {\n        used_edge[x1][y1][0] = true;\n    } else if (x2 == x1 + 1 && y2 == y1 + 1) {\n        used_edge[x1][y1][2] = true;\n    } else if (x2 == x1 - 1 && y2 == y1 + 1) {\n        used_edge[x2][y2][3] = true;\n    } else if (x1 == x2 && y1 == y2 + 1) {\n        used_edge[x2][y2][1] = true;\n    } else if (y1 == y2 && x1 == x2 + 1) {\n        used_edge[x2][y2][0] = true;\n    } else if (x1 == x2 + 1 && y1 == y2 + 1) {\n        used_edge[x2][y2][2] = true;\n    } else if (x1 == x2 - 1 && y1 == y2 + 1) {\n        used_edge[x1][y1][3] = true;\n    }\n}\n\n// Check if a single unit edge is used\nbool is_unit_edge_used(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y2 == y1 + 1) {\n        return used_edge[x1][y1][1];\n    } else if (y1 == y2 && x2 == x1 + 1) {\n        return used_edge[x1][y1][0];\n    } else if (x2 == x1 + 1 && y2 == y1 + 1) {\n        return used_edge[x1][y1][2];\n    } else if (x2 == x1 - 1 && y2 == y1 + 1) {\n        return used_edge[x2][y2][3];\n    } else if (x1 == x2 && y1 == y2 + 1) {\n        return used_edge[x2][y2][1];\n    } else if (y1 == y2 && x1 == x2 + 1) {\n        return used_edge[x2][y2][0];\n    } else if (x1 == x2 + 1 && y1 == y2 + 1) {\n        return used_edge[x2][y2][2];\n    } else if (x1 == x2 - 1 && y1 == y2 + 1) {\n        return used_edge[x1][y1][3];\n    }\n    return false;\n}\n\n// Mark all edges along a line segment\nvoid mark_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return;\n    \n    int sx = (dx == 0) ? 0 : (dx > 0 ? 1 : -1);\n    int sy = (dy == 0) ? 0 : (dy > 0 ? 1 : -1);\n    \n    int cx = x1, cy = y1;\n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        mark_unit_edge(cx, cy, nx, ny);\n        cx = nx;\n        cy = ny;\n    }\n}\n\n// Check if all edges along a line segment are unused\nbool check_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return true;\n    \n    int sx = (dx == 0) ? 0 : (dx > 0 ? 1 : -1);\n    int sy = (dy == 0) ? 0 : (dy > 0 ? 1 : -1);\n    \n    int cx = x1, cy = y1;\n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        if (is_unit_edge_used(cx, cy, nx, ny)) return false;\n        cx = nx;\n        cy = ny;\n    }\n    return true;\n}\n\n// Calculate approximate area of rectangle\nint calc_area(const vector<pair<int,int>>& pts) {\n    // For axis-aligned: width * height\n    // For 45-degree: diagonal1 * diagonal2 / 2\n    int min_x = pts[0].first, max_x = pts[0].first;\n    int min_y = pts[0].second, max_y = pts[0].second;\n    for (const auto& p : pts) {\n        min_x = min(min_x, p.first);\n        max_x = max(max_x, p.first);\n        min_y = min(min_y, p.second);\n        max_y = max(max_y, p.second);\n    }\n    return (max_x - min_x) * (max_y - min_y);\n}\n\n// Check perimeter constraints and count edges\nbool check_perimeter(const vector<pair<int,int>>& pts, const vector<pair<int,int>>& dots, int& edge_count) {\n    edge_count = 0;\n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        if (!check_segment(x1, y1, x2, y2)) return false;\n        edge_count += max(abs(x2 - x1), abs(y2 - y1));\n    }\n    \n    for (size_t i = 0; i < 4; ++i) {\n        int x1 = pts[i].first, y1 = pts[i].second;\n        int x2 = pts[(i + 1) % 4].first, y2 = pts[(i + 1) % 4].second;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0) ? 0 : (dx / abs(dx));\n        int sy = (dy == 0) ? 0 : (dy / abs(dy));\n        \n        for (int k = 1; k < steps; ++k) {\n            int cx = x1 + k * sx;\n            int cy = y1 + k * sy;\n            if (has_dot[cx][cy]) {\n                bool allowed = false;\n                for (const auto& d : dots) {\n                    if (d.first == cx && d.second == cy) {\n                        allowed = true;\n                        break;\n                    }\n                }\n                if (!allowed) return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Find all valid rectangles for a point\nvector<Rectangle> find_all_rectangles(int x, int y) {\n    vector<Rectangle> rectangles;\n    \n    // 1. Axis Aligned rectangle\n    for (int x2 : dots_in_row[y]) {\n        if (x2 == x) continue;\n        for (int y2 : dots_in_col[x]) {\n            if (y2 == y) continue;\n            if (has_dot[x2][y2]) {\n                vector<pair<int,int>> rect = {{x, y}, {x2, y}, {x2, y2}, {x, y2}};\n                vector<pair<int,int>> dots = {{x2, y}, {x2, y2}, {x, y2}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, x2, y, x2, y2, x, y2, rect, edge_count, calc_area(rect)});\n                }\n            }\n        }\n    }\n    \n    // 2. 45-degree - Vertical Diagonal\n    for (int yd : dots_in_col[x]) {\n        if (yd == y) continue;\n        int dy = yd - y;\n        if (abs(dy) % 2 != 0) continue;\n        int w = abs(dy) / 2;\n        int ym = y + dy / 2;\n        int xa = x - w;\n        int xb = x + w;\n        \n        if (xa >= 0 && xa < N && xb >= 0 && xb < N) {\n            if (has_dot[xa][ym] && has_dot[xb][ym]) {\n                vector<pair<int,int>> rect = {{x, y}, {xb, ym}, {x, yd}, {xa, ym}};\n                vector<pair<int,int>> dots = {{x, yd}, {xa, ym}, {xb, ym}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, xb, ym, x, yd, xa, ym, rect, edge_count, calc_area(rect)});\n                }\n            }\n        }\n    }\n    \n    // 3. 45-degree - Horizontal Diagonal\n    for (int xd : dots_in_row[y]) {\n        if (xd == x) continue;\n        int dx = xd - x;\n        if (abs(dx) % 2 != 0) continue;\n        int w = abs(dx) / 2;\n        int xm = x + dx / 2;\n        int ya = y - w;\n        int yb = y + w;\n        \n        if (ya >= 0 && ya < N && yb >= 0 && yb < N) {\n            if (has_dot[xm][ya] && has_dot[xm][yb]) {\n                vector<pair<int,int>> rect = {{x, y}, {xm, yb}, {xd, y}, {xm, ya}};\n                vector<pair<int,int>> dots = {{xd, y}, {xm, ya}, {xm, yb}};\n                int edge_count;\n                if (check_perimeter(rect, dots, edge_count)) {\n                    rectangles.push_back({x, y, xm, yb, xd, y, xm, ya, rect, edge_count, calc_area(rect)});\n                }\n            }\n        }\n    }\n    \n    return rectangles;\n}\n\n// Count valid rectangles for a point\nint count_valid_rectangles(int x, int y) {\n    return (int)find_all_rectangles(x, y).size();\n}\n\nvoid apply_rectangle(const Rectangle& rect) {\n    has_dot[rect.x1][rect.y1] = true;\n    dots_in_row[rect.y1].push_back(rect.x1);\n    dots_in_col[rect.x1].push_back(rect.y1);\n    \n    for (size_t i = 0; i < 4; ++i) {\n        mark_segment(rect.rect_pts[i].first, rect.rect_pts[i].second,\n                    rect.rect_pts[(i + 1) % 4].first, rect.rect_pts[(i + 1) % 4].second);\n    }\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    long long c = (N - 1) / 2;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        has_dot[x][y] = true;\n        dots_in_row[y].push_back(x);\n        dots_in_col[x].push_back(y);\n    }\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            sorted_points.push_back({x, y, w, 0});\n        }\n    }\n    \n    // Initial sort by weight\n    sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n        return a.w > b.w;\n    });\n    \n    // Multiple passes to fill points\n    bool any_change = true;\n    \n    while (any_change) {\n        any_change = false;\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        // Update valid rectangle counts\n        for (auto& p : sorted_points) {\n            if (!has_dot[p.x][p.y]) {\n                p.valid_rect_count = count_valid_rectangles(p.x, p.y);\n            } else {\n                p.valid_rect_count = -1;\n            }\n        }\n        \n        // Sort by: has valid rects, then by weight (higher first), then by constraint (fewer options first)\n        sort(sorted_points.begin(), sorted_points.end(), [](const Point& a, const Point& b) {\n            bool a_valid = (a.valid_rect_count > 0);\n            bool b_valid = (b.valid_rect_count > 0);\n            if (a_valid != b_valid) return a_valid > b_valid;\n            if (a.w != b.w) return a.w > b.w;\n            // Prefer more constrained points (fewer options)\n            return a.valid_rect_count < b.valid_rect_count;\n        });\n        \n        // Find best move - evaluate multiple candidates before selecting\n        Rectangle best_rect;\n        bool found = false;\n        int best_edge_count = 1000000;\n        long long best_weight = -1;\n        int best_constraint = 1000000;\n        int best_area = 1000000;\n        \n        // Look at top 150 candidates (increased from 100)\n        int max_candidates = min(150, (int)sorted_points.size());\n        for (int i = 0; i < max_candidates; ++i) {\n            const auto& p = sorted_points[i];\n            if (has_dot[p.x][p.y]) continue;\n            if (p.valid_rect_count <= 0) continue;\n            \n            auto rects = find_all_rectangles(p.x, p.y);\n            if (rects.empty()) continue;\n            \n            // Evaluate ALL rectangles for this point\n            for (const auto& rect : rects) {\n                bool better = false;\n                if (!found) {\n                    better = true;\n                } else if (p.w > best_weight + 100) {\n                    // Significantly higher weight wins\n                    better = true;\n                } else if (abs(p.w - best_weight) <= 100) {\n                    // Similar weight - prefer fewer edges FIRST\n                    if (rect.edge_count < best_edge_count) {\n                        better = true;\n                    } else if (rect.edge_count == best_edge_count) {\n                        // Same edges - prefer smaller area\n                        if (rect.area < best_area) {\n                            better = true;\n                        } else if (rect.area == best_area && p.valid_rect_count < best_constraint) {\n                            // Same area - prefer more constrained point\n                            better = true;\n                        }\n                    }\n                }\n                \n                if (better) {\n                    best_rect = rect;\n                    best_edge_count = rect.edge_count;\n                    best_weight = p.w;\n                    best_constraint = p.valid_rect_count;\n                    best_area = rect.area;\n                    found = true;\n                }\n            }\n        }\n        \n        if (found) {\n            result_moves.push_back({best_rect.x1, best_rect.y1, best_rect.x2, best_rect.y2, \n                                    best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4});\n            apply_rectangle(best_rect);\n            any_change = true;\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& m : result_moves) {\n        cout << m[0] << \" \" << m[1] << \" \" << m[2] << \" \" << m[3] << \" \" \n             << m[4] << \" \" << m[5] << \" \" << m[6] << \" \" << m[7] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 10;\n\nstruct Candy {\n    int flavor;\n    int row, col;\n};\n\nclass GameState {\npublic:\n    array<array<int, N>, N> grid;  // 0 = empty, 1-3 = flavor\n    vector<Candy> candies;\n    \n    GameState() {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = 0;\n    }\n    \n    GameState(const GameState& other) = default;\n    \n    void placeCandy(int row, int col, int flavor) {\n        grid[row][col] = flavor;\n        candies.push_back({flavor, row, col});\n    }\n    \n    vector<pair<int,int>> getEmptyCells() const {\n        vector<pair<int,int>> empty;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    empty.push_back({i, j});\n                }\n            }\n        }\n        return empty;\n    }\n    \n    GameState tilt(char dir) const {\n        GameState result = *this;\n        auto& g = result.grid;\n        \n        if (dir == 'F') {  // Forward (up)\n            for (int j = 0; j < N; j++) {\n                int writeRow = 0;\n                for (int i = 0; i < N; i++) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow++;\n                    }\n                }\n            }\n        } else if (dir == 'B') {  // Backward (down)\n            for (int j = 0; j < N; j++) {\n                int writeRow = N - 1;\n                for (int i = N - 1; i >= 0; i--) {\n                    if (g[i][j] != 0) {\n                        g[writeRow][j] = g[i][j];\n                        if (writeRow != i) g[i][j] = 0;\n                        writeRow--;\n                    }\n                }\n            }\n        } else if (dir == 'L') {  // Left\n            for (int i = 0; i < N; i++) {\n                int writeCol = 0;\n                for (int j = 0; j < N; j++) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol++;\n                    }\n                }\n            }\n        } else if (dir == 'R') {  // Right\n            for (int i = 0; i < N; i++) {\n                int writeCol = N - 1;\n                for (int j = N - 1; j >= 0; j--) {\n                    if (g[i][j] != 0) {\n                        g[i][writeCol] = g[i][j];\n                        if (writeCol != j) g[i][j] = 0;\n                        writeCol--;\n                    }\n                }\n            }\n        }\n        \n        // Update candy positions\n        result.candies.clear();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (g[i][j] != 0) {\n                    result.candies.push_back({g[i][j], i, j});\n                }\n            }\n        }\n        \n        return result;\n    }\n    \n    int countSameFlavorAdjacency() const {\n        int count = 0;\n        const int dr[] = {-1, 1, 0, 0};\n        const int dc[] = {0, 0, -1, 1};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) continue;\n                for (int d = 0; d < 4; d++) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (grid[ni][nj] == grid[i][j]) {\n                            count++;\n                        }\n                    }\n                }\n            }\n        }\n        return count / 2;  // Each adjacency counted twice\n    }\n    \n    vector<int> getComponentSizes() const {\n        vector<int> sizes;\n        array<array<bool, N>, N> visited{};\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0 && !visited[i][j]) {\n                    int flavor = grid[i][j];\n                    int size = 0;\n                    vector<pair<int,int>> stack = {{i, j}};\n                    visited[i][j] = true;\n                    \n                    while (!stack.empty()) {\n                        auto [r, c] = stack.back();\n                        stack.pop_back();\n                        size++;\n                        \n                        const int dr[] = {-1, 1, 0, 0};\n                        const int dc[] = {0, 0, -1, 1};\n                        \n                        for (int d = 0; d < 4; d++) {\n                            int nr = r + dr[d], nc = c + dc[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                if (!visited[nr][nc] && grid[nr][nc] == flavor) {\n                                    visited[nr][nc] = true;\n                                    stack.push_back({nr, nc});\n                                }\n                            }\n                        }\n                    }\n                    sizes.push_back(size);\n                }\n            }\n        }\n        return sizes;\n    }\n    \n    double evaluateScore() const {\n        auto sizes = getComponentSizes();\n        array<int, 4> flavorCount{};\n        \n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] != 0)\n                    flavorCount[grid[i][j]]++;\n        \n        double numerator = 0;\n        for (int s : sizes) numerator += s * s;\n        \n        double denominator = 0;\n        for (int f = 1; f <= 3; f++) denominator += flavorCount[f] * flavorCount[f];\n        \n        if (denominator == 0) return 0;\n        return 1e6 * numerator / denominator;\n    }\n    \n    // Heuristic evaluation for greedy selection\n    double heuristicEvaluate(const vector<int>& futureFlavors, int lookAhead) const {\n        double score = countSameFlavorAdjacency() * 10.0;\n        \n        // Add component size bonus\n        auto sizes = getComponentSizes();\n        for (int s : sizes) {\n            score += s * s * 0.5;\n        }\n        \n        // Consider future flavors - prefer tilts that create space for upcoming flavors\n        if (lookAhead > 0 && !futureFlavors.empty()) {\n            array<int, 4> flavorCount{};\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (grid[i][j] != 0)\n                        flavorCount[grid[i][j]]++;\n            \n            // Bonus for having clusters of flavors that appear soon\n            for (int f = 1; f <= 3; f++) {\n                if (flavorCount[f] > 0) {\n                    int upcoming = 0;\n                    for (int i = 0; i < min(lookAhead, (int)futureFlavors.size()); i++) {\n                        if (futureFlavors[i] == f) upcoming++;\n                    }\n                    score += upcoming * flavorCount[f] * 0.3;\n                }\n            }\n        }\n        \n        return score;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read flavor sequence\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; i++) {\n        cin >> flavors[i];\n    }\n    \n    GameState state;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    const char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        \n        // Find the p-th empty cell (1-indexed)\n        auto empty = state.getEmptyCells();\n        int row = empty[p - 1].first;\n        int col = empty[p - 1].second;\n        \n        // Place the candy\n        state.placeCandy(row, col, flavors[t]);\n        \n        // Skip tilt on last candy (nothing happens)\n        if (t == 99) {\n            cout << 'F' << endl;\n            continue;\n        }\n        \n        // Evaluate all 4 tilt directions\n        vector<pair<double, char>> evaluations;\n        \n        for (char dir : dirs) {\n            GameState next = state.tilt(dir);\n            \n            // Base heuristic score\n            double score = next.heuristicEvaluate(\n                vector<int>(flavors.begin() + t + 1, flavors.end()),\n                5\n            );\n            \n            // Add some randomness for exploration\n            score += (rng() % 100) * 0.01;\n            \n            evaluations.push_back({score, dir});\n        }\n        \n        // Select best direction\n        sort(evaluations.begin(), evaluations.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        char bestDir = evaluations[0].second;\n        cout << bestDir << endl;\n        \n        // Update state\n        state = state.tilt(bestDir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Compute degree sequence from edge string (sorted)\nvector<int> computeDegreeSeq(const string& edges, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Count edges\nint countEdges(const string& edges) {\n    int cnt = 0;\n    for (char c : edges) {\n        if (c == '1') cnt++;\n    }\n    return cnt;\n}\n\n// Sum of squared degrees\nlong long computeSumSqDegrees(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Sum of cubed degrees (3rd moment)\nlong long computeSumCbDegrees(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2\nint count2Paths(const vector<int>& deg) {\n    int paths = 0;\n    for (int d : deg) {\n        if (d >= 2) paths += d * (d - 1) / 2;\n    }\n    return paths;\n}\n\n// Degree variance\ndouble computeDegreeVariance(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    double mean = accumulate(deg.begin(), deg.end(), 0.0) / deg.size();\n    double var = 0;\n    for (int d : deg) {\n        var += (d - mean) * (d - mean);\n    }\n    return var / deg.size();\n}\n\n// Degree entropy\ndouble computeDegreeEntropy(const vector<int>& deg) {\n    if (deg.empty()) return 0;\n    int total = accumulate(deg.begin(), deg.end(), 0);\n    if (total == 0) return 0;\n    double entropy = 0;\n    for (int d : deg) {\n        if (d > 0) {\n            double p = (double)d / total;\n            entropy -= p * log2(p);\n        }\n    }\n    return entropy;\n}\n\n// Build adjacency matrix\nvector<vector<bool>> buildAdj(const string& edges, int N) {\n    vector<vector<bool>> adj(N, vector<bool>(N, false));\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (edges[idx] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            idx++;\n        }\n    }\n    return adj;\n}\n\n// Count triangles\nint countTriangles(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    int triangles = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (!adj[i][j]) continue;\n            for (int k = j + 1; k < N; k++) {\n                if (adj[i][k] && adj[j][k]) {\n                    triangles++;\n                }\n            }\n        }\n    }\n    return triangles;\n}\n\n// Count connected components\nint countConnectedComponents(const string& edges, int N) {\n    auto adj = buildAdj(edges, N);\n    vector<bool> visited(N, false);\n    int components = 0;\n    for (int i = 0; i < N; i++) {\n        if (!visited[i]) {\n            components++;\n            vector<int> q = {i};\n            visited[i] = true;\n            int head = 0;\n            while (head < (int)q.size()) {\n                int u = q[head++];\n                for (int v = 0; v < N; v++) {\n                    if (adj[u][v] && !visited[v]) {\n                        visited[v] = true;\n                        q.push_back(v);\n                    }\n                }\n            }\n        }\n    }\n    return components;\n}\n\n// Compute max degree\nint computeMaxDegree(const vector<int>& deg) {\n    return deg.empty() ? 0 : deg.back();\n}\n\n// Compute min degree\nint computeMinDegree(const vector<int>& deg) {\n    return deg.empty() ? 0 : deg.front();\n}\n\nstruct GraphInfo {\n    string edges;\n    int edge_count;\n    vector<int> degree_seq;\n    long long sum_sq_deg;\n    long long sum_cb_deg;\n    int two_paths;\n    int triangles;\n    int components;\n    double degree_var;\n    double degree_entropy;\n    int max_deg;\n    int min_deg;\n};\n\n// Generate edge positions in DETERMINISTIC order\n// Order: by (i+j) sum, then by i, then by j - creates consistent pattern\nvector<int> generateEdgeOrder(int N) {\n    int total_edges = N * (N - 1) / 2;\n    vector<pair<int, int>> edges;\n    edges.reserve(total_edges);\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            edges.push_back({i, j});\n        }\n    }\n    \n    // Sort by sum of indices, then by first index\n    sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n        int sum_a = a.first + a.second;\n        int sum_b = b.first + b.second;\n        if (sum_a != sum_b) return sum_a < sum_b;\n        return a.first < b.first;\n    });\n    \n    // Convert to linear indices\n    vector<int> positions(total_edges);\n    for (int i = 0; i < total_edges; i++) {\n        int ii = edges[i].first;\n        int jj = edges[i].second;\n        positions[i] = ii * N - ii * (ii + 1) / 2 + (jj - ii - 1);\n    }\n    \n    return positions;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n    \n    // Refined N selection - fine-tuned thresholds\n    int N;\n    if (eps < 0.01) {\n        N = 14;\n    } else if (eps < 0.025) {\n        N = 19;\n    } else if (eps < 0.045) {\n        N = 25;\n    } else if (eps < 0.07) {\n        N = 33;\n    } else if (eps < 0.10) {\n        N = 43;\n    } else if (eps < 0.14) {\n        N = 54;\n    } else if (eps < 0.18) {\n        N = 65;\n    } else if (eps < 0.22) {\n        N = 76;\n    } else if (eps < 0.27) {\n        N = 85;\n    } else if (eps < 0.32) {\n        N = 92;\n    } else if (eps < 0.36) {\n        N = 96;\n    } else if (eps < 0.39) {\n        N = 99;\n    } else {\n        N = 100;\n    }\n    \n    // Aggressive adjustment for large M - critical for high-value cases\n    if (M >= 65 && eps >= 0.18) N = max(N, 80);\n    if (M >= 70 && eps >= 0.20) N = max(N, 88);\n    if (M >= 75 && eps >= 0.22) N = max(N, 92);\n    if (M >= 80 && eps >= 0.15) N = max(N, 90);\n    if (M >= 85) N = min(100, N + 4);\n    if (M >= 90) N = min(100, N + 6);\n    if (M >= 95) N = 100;\n    if (M >= 70 && eps >= 0.28) N = 100;\n    if (M >= 75 && eps >= 0.25) N = 100;\n    if (M >= 80 && eps >= 0.20) N = 100;\n    \n    N = max(4, min(100, N));\n    int total_edges = N * (N - 1) / 2;\n    \n    // DETERMINISTIC edge order\n    vector<int> edge_order = generateEdgeOrder(N);\n    \n    // Store graph information\n    vector<GraphInfo> graphs(M);\n    \n    for (int k = 0; k < M; k++) {\n        GraphInfo& info = graphs[k];\n        \n        // Even distribution of edge counts\n        int target_edges = (M > 1) ? (k * total_edges) / max(1, M - 1) : total_edges / 2;\n        target_edges = max(0, min(total_edges, target_edges));\n        info.edge_count = target_edges;\n        \n        // Generate with DETERMINISTIC edge order\n        string g(total_edges, '0');\n        for (int i = 0; i < target_edges && i < total_edges; i++) {\n            g[edge_order[i]] = '1';\n        }\n        \n        info.edges = g;\n        info.degree_seq = computeDegreeSeq(g, N);\n        info.sum_sq_deg = computeSumSqDegrees(info.degree_seq);\n        info.sum_cb_deg = computeSumCbDegrees(info.degree_seq);\n        info.two_paths = count2Paths(info.degree_seq);\n        info.triangles = (eps < 0.20) ? countTriangles(g, N) : 0;\n        info.components = countConnectedComponents(g, N);\n        info.degree_var = computeDegreeVariance(info.degree_seq);\n        info.degree_entropy = computeDegreeEntropy(info.degree_seq);\n        info.max_deg = computeMaxDegree(info.degree_seq);\n        info.min_deg = computeMinDegree(info.degree_seq);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << graphs[k].edges << \"\\n\";\n    }\n    cout << flush;\n    \n    // Optimized scoring with fine-tuned weights\n    double edge_noise_var = total_edges * eps * (1.0 - eps);\n    double edge_noise_std = sqrt(max(1.0, edge_noise_var));\n    \n    // Feature weights - optimized based on performance analysis\n    double w_sq = (eps < 0.15) ? 0.4 : (eps < 0.25) ? 0.25 : 0.12;\n    double w_cb = (eps < 0.12) ? 0.25 : (eps < 0.20) ? 0.12 : 0.05;\n    double w_path = (eps < 0.15) ? 0.35 : (eps < 0.25) ? 0.18 : 0.08;\n    double w_var = (eps < 0.20) ? 60.0 : (eps < 0.30) ? 30.0 : 10.0;\n    double w_ent = (eps < 0.18) ? 35.0 : (eps < 0.28) ? 15.0 : 4.0;\n    double w_maxdeg = (eps < 0.20) ? 4.0 : (eps < 0.30) ? 2.0 : 0.8;\n    double w_mindeg = (eps < 0.20) ? 4.0 : (eps < 0.30) ? 2.0 : 0.8;\n    double w_tri = (eps < 0.12) ? 0.25 : (eps < 0.15) ? 0.10 : 0.0;\n    double w_comp = (eps < 0.20) ? 2.5 : (eps < 0.30) ? 1.5 : 0.6;\n    \n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        if (h.empty() || h.length() != (size_t)total_edges) {\n            cout << 0 << \"\\n\";\n            cout << flush;\n            continue;\n        }\n        \n        // Compute query features\n        int h_edges = countEdges(h);\n        vector<int> h_deg = computeDegreeSeq(h, N);\n        long long h_sum_sq = computeSumSqDegrees(h_deg);\n        long long h_sum_cb = computeSumCbDegrees(h_deg);\n        int h_2paths = count2Paths(h_deg);\n        int h_triangles = (eps < 0.20) ? countTriangles(h, N) : 0;\n        int h_components = countConnectedComponents(h, N);\n        double h_degree_var = computeDegreeVariance(h_deg);\n        double h_entropy = computeDegreeEntropy(h_deg);\n        int h_max_deg = computeMaxDegree(h_deg);\n        int h_min_deg = computeMinDegree(h_deg);\n        \n        int best_k = 0;\n        double best_log_prob = -1e18;\n        \n        for (int k = 0; k < M; k++) {\n            double log_prob = 0;\n            \n            // Edge count (primary signal) - always weight 1.0\n            double edge_diff = h_edges - graphs[k].edge_count;\n            log_prob -= 0.5 * (edge_diff * edge_diff) / (edge_noise_var + 1);\n            \n            // Sum of squared degrees\n            double sq_diff = (double)(h_sum_sq - graphs[k].sum_sq_deg);\n            double sq_noise_var = N * N * N * eps * 0.28;\n            log_prob -= w_sq * 0.5 * (sq_diff * sq_diff) / (sq_noise_var * sq_noise_var + 1);\n            \n            // Sum of cubed degrees (3rd moment)\n            if (w_cb > 0.01) {\n                double cb_diff = (double)(h_sum_cb - graphs[k].sum_cb_deg);\n                double cb_noise_var = N * N * N * N * eps * 0.15;\n                log_prob -= w_cb * 0.5 * (cb_diff * cb_diff) / (cb_noise_var * cb_noise_var + 1);\n            }\n            \n            // 2-path count\n            double path_diff = h_2paths - graphs[k].two_paths;\n            double path_noise_var = total_edges * N * eps * 0.18;\n            log_prob -= w_path * 0.5 * (path_diff * path_diff) / (max(1.0, path_noise_var) + 1);\n            \n            // Degree variance\n            double var_diff = h_degree_var - graphs[k].degree_var;\n            log_prob -= w_var * var_diff * var_diff;\n            \n            // Degree entropy\n            double ent_diff = h_entropy - graphs[k].degree_entropy;\n            log_prob -= w_ent * ent_diff * ent_diff;\n            \n            // Max degree\n            double maxdeg_diff = h_max_deg - graphs[k].max_deg;\n            log_prob -= w_maxdeg * maxdeg_diff * maxdeg_diff;\n            \n            // Min degree\n            double mindeg_diff = h_min_deg - graphs[k].min_deg;\n            log_prob -= w_mindeg * mindeg_diff * mindeg_diff;\n            \n            // Triangle count (only for low eps)\n            if (w_tri > 0.01 && graphs[k].triangles > 0) {\n                double tri_diff = h_triangles - graphs[k].triangles;\n                double tri_noise_var = graphs[k].triangles * eps * 3 + 1;\n                log_prob -= w_tri * 0.5 * (tri_diff * tri_diff) / (tri_noise_var + 1);\n            }\n            \n            // Component count\n            if (h_components != graphs[k].components) {\n                log_prob -= w_comp;\n            }\n            \n            if (log_prob > best_log_prob) {\n                best_log_prob = log_prob;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nstruct Edge {\n    int id;\n    int u, v;\n    long long w;\n    double mid_x, mid_y;\n    double importance;\n};\n\nclass Solver {\npublic:\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<vector<pair<int, int>>> adj;\n    vector<pair<int, int>> coords;\n    vector<vector<long long>> base_dist;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    static constexpr long long INF = 1e18;\n    static constexpr long long UNREACHABLE = 1000000000;\n    \n    void compute_base_distances() {\n        base_dist.assign(N, vector<long long>(N, INF));\n        \n        for (int src = 0; src < N; src++) {\n            base_dist[src][src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > base_dist[src][u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < base_dist[src][v]) {\n                        base_dist[src][v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n        }\n    }\n    \n    void compute_edge_importance() {\n        vector<double> importance(M, 0);\n        \n        int samples = min(N, 30);\n        for (int i = 0; i < samples; i++) {\n            int src = i * N / samples;\n            vector<long long> dist(N, INF);\n            vector<int> parent_edge(N, -1);\n            dist[src] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        parent_edge[v] = edge_idx;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int v = 0; v < N; v++) {\n                if (v != src && parent_edge[v] != -1) {\n                    importance[parent_edge[v]] += 1.0;\n                }\n            }\n        }\n        \n        long long max_w = 1;\n        for (auto& e : edges) max_w = max(max_w, e.w);\n        \n        double center_x = 500, center_y = 500;\n        for (int i = 0; i < M; i++) {\n            double dist_from_center = hypot(edges[i].mid_x - center_x, edges[i].mid_y - center_y);\n            double weight_factor = 1.0 + (max_w - edges[i].w) / (double)max_w * 0.3;\n            double spatial_factor = 1.0 + dist_from_center / 1000.0;\n            edges[i].importance = importance[i] * weight_factor * spatial_factor;\n        }\n    }\n    \n    long long compute_day_frustration_fast(const vector<int>& edges_to_remove) {\n        if (edges_to_remove.empty()) return 0;\n        \n        vector<bool> edge_removed(M, false);\n        for (int idx : edges_to_remove) {\n            edge_removed[idx] = true;\n        }\n        \n        long long total_increase = 0;\n        int samples = min(N, 15);\n        \n        for (int src = 0; src < samples; src++) {\n            int src_idx = src * N / samples;\n            vector<long long> dist(N, INF);\n            dist[src_idx] = 0;\n            priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n            pq.push({0, src_idx});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                \n                if (d > dist[u]) continue;\n                \n                for (auto [v, edge_idx] : adj[u]) {\n                    if (edge_removed[edge_idx]) continue;\n                    \n                    long long new_dist = d + edges[edge_idx].w;\n                    if (new_dist < dist[v]) {\n                        dist[v] = new_dist;\n                        pq.push({new_dist, v});\n                    }\n                }\n            }\n            \n            for (int dst = 0; dst < samples; dst++) {\n                if (src == dst) continue;\n                int dst_idx = dst * N / samples;\n                \n                long long d_k = (dist[dst_idx] >= INF) ? UNREACHABLE : dist[dst_idx];\n                long long d_base = (base_dist[src_idx][dst_idx] >= INF) ? UNREACHABLE : base_dist[src_idx][dst_idx];\n                \n                total_increase += max(0LL, d_k - d_base);\n            }\n        }\n        \n        double scale = (double)(N * (N - 1)) / (samples * (samples - 1));\n        return (long long)(total_increase * scale);\n    }\n    \n    vector<int> solve() {\n        start_time = chrono::steady_clock::now();\n        \n        compute_base_distances();\n        compute_edge_importance();\n        \n        // Sort edges by importance (descending)\n        vector<int> edge_order(M);\n        iota(edge_order.begin(), edge_order.end(), 0);\n        sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n            return edges[a].importance > edges[b].importance;\n        });\n        \n        // Initial assignment with spatial awareness\n        vector<int> assignment(M, -1);\n        vector<vector<int>> day_edges(D);\n        vector<double> day_center_x(D, 500), day_center_y(D, 500);\n        vector<long long> day_importance(D, 0);\n        \n        for (int edge_idx : edge_order) {\n            int best_day = 0;\n            double best_score = 1e18;\n            \n            for (int d = 0; d < D; d++) {\n                if ((int)day_edges[d].size() < K) {\n                    // Score based on importance balance and spatial spread\n                    double importance_score = day_importance[d];\n                    double spatial_score = 0;\n                    if (!day_edges[d].empty()) {\n                        spatial_score = hypot(edges[edge_idx].mid_x - day_center_x[d], \n                                            edges[edge_idx].mid_y - day_center_y[d]);\n                    }\n                    double score = importance_score * 0.7 - spatial_score * 0.3;\n                    \n                    if (score < best_score) {\n                        best_score = score;\n                        best_day = d;\n                    }\n                }\n            }\n            \n            assignment[edge_idx] = best_day + 1;\n            day_edges[best_day].push_back(edge_idx);\n            day_importance[best_day] += (long long)(edges[edge_idx].importance * 1000);\n            \n            // Update day center\n            int n = day_edges[best_day].size();\n            day_center_x[best_day] = (day_center_x[best_day] * (n-1) + edges[edge_idx].mid_x) / n;\n            day_center_y[best_day] = (day_center_y[best_day] * (n-1) + edges[edge_idx].mid_y) / n;\n        }\n        \n        // Compute initial day frustrations\n        vector<long long> day_frustration(D);\n        long long current_total = 0;\n        for (int d = 0; d < D; d++) {\n            day_frustration[d] = compute_day_frustration_fast(day_edges[d]);\n            current_total += day_frustration[d];\n        }\n        \n        long long best_total = current_total;\n        vector<int> best_assignment = assignment;\n        \n        // Aggressive local search with time budget\n        double time_limit = 5.3;\n        double temperature = 0.8;\n        int iteration = 0;\n        int no_improve_count = 0;\n        \n        vector<double> edge_selection_prob(M);\n        double total_importance = 0;\n        for (int i = 0; i < M; i++) {\n            edge_selection_prob[i] = edges[i].importance + 1.0;\n            total_importance += edge_selection_prob[i];\n        }\n        \n        while (no_improve_count < 50) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Select edge biased by importance\n            double r = uniform_real_distribution<>(0.0, total_importance)(rng);\n            int edge_idx = 0;\n            double cumsum = 0;\n            for (int i = 0; i < M; i++) {\n                cumsum += edge_selection_prob[i];\n                if (r <= cumsum) {\n                    edge_idx = i;\n                    break;\n                }\n            }\n            \n            int old_day = assignment[edge_idx] - 1;\n            int new_day = uniform_int_distribution<>(0, D - 1)(rng);\n            \n            if (new_day == old_day || (int)day_edges[new_day].size() >= K) {\n                continue;\n            }\n            \n            // Fast delta computation\n            vector<int> old_day_temp;\n            old_day_temp.reserve(day_edges[old_day].size());\n            for (int e : day_edges[old_day]) {\n                if (e != edge_idx) old_day_temp.push_back(e);\n            }\n            \n            vector<int> new_day_temp = day_edges[new_day];\n            new_day_temp.push_back(edge_idx);\n            \n            long long new_old = compute_day_frustration_fast(old_day_temp);\n            long long new_new = compute_day_frustration_fast(new_day_temp);\n            \n            long long delta = (new_old + new_new) - (day_frustration[old_day] + day_frustration[new_day]);\n            \n            double accept_prob = exp(-delta / (temperature * max(1LL, current_total / D) + 1));\n            \n            if (delta < 0 || uniform_real_distribution<>(0.0, 1.0)(rng) < accept_prob) {\n                assignment[edge_idx] = new_day + 1;\n                \n                auto it = find(day_edges[old_day].begin(), day_edges[old_day].end(), edge_idx);\n                if (it != day_edges[old_day].end()) day_edges[old_day].erase(it);\n                day_edges[new_day].push_back(edge_idx);\n                \n                day_frustration[old_day] = new_old;\n                day_frustration[new_day] = new_new;\n                \n                current_total += delta;\n                \n                if (current_total < best_total) {\n                    best_total = current_total;\n                    best_assignment = assignment;\n                    no_improve_count = 0;\n                } else {\n                    no_improve_count++;\n                }\n            } else {\n                no_improve_count++;\n            }\n            \n            iteration++;\n            temperature *= 0.9998;\n        }\n        \n        return best_assignment;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    Solver solver;\n    solver.N = N;\n    solver.M = M;\n    solver.D = D;\n    solver.K = K;\n    solver.rng.seed(42);\n    \n    solver.edges.resize(M);\n    solver.adj.resize(N);\n    solver.coords.resize(N);\n    \n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        solver.edges[i] = {i, u, v, (long long)w, 0, 0, 0};\n        solver.adj[u].push_back({v, i});\n        solver.adj[v].push_back({u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    \n    for (int i = 0; i < M; i++) {\n        int u = solver.edges[i].u;\n        int v = solver.edges[i].v;\n        solver.edges[i].mid_x = (solver.coords[u].first + solver.coords[v].first) / 2.0;\n        solver.edges[i].mid_y = (solver.coords[u].second + solver.coords[v].second) / 2.0;\n    }\n    \n    auto assignment = solver.solve();\n    \n    for (int i = 0; i < M; i++) {\n        cout << assignment[i] << (i == M - 1 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n};\n\n// Estimate score from used positions\nlong long estimateScore(int D, const vector<vector<vector<bool>>>& used1, \n                        const vector<vector<vector<bool>>>& used2,\n                        const vector<vector<vector<bool>>>& common) {\n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    int r1 = 0, r2 = 0;\n    double shared_inv_sum = 0;\n    \n    // Shared blocks (common positions)\n    vector<vector<vector<bool>>> visited_shared(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x] && !visited_shared[z][y][x]) {\n                    int vol = 0;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited_shared[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        vol++;\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir], ny = cur.y + dy[dir], nz = cur.z + dz[dir];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                common[nz][ny][nx] && !visited_shared[nz][ny][nx]) {\n                                visited_shared[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    shared_inv_sum += 1.0 / vol;\n                }\n            }\n        }\n    }\n    \n    // Unique blocks in arrangement 1 (contribute to r2)\n    vector<vector<vector<bool>>> visited1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used1[z][y][x] && !common[z][y][x] && !visited1[z][y][x]) {\n                    int vol = 0;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited1[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        vol++;\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir], ny = cur.y + dy[dir], nz = cur.z + dz[dir];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used1[nz][ny][nx] && !common[nz][ny][nx] && !visited1[nz][ny][nx]) {\n                                visited1[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    r2 += vol;\n                }\n            }\n        }\n    }\n    \n    // Unique blocks in arrangement 2 (contribute to r1)\n    vector<vector<vector<bool>>> visited2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used2[z][y][x] && !common[z][y][x] && !visited2[z][y][x]) {\n                    int vol = 0;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited2[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        vol++;\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir], ny = cur.y + dy[dir], nz = cur.z + dz[dir];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used2[nz][ny][nx] && !common[nz][ny][nx] && !visited2[nz][ny][nx]) {\n                                visited2[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    r1 += vol;\n                }\n            }\n        }\n    }\n    \n    return (long long)round(1e9 * (r1 + r2 + shared_inv_sum));\n}\n\n// Check if silhouette is satisfied\nbool checkSilhouette(int D, const vector<vector<vector<bool>>>& used,\n                     const vector<string>& f, const vector<string>& r) {\n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            if (f[z][x] == '1') {\n                bool found = false;\n                for (int y = 0; y < D; y++) {\n                    if (used[z][y][x]) { found = true; break; }\n                }\n                if (!found) return false;\n            }\n        }\n        for (int y = 0; y < D; y++) {\n            if (r[z][y] == '1') {\n                bool found = false;\n                for (int x = 0; x < D; x++) {\n                    if (used[z][y][x]) { found = true; break; }\n                }\n                if (!found) return false;\n            }\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    int D;\n    cin >> D;\n    \n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; i++) cin >> f1[i];\n    for (int i = 0; i < D; i++) cin >> r1[i];\n    for (int i = 0; i < D; i++) cin >> f2[i];\n    for (int i = 0; i < D; i++) cin >> r2[i];\n    \n    // Compute valid positions\n    vector<vector<vector<bool>>> valid1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> valid2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[z][y][x] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[z][y][x] = true;\n                }\n            }\n        }\n    }\n    \n    // Common positions\n    vector<vector<vector<bool>>> common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                common[z][y][x] = valid1[z][y][x] && valid2[z][y][x];\n            }\n        }\n    }\n    \n    int dx[6] = {1, -1, 0, 0, 0, 0};\n    int dy[6] = {0, 0, 1, -1, 0, 0};\n    int dz[6] = {0, 0, 0, 0, 1, -1};\n    \n    // Best solution tracking\n    vector<vector<vector<bool>>> best_used1, best_used2;\n    long long best_score = LLONG_MAX;\n    \n    mt19937 rng(42);\n    \n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // More restarts with time-aware termination (target ~5 seconds)\n    int max_restarts = 30;\n    for (int seed = 0; seed < max_restarts; seed++) {\n        if (elapsed_ms() > 5000) break;\n        \n        if (seed > 0) rng.seed(seed * 12345 + D);\n        \n        vector<vector<vector<bool>>> used1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        vector<vector<vector<bool>>> used2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        \n        // Step 1: ALL common positions\n        for (int z = 0; z < D; z++) {\n            for (int y = 0; y < D; y++) {\n                for (int x = 0; x < D; x++) {\n                    if (common[z][y][x]) {\n                        used1[z][y][x] = true;\n                        used2[z][y][x] = true;\n                    }\n                }\n            }\n        }\n        \n        auto countAdjacent = [&](int x, int y, int z, const vector<vector<vector<bool>>>& used) {\n            int cnt = 0;\n            for (int dir = 0; dir < 6; dir++) {\n                int nx = x + dx[dir], ny = y + dy[dir], nz = z + dz[dir];\n                if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n                    if (used[nz][ny][nx]) cnt++;\n                }\n            }\n            return cnt;\n        };\n        \n        // Strategy variation: different randomization levels\n        int random_range = 10 + (seed % 5) * 5;\n        \n        // Step 2: Greedy placement with randomization\n        for (int z = 0; z < D; z++) {\n            // Arrangement 1\n            vector<bool> covered_x1(D, false), covered_y1(D, false);\n            \n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (common[z][y][x]) {\n                        if (f1[z][x] == '1') covered_x1[x] = true;\n                        if (r1[z][y] == '1') covered_y1[y] = true;\n                    }\n                }\n            }\n            \n            vector<tuple<int,int,int,int,int>> candidates1;\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (valid1[z][y][x] && !common[z][y][x]) {\n                        bool need_x = (f1[z][x] == '1' && !covered_x1[x]);\n                        bool need_y = (r1[z][y] == '1' && !covered_y1[y]);\n                        int covers = (need_x ? 1 : 0) + (need_y ? 1 : 0);\n                        int adj = countAdjacent(x, y, z, used1);\n                        candidates1.push_back({covers, adj, x, y, z});\n                    }\n                }\n            }\n            \n            for (auto& t : candidates1) {\n                get<1>(t) += rng() % random_range;\n            }\n            \n            sort(candidates1.begin(), candidates1.end(), [](const auto& a, const auto& b) {\n                if (get<0>(a) != get<0>(b)) return get<0>(a) > get<0>(b);\n                return get<1>(a) > get<1>(b);\n            });\n            \n            for (const auto& [covers, adj, x, y, zz] : candidates1) {\n                bool need_x = (f1[z][x] == '1' && !covered_x1[x]);\n                bool need_y = (r1[z][y] == '1' && !covered_y1[y]);\n                if (need_x || need_y) {\n                    used1[z][y][x] = true;\n                    if (need_x) covered_x1[x] = true;\n                    if (need_y) covered_y1[y] = true;\n                }\n            }\n            \n            // Arrangement 2\n            vector<bool> covered_x2(D, false), covered_y2(D, false);\n            \n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (common[z][y][x]) {\n                        if (f2[z][x] == '1') covered_x2[x] = true;\n                        if (r2[z][y] == '1') covered_y2[y] = true;\n                    }\n                }\n            }\n            \n            vector<tuple<int,int,int,int,int>> candidates2;\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (valid2[z][y][x] && !common[z][y][x]) {\n                        bool need_x = (f2[z][x] == '1' && !covered_x2[x]);\n                        bool need_y = (r2[z][y] == '1' && !covered_y2[y]);\n                        int covers = (need_x ? 1 : 0) + (need_y ? 1 : 0);\n                        int adj = countAdjacent(x, y, z, used2);\n                        candidates2.push_back({covers, adj, x, y, z});\n                    }\n                }\n            }\n            \n            for (auto& t : candidates2) {\n                get<1>(t) += rng() % random_range;\n            }\n            \n            sort(candidates2.begin(), candidates2.end(), [](const auto& a, const auto& b) {\n                if (get<0>(a) != get<0>(b)) return get<0>(a) > get<0>(b);\n                return get<1>(a) > get<1>(b);\n            });\n            \n            for (const auto& [covers, adj, x, y, zz] : candidates2) {\n                bool need_x = (f2[z][x] == '1' && !covered_x2[x]);\n                bool need_y = (r2[z][y] == '1' && !covered_y2[y]);\n                if (need_x || need_y) {\n                    used2[z][y][x] = true;\n                    if (need_x) covered_x2[x] = true;\n                    if (need_y) covered_y2[y] = true;\n                }\n            }\n        }\n        \n        // Step 3: Post-optimization with multiple passes\n        auto canRemove = [&](int x, int y, int z, vector<vector<vector<bool>>>& used,\n                             const vector<string>& f, const vector<string>& r) -> bool {\n            used[z][y][x] = false;\n            bool ok = true;\n            for (int xx = 0; xx < D; xx++) {\n                if (f[z][xx] == '1') {\n                    bool found = false;\n                    for (int yy = 0; yy < D; yy++) {\n                        if (used[z][yy][xx]) { found = true; break; }\n                    }\n                    if (!found) { ok = false; break; }\n                }\n            }\n            if (ok) {\n                for (int yy = 0; yy < D; yy++) {\n                    if (r[z][yy] == '1') {\n                        bool found = false;\n                        for (int xx = 0; xx < D; xx++) {\n                            if (used[z][yy][xx]) { found = true; break; }\n                        }\n                        if (!found) { ok = false; break; }\n                    }\n                }\n            }\n            if (!ok) used[z][y][x] = true;\n            return ok;\n        };\n        \n        // More aggressive removal\n        for (int pass = 0; pass < 10; pass++) {\n            for (int z = D - 1; z >= 0; z--) {\n                for (int y = D - 1; y >= 0; y--) {\n                    for (int x = D - 1; x >= 0; x--) {\n                        if (used1[z][y][x] && !common[z][y][x]) {\n                            canRemove(x, y, z, used1, f1, r1);\n                        }\n                    }\n                }\n            }\n            \n            for (int z = D - 1; z >= 0; z--) {\n                for (int y = D - 1; y >= 0; y--) {\n                    for (int x = D - 1; x >= 0; x--) {\n                        if (used2[z][y][x] && !common[z][y][x]) {\n                            canRemove(x, y, z, used2, f2, r2);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Estimate actual score\n        long long score = estimateScore(D, used1, used2, common);\n        \n        if (score < best_score) {\n            best_score = score;\n            best_used1 = used1;\n            best_used2 = used2;\n        }\n    }\n    \n    auto& used1 = best_used1;\n    auto& used2 = best_used2;\n    \n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    int block_id = 1;\n    \n    // Step 4: Assign connected components (3D)\n    // First: shared blocks\n    vector<vector<vector<bool>>> visited_shared(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (common[z][y][x] && !visited_shared[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited_shared[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                common[nz][ny][nx] && !visited_shared[nz][ny][nx]) {\n                                visited_shared[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Second: arrangement 1 only\n    vector<vector<vector<bool>>> visited1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used1[z][y][x] && b1[z][y][x] == 0 && !visited1[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited1[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used1[nz][ny][nx] && b1[nz][ny][nx] == 0 && !visited1[nz][ny][nx]) {\n                                visited1[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b1[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    // Third: arrangement 2 only\n    vector<vector<vector<bool>>> visited2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int y = 0; y < D; y++) {\n            for (int x = 0; x < D; x++) {\n                if (used2[z][y][x] && b2[z][y][x] == 0 && !visited2[z][y][x]) {\n                    vector<Point3D> component;\n                    queue<Point3D> q;\n                    q.push({x, y, z});\n                    visited2[z][y][x] = true;\n                    \n                    while (!q.empty()) {\n                        Point3D cur = q.front(); q.pop();\n                        component.push_back(cur);\n                        \n                        for (int dir = 0; dir < 6; dir++) {\n                            int nx = cur.x + dx[dir];\n                            int ny = cur.y + dy[dir];\n                            int nz = cur.z + dz[dir];\n                            \n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                used2[nz][ny][nx] && b2[nz][ny][nx] == 0 && !visited2[nz][ny][nx]) {\n                                visited2[nz][ny][nx] = true;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    \n                    for (const auto& p : component) {\n                        b2[p.z][p.y][p.x] = block_id;\n                    }\n                    block_id++;\n                }\n            }\n        }\n    }\n    \n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    \n    // Output in correct order: x*D^2 + y*D + z\n    for (int i = 0; i < 2; i++) {\n        vector<int> output;\n        output.reserve(D * D * D);\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                    output.push_back(i == 0 ? b1[z][y][x] : b2[z][y][x]);\n                }\n            }\n        }\n        \n        for (int j = 0; j < (int)output.size(); j++) {\n            cout << output[j] << (j == (int)output.size() - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <numeric>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        return parent[x] == x ? x : parent[x] = find(parent[x]);\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        parent[y] = x;\n        return true;\n    }\n};\n\nlong long dist_ll(Point a, Point b) {\n    long long dx = a.x - b.x;\n    long long dy = a.y - b.y;\n    return round(sqrt(dx * dx + dy * dy));\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    vector<Point> stations(N);\n    for (int i = 0; i < N; i++) {\n        cin >> stations[i].x >> stations[i].y;\n    }\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n    }\n    \n    vector<Point> residents(K);\n    for (int i = 0; i < K; i++) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n    \n    // Precompute distances from each resident to each station\n    vector<vector<long long>> resident_station_dist(K, vector<long long>(N));\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            resident_station_dist[k][i] = dist_ll(residents[k], stations[i]);\n        }\n    }\n    \n    // Build MST from station 0 for initial connectivity\n    vector<pair<long long, int>> mst_edges;\n    vector<Edge> sorted_edges = edges;\n    sort(sorted_edges.begin(), sorted_edges.end(), \n         [](const Edge& a, const Edge& b) { return a.w < b.w; });\n    \n    DSU dsu(N);\n    vector<int> edge_in_mst(M, 0);\n    long long mst_cost = 0;\n    int edges_added = 0;\n    \n    for (int i = 0; i < M && edges_added < N - 1; i++) {\n        int idx = -1;\n        for (int j = 0; j < M; j++) {\n            if (edge_in_mst[j]) continue;\n            if (edges[j].w == sorted_edges[i].w && \n                dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                idx = j;\n                break;\n            }\n        }\n        if (idx == -1) {\n            for (int j = 0; j < M; j++) {\n                if (edge_in_mst[j]) continue;\n                if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                    idx = j;\n                    break;\n                }\n            }\n        }\n        if (idx != -1) {\n            dsu.unite(edges[idx].u, edges[idx].v);\n            edge_in_mst[idx] = 1;\n            mst_cost += edges[idx].w;\n            edges_added++;\n        }\n    }\n    \n    // Find connected component from station 0\n    vector<int> reachable(N, 0);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (edge_in_mst[i]) {\n            adj[edges[i].u].push_back(edges[i].v);\n            adj[edges[i].v].push_back(edges[i].u);\n        }\n    }\n    \n    queue<int> q;\n    q.push(0);\n    reachable[0] = 1;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (!reachable[v]) {\n                reachable[v] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Assign residents to nearest reachable station\n    vector<long long> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        long long min_dist = 1e18;\n        int best_station = -1;\n        for (int i = 0; i < N; i++) {\n            if (reachable[i]) {\n                if (resident_station_dist[k][i] < min_dist) {\n                    min_dist = resident_station_dist[k][i];\n                    best_station = i;\n                }\n            }\n        }\n        if (best_station != -1 && min_dist <= 5000) {\n            P[best_station] = max(P[best_station], min_dist);\n        }\n    }\n    \n    // Calculate initial cost\n    auto calc_cost = [&]() -> long long {\n        long long cost = 0;\n        for (int i = 0; i < N; i++) {\n            cost += P[i] * P[i];\n        }\n        for (int i = 0; i < M; i++) {\n            if (edge_in_mst[i]) {\n                cost += edges[i].w;\n            }\n        }\n        return cost;\n    };\n    \n    auto check_coverage = [&]() -> bool {\n        for (int k = 0; k < K; k++) {\n            bool covered = false;\n            for (int i = 0; i < N; i++) {\n                if (reachable[i] && resident_station_dist[k][i] <= P[i]) {\n                    covered = true;\n                    break;\n                }\n            }\n            if (!covered) return false;\n        }\n        return true;\n    };\n    \n    long long best_cost = calc_cost();\n    vector<int> best_edge_state = edge_in_mst;\n    vector<long long> best_P = P;\n    \n    // Try adding beneficial edges\n    mt19937 rng(42);\n    for (int iter = 0; iter < 500; iter++) {\n        vector<int> current_edge_state = best_edge_state;\n        vector<long long> current_P = best_P;\n        \n        // Recompute reachable\n        vector<int> cur_reachable(N, 0);\n        vector<vector<int>> cur_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (current_edge_state[i]) {\n                cur_adj[edges[i].u].push_back(edges[i].v);\n                cur_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> cq;\n        cq.push(0);\n        cur_reachable[0] = 1;\n        while (!cq.empty()) {\n            int u = cq.front(); cq.pop();\n            for (int v : cur_adj[u]) {\n                if (!cur_reachable[v]) {\n                    cur_reachable[v] = 1;\n                    cq.push(v);\n                }\n            }\n        }\n        \n        // Try adding a random edge\n        int edge_to_add = uniform_int_distribution<>(0, M-1)(rng);\n        if (!current_edge_state[edge_to_add]) {\n            current_edge_state[edge_to_add] = 1;\n            \n            // Recompute reachable\n            fill(cur_reachable.begin(), cur_reachable.end(), 0);\n            for (int i = 0; i < N; i++) cur_adj[i].clear();\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    cur_adj[edges[i].u].push_back(edges[i].v);\n                    cur_adj[edges[i].v].push_back(edges[i].u);\n                }\n            }\n            cq = queue<int>();\n            cq.push(0);\n            cur_reachable[0] = 1;\n            while (!cq.empty()) {\n                int u = cq.front(); cq.pop();\n                for (int v : cur_adj[u]) {\n                    if (!cur_reachable[v]) {\n                        cur_reachable[v] = 1;\n                        cq.push(v);\n                    }\n                }\n            }\n            \n            // Recalculate P\n            fill(current_P.begin(), current_P.end(), 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    current_P[best_station] = max(current_P[best_station], min_dist);\n                }\n            }\n            \n            // Calculate new cost\n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += current_P[i] * current_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (current_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            // Check if all residents covered\n            bool all_covered = true;\n            for (int k = 0; k < K; k++) {\n                bool covered = false;\n                for (int i = 0; i < N; i++) {\n                    if (cur_reachable[i] && resident_station_dist[k][i] <= current_P[i]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    all_covered = false;\n                    break;\n                }\n            }\n            \n            if (all_covered && new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = current_edge_state;\n                best_P = current_P;\n            }\n        }\n    }\n    \n    // Try removing expensive edges if possible\n    vector<pair<long long, int>> edge_by_cost;\n    for (int i = 0; i < M; i++) {\n        if (best_edge_state[i]) {\n            edge_by_cost.push_back({edges[i].w, i});\n        }\n    }\n    sort(edge_by_cost.rbegin(), edge_by_cost.rend());\n    \n    for (auto& [w, idx] : edge_by_cost) {\n        vector<int> test_edge_state = best_edge_state;\n        test_edge_state[idx] = 0;\n        \n        // Check if still connected\n        vector<int> test_reachable(N, 0);\n        vector<vector<int>> test_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (test_edge_state[i]) {\n                test_adj[edges[i].u].push_back(edges[i].v);\n                test_adj[edges[i].v].push_back(edges[i].u);\n            }\n        }\n        queue<int> tq;\n        tq.push(0);\n        test_reachable[0] = 1;\n        while (!tq.empty()) {\n            int u = tq.front(); tq.pop();\n            for (int v : test_adj[u]) {\n                if (!test_reachable[v]) {\n                    test_reachable[v] = 1;\n                    tq.push(v);\n                }\n            }\n        }\n        \n        // Check if all residents still coverable\n        bool all_coverable = true;\n        for (int k = 0; k < K; k++) {\n            bool can_cover = false;\n            for (int i = 0; i < N; i++) {\n                if (test_reachable[i] && resident_station_dist[k][i] <= 5000) {\n                    can_cover = true;\n                    break;\n                }\n            }\n            if (!can_cover) {\n                all_coverable = false;\n                break;\n            }\n        }\n        \n        if (all_coverable) {\n            vector<long long> test_P(N, 0);\n            for (int k = 0; k < K; k++) {\n                long long min_dist = 1e18;\n                int best_station = -1;\n                for (int i = 0; i < N; i++) {\n                    if (test_reachable[i]) {\n                        if (resident_station_dist[k][i] < min_dist) {\n                            min_dist = resident_station_dist[k][i];\n                            best_station = i;\n                        }\n                    }\n                }\n                if (best_station != -1 && min_dist <= 5000) {\n                    test_P[best_station] = max(test_P[best_station], min_dist);\n                }\n            }\n            \n            long long new_cost = 0;\n            for (int i = 0; i < N; i++) {\n                new_cost += test_P[i] * test_P[i];\n            }\n            for (int i = 0; i < M; i++) {\n                if (test_edge_state[i]) {\n                    new_cost += edges[i].w;\n                }\n            }\n            \n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_edge_state = test_edge_state;\n                best_P = test_P;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << best_P[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << best_edge_state[i] << (i == M-1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cstring>\n#include <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nint N = 30;\nint grid[30][30];\nPoint pos[465]; \n\nvector<tuple<int, int, int, int>> ops;\n\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool is_valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid do_swap(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return;\n    int v1 = grid[x1][y1];\n    int v2 = grid[x2][y2];\n    grid[x1][y1] = v2;\n    grid[x2][y2] = v1;\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n}\n\n// BFS from target to compute distances to all reachable cells\nvoid bfs_from_target(int tr, int tc, int dist[30][30], const bool fixed_cell[30][30]) {\n    static bool visited[30][30];\n    \n    for(int i = 0; i < N; ++i) {\n        for(int j = 0; j <= i; ++j) {\n            visited[i][j] = false;\n            dist[i][j] = 1e9;\n        }\n    }\n    \n    queue<Point> q;\n    q.push({tr, tc});\n    visited[tr][tc] = true;\n    dist[tr][tc] = 0;\n    \n    while(!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n        \n        for(int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (!is_valid(nx, ny)) continue;\n            if (visited[nx][ny]) continue;\n            if (nx < tr) continue;\n            if (nx == tr && ny < tc) continue;\n            if (fixed_cell[nx][ny]) continue;\n            \n            visited[nx][ny] = true;\n            dist[nx][ny] = dist[curr.x][curr.y] + 1;\n            q.push({nx, ny});\n        }\n    }\n}\n\n// Find path from src to target\nvector<Point> find_path(int sx, int sy, int tx, int ty, const bool fixed_cell[30][30]) {\n    static bool visited[30][30];\n    static Point parent[30][30];\n    \n    for(int i = 0; i < N; ++i) {\n        for(int j = 0; j <= i; ++j) {\n            visited[i][j] = false;\n            parent[i][j] = {-1, -1};\n        }\n    }\n    \n    queue<Point> q;\n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    \n    while(!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n        \n        if (curr.x == tx && curr.y == ty) break;\n        \n        for(int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            \n            if (!is_valid(nx, ny)) continue;\n            if (visited[nx][ny]) continue;\n            if (nx < tx) continue;\n            if (nx == tx && ny < ty) continue;\n            if (fixed_cell[nx][ny]) continue;\n            \n            visited[nx][ny] = true;\n            parent[nx][ny] = curr;\n            q.push({nx, ny});\n        }\n    }\n    \n    if (!visited[tx][ty]) return {};\n    \n    vector<Point> path;\n    Point curr = {tx, ty};\n    while (true) {\n        path.push_back(curr);\n        if (curr.x == sx && curr.y == sy) break;\n        curr = parent[curr.x][curr.y];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid move_value(int sx, int sy, int tx, int ty, bool fixed_cell[30][30]) {\n    if (sx == tx && sy == ty) return;\n    \n    bool was_fixed = fixed_cell[tx][ty];\n    fixed_cell[tx][ty] = false;\n    \n    vector<Point> path = find_path(sx, sy, tx, ty, fixed_cell);\n    \n    fixed_cell[tx][ty] = was_fixed;\n    \n    if (path.empty()) return;\n    \n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        do_swap(path[i].x, path[i].y, path[i+1].x, path[i+1].y);\n    }\n}\n\n// Hungarian algorithm for minimum cost assignment\n// cost[i][j] = cost of assigning position i to value j\nvector<int> hungarian(const vector<vector<int>>& cost) {\n    int n = cost.size();\n    if (n == 0) return {};\n    int m = cost[0].size();\n    \n    // u[i] = potential for row i, v[j] = potential for column j\n    // p[j] = row assigned to column j, way[j] = previous column in augmenting path\n    vector<int> u(n + 1, 0), v(m + 1, 0), p(m + 1, 0), way(m + 1, 0);\n    \n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(m + 1, INT_MAX);\n        vector<bool> used(m + 1, false);\n        \n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INT_MAX;\n            int j1 = 0;\n            \n            for (int j = 1; j <= m; ++j) {\n                if (!used[j]) {\n                    int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];\n                    if (cur < minv[j]) {\n                        minv[j] = cur;\n                        way[j] = j0;\n                    }\n                    if (minv[j] < delta) {\n                        delta = minv[j];\n                        j1 = j;\n                    }\n                }\n            }\n            \n            for (int j = 0; j <= m; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        \n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n    \n    // ans[i] = column assigned to row i (-1 if none)\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= m; ++j) {\n        if (p[j] > 0) {\n            ans[p[j] - 1] = j - 1;\n        }\n    }\n    return ans;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> grid[i][j];\n            pos[grid[i][j]] = {i, j};\n        }\n    }\n    \n    ops.reserve(8000);\n    \n    static bool fixed_cell[30][30];\n    static int dist[30][30];\n    memset(fixed_cell, 0, sizeof(fixed_cell));\n    \n    for (int r = 0; r < N; ++r) {\n        int row_min = r * (r + 1) / 2;\n        int row_max = (r + 1) * (r + 2) / 2 - 1;\n        int row_size = r + 1;\n        \n        vector<Point> row_positions;\n        for (int c = 0; c <= r; ++c) {\n            row_positions.push_back({r, c});\n        }\n        \n        vector<int> row_values;\n        for (int v = row_min; v <= row_max; ++v) {\n            row_values.push_back(v);\n        }\n        \n        vector<bool> pos_fixed(row_size, false);\n        vector<bool> val_used(row_size, false);\n        \n        // Phase 1: Keep values already in this row\n        for (int i = 0; i < row_size; ++i) {\n            Point p = row_positions[i];\n            int val = grid[p.x][p.y];\n            if (val >= row_min && val <= row_max) {\n                int val_idx = val - row_min;\n                if (!val_used[val_idx]) {\n                    pos_fixed[i] = true;\n                    val_used[val_idx] = true;\n                    fixed_cell[p.x][p.y] = true;\n                }\n            }\n        }\n        \n        // Collect unfixed positions and unused values\n        vector<int> free_pos_idx;\n        vector<int> free_val_idx;\n        \n        for (int i = 0; i < row_size; ++i) {\n            if (!pos_fixed[i]) free_pos_idx.push_back(i);\n        }\n        for (int j = 0; j < row_size; ++j) {\n            if (!val_used[j]) free_val_idx.push_back(j);\n        }\n        \n        if (free_pos_idx.empty()) continue;\n        \n        int n_free = free_pos_idx.size();\n        \n        // Build cost matrix: cost[i][j] = distance from value j to position i\n        vector<vector<int>> cost(n_free, vector<int>(n_free));\n        \n        for (int i = 0; i < n_free; ++i) {\n            int pos_idx = free_pos_idx[i];\n            Point target = row_positions[pos_idx];\n            \n            // Compute distances from this target\n            bfs_from_target(target.x, target.y, dist, fixed_cell);\n            \n            for (int j = 0; j < n_free; ++j) {\n                int val_idx = free_val_idx[j];\n                int v = row_values[val_idx];\n                Point src = pos[v];\n                \n                cost[i][j] = (dist[src.x][src.y] < 1e9) ? dist[src.x][src.y] : 1e8;\n            }\n        }\n        \n        // Find optimal assignment using Hungarian algorithm\n        vector<int> assignment = hungarian(cost);\n        \n        // Execute assignments in order of increasing distance\n        vector<pair<int, int>> exec_order;\n        for (int i = 0; i < n_free; ++i) {\n            if (assignment[i] >= 0) {\n                int val_idx = free_val_idx[assignment[i]];\n                int v = row_values[val_idx];\n                Point src = pos[v];\n                Point target = row_positions[free_pos_idx[i]];\n                bfs_from_target(target.x, target.y, dist, fixed_cell);\n                int d = dist[src.x][src.y];\n                exec_order.push_back({d, i});\n            }\n        }\n        sort(exec_order.begin(), exec_order.end());\n        \n        for (auto& p : exec_order) {\n            int i = p.second;\n            int pos_idx = free_pos_idx[i];\n            int val_idx = free_val_idx[assignment[i]];\n            int v = row_values[val_idx];\n            \n            Point src = pos[v];\n            Point target = row_positions[pos_idx];\n            \n            move_value(src.x, src.y, target.x, target.y, fixed_cell);\n            fixed_cell[target.x][target.y] = true;\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \" << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0;\nconst int ENTRANCE_J = 4;\n\nstruct Container {\n    int id;\n    int pi, pj;\n    bool retrieved;\n};\n\n// Check if a specific cell is reachable from entrance through empty cells\nbool isCellReachable(int ti, int tj, const vector<vector<int>>& cellContainer,\n                     const vector<vector<bool>>& obstacle) {\n    if (obstacle[ti][tj]) return false;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        if (ci == ti && cj == tj) return true;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && cellContainer[ni][nj] == -1) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return false;\n}\n\n// Check if all placed containers are reachable\nbool allContainersReachable(const vector<Container>& containers,\n                            const vector<vector<int>>& cellContainer,\n                            const vector<vector<bool>>& obstacle) {\n    for (const auto& c : containers) {\n        if (!c.retrieved && !isCellReachable(c.pi, c.pj, cellContainer, obstacle)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Get all accessible containers with their info\nvector<pair<int, int>> getAccessibleContainers(const vector<Container>& containers,\n                                                const vector<vector<int>>& cellContainer,\n                                                const vector<vector<bool>>& obstacle) {\n    vector<pair<int, int>> accessible; // (container_index, id)\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj]) {\n                visited[ni][nj] = true;\n                \n                int containerIdx = cellContainer[ni][nj];\n                \n                if (containerIdx == -1) {\n                    // Empty cell - can traverse through\n                    q.push({ni, nj});\n                } else {\n                    // Cell has a container - can retrieve but not traverse through\n                    if (!containers[containerIdx].retrieved) {\n                        accessible.push_back({containerIdx, containers[containerIdx].id});\n                    }\n                }\n            }\n        }\n    }\n    return accessible;\n}\n\n// Get all reachable empty cells from entrance\nvector<pair<int,int>> getReachableEmptyCells(const vector<vector<int>>& cellContainer,\n                                              const vector<vector<bool>>& obstacle,\n                                              const vector<vector<int>>& dist) {\n    vector<pair<int,int>> result;\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    vector<vector<bool>> visited(D, vector<bool>(D, false));\n    visited[ENTRANCE_I][ENTRANCE_J] = true;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            int ni = ci + di_arr[dir];\n            int nj = cj + dj_arr[dir];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                !visited[ni][nj] && !obstacle[ni][nj] && cellContainer[ni][nj] == -1) {\n                visited[ni][nj] = true;\n                q.push({ni, nj});\n                result.push_back({ni, nj});\n            }\n        }\n    }\n    \n    // Sort by distance (farthest first)\n    sort(result.begin(), result.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        return dist[a.first][a.second] > dist[b.first][b.second];\n    });\n    \n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    int D_val;\n    cin >> D_val >> N;\n    \n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n    \n    // Compute BFS distance from entrance for all cells\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({ENTRANCE_I, ENTRANCE_J});\n    dist[ENTRANCE_I][ENTRANCE_J] = 0;\n    \n    int di_arr[] = {-1, 0, 1, 0};\n    int dj_arr[] = {0, 1, 0, -1};\n    \n    while (!q.empty()) {\n        auto [ci, cj] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int ni = ci + di_arr[d];\n            int nj = cj + dj_arr[d];\n            \n            if (ni >= 0 && ni < D && nj >= 0 && nj < D && \n                dist[ni][nj] == -1 && !obstacle[ni][nj]) {\n                dist[ni][nj] = dist[ci][cj] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Track which cells are occupied (-1 = empty, otherwise container index)\n    vector<vector<int>> cellContainer(D, vector<int>(D, -1));\n    \n    vector<Container> containers;\n    int totalContainers = D * D - 1 - N;\n    \n    // Storage phase\n    for (int d = 0; d < totalContainers; d++) {\n        int t;\n        cin >> t;\n        \n        // Get all reachable empty cells (sorted farthest first)\n        auto reachableCells = getReachableEmptyCells(cellContainer, obstacle, dist);\n        \n        int bestI = -1, bestJ = -1;\n        \n        // Try each reachable cell, starting from farthest\n        for (auto& [ni, nj] : reachableCells) {\n            // Temporarily place container here\n            cellContainer[ni][nj] = -2; // Mark as temporarily occupied\n            \n            // Check if all existing containers remain reachable\n            bool allReachable = true;\n            for (const auto& c : containers) {\n                if (!isCellReachable(c.pi, c.pj, cellContainer, obstacle)) {\n                    allReachable = false;\n                    break;\n                }\n            }\n            \n            // Restore\n            cellContainer[ni][nj] = -1;\n            \n            if (allReachable) {\n                bestI = ni;\n                bestJ = nj;\n                break; // Take the farthest valid cell\n            }\n        }\n        \n        // Fallback: if no cell keeps all containers reachable, just take farthest reachable\n        if (bestI == -1 && !reachableCells.empty()) {\n            bestI = reachableCells[0].first;\n            bestJ = reachableCells[0].second;\n        }\n        \n        if (bestI == -1) {\n            // Last resort: any empty non-obstacle cell\n            for (int i = 0; i < D; i++) {\n                for (int j = 0; j < D; j++) {\n                    if (cellContainer[i][j] == -1 && !obstacle[i][j] && \n                        !(i == ENTRANCE_I && j == ENTRANCE_J)) {\n                        bestI = i;\n                        bestJ = j;\n                        break;\n                    }\n                }\n                if (bestI != -1) break;\n            }\n        }\n        \n        int containerIdx = containers.size();\n        containers.push_back({t, bestI, bestJ, false});\n        cellContainer[bestI][bestJ] = containerIdx;\n        cout << bestI << \" \" << bestJ << \"\\n\";\n        cout.flush();\n    }\n    \n    // Retrieval phase - pick lowest ID accessible container\n    vector<pair<int,int>> retrievalOrder;\n    \n    for (int step = 0; step < totalContainers; step++) {\n        auto accessible = getAccessibleContainers(containers, cellContainer, obstacle);\n        \n        if (accessible.empty()) {\n            cerr << \"Error: No accessible container found at step \" << step << endl;\n            return 1;\n        }\n        \n        // Sort by ID and pick lowest\n        sort(accessible.begin(), accessible.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.second < b.second;\n        });\n        \n        int bestIdx = accessible[0].first;\n        \n        containers[bestIdx].retrieved = true;\n        int ri = containers[bestIdx].pi;\n        int rj = containers[bestIdx].pj;\n        cellContainer[ri][rj] = -1; // Mark as empty now\n        retrievalOrder.push_back({ri, rj});\n    }\n    \n    // Output retrieval order\n    for (auto& [qi, qj] : retrievalOrder) {\n        cout << qi << \" \" << qj << \"\\n\";\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    // Use a 2D vector to store the grid. \n    // n=50 is small, so memory usage is negligible.\n    vector<vector<int>> grid(n, vector<int>(n));\n\n    // Read the input grid\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    // Output the grid exactly as is.\n    // Reasoning:\n    // 1. The input constraints state 1 <= c_{i,j} <= m, so there are no 0s in the input.\n    // 2. The score is (number of 0s) + 1. Since input has 0 zeros, Score = 1.\n    // 3. Score 1 is the theoretical minimum (count cannot be negative).\n    // 4. The input is guaranteed to satisfy connectivity for colors 1..m.\n    // 5. Color 0 connectivity is satisfied via the \"outside\" region (as per problem note).\n    // 6. Adjacencies are preserved because the map is identical.\n    // Thus, echoing the input is the optimal and safest strategy.\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 <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Elo-style ratings for relative weight estimation\n    vector<double> rating(N, 1000.0);\n    vector<int> comparison_count(N, 0);\n    \n    mt19937_64 rng(42);\n    \n    int queries_used = 0;\n    \n    auto update_elo = [&](int i, int j, int result) {\n        const double K = 25.0;\n        double expected_i = 1.0 / (1.0 + pow(10.0, (rating[j] - rating[i]) / 400.0));\n        double expected_j = 1.0 - expected_i;\n        \n        double actual_i, actual_j;\n        if (result < 0) {\n            actual_i = 0.0;\n            actual_j = 1.0;\n        } else if (result > 0) {\n            actual_i = 1.0;\n            actual_j = 0.0;\n        } else {\n            actual_i = 0.5;\n            actual_j = 0.5;\n        }\n        \n        rating[i] += K * (actual_i - expected_i);\n        rating[j] += K * (actual_j - expected_j);\n    };\n    \n    // Phase 1: Generate all pairs and shuffle\n    vector<pair<int, int>> all_pairs;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            all_pairs.push_back({i, j});\n        }\n    }\n    shuffle(all_pairs.begin(), all_pairs.end(), rng);\n    \n    // Execute comparisons - MUST complete exactly Q queries\n    int pair_idx = 0;\n    while (queries_used < Q) {\n        int i, j;\n        \n        if (pair_idx < (int)all_pairs.size()) {\n            i = all_pairs[pair_idx].first;\n            j = all_pairs[pair_idx].second;\n            pair_idx++;\n        } else {\n            // Ran out of unique pairs, use random pairs\n            i = rng() % N;\n            j = rng() % N;\n            if (i == j) j = (j + 1) % N;\n        }\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        comparison_count[i]++;\n        comparison_count[j]++;\n        \n        int cmp_result = 0;\n        if (result == \"<\") cmp_result = -1;\n        else if (result == \">\") cmp_result = 1;\n        \n        update_elo(i, j, cmp_result);\n    }\n    \n    // Phase 2: Convert ratings to weights\n    vector<double> weight(N);\n    double min_rating = *min_element(rating.begin(), rating.end());\n    double max_rating = *max_element(rating.begin(), rating.end());\n    double rating_range = max(1.0, max_rating - min_rating);\n    \n    for (int i = 0; i < N; i++) {\n        double normalized = (rating[i] - min_rating) / rating_range;\n        weight[i] = exp(normalized * 5.0);\n    }\n    \n    // Phase 3: Multi-way partitioning\n    // Sort items by weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return weight[a] > weight[b];\n    });\n    \n    // Greedy assignment: heaviest items to lightest groups\n    vector<double> group_weight(D, 0.0);\n    vector<int> assignment(N, 0);\n    vector<vector<int>> groups(D);\n    \n    for (int idx : indices) {\n        int best_group = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] < group_weight[best_group]) {\n                best_group = g;\n            }\n        }\n        assignment[idx] = best_group;\n        group_weight[best_group] += weight[idx];\n        groups[best_group].push_back(idx);\n    }\n    \n    // Phase 4: Local search optimization (limited iterations for speed)\n    auto calculate_variance = [&]() -> double {\n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        double variance = 0;\n        for (int g = 0; g < D; g++) {\n            variance += (group_weight[g] - mean) * (group_weight[g] - mean);\n        }\n        return variance;\n    };\n    \n    int max_iterations = 1000;\n    for (int iter = 0; iter < max_iterations; iter++) {\n        bool improved = false;\n        \n        double mean = 0;\n        for (int g = 0; g < D; g++) {\n            mean += group_weight[g];\n        }\n        mean /= D;\n        \n        // Find heaviest and lightest groups\n        int heaviest_g = 0, lightest_g = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_weight[g] > group_weight[heaviest_g]) heaviest_g = g;\n            if (group_weight[g] < group_weight[lightest_g]) lightest_g = g;\n        }\n        \n        if (heaviest_g == lightest_g) break;\n        \n        // Try moving item from heaviest to lightest\n        for (int i : groups[heaviest_g]) {\n            double new_w_h = group_weight[heaviest_g] - weight[i];\n            double new_w_l = group_weight[lightest_g] + weight[i];\n            \n            double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n            double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                (new_w_l - mean) * (new_w_l - mean);\n            \n            if (new_contrib < old_contrib - 1e-9) {\n                assignment[i] = lightest_g;\n                \n                auto it = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                groups[heaviest_g].erase(it);\n                groups[lightest_g].push_back(i);\n                \n                group_weight[heaviest_g] = new_w_h;\n                group_weight[lightest_g] = new_w_l;\n                \n                improved = true;\n                break;\n            }\n        }\n        \n        // Try swapping items\n        if (!improved && !groups[heaviest_g].empty() && !groups[lightest_g].empty()) {\n            for (int i : groups[heaviest_g]) {\n                for (int j : groups[lightest_g]) {\n                    double new_w_h = group_weight[heaviest_g] - weight[i] + weight[j];\n                    double new_w_l = group_weight[lightest_g] - weight[j] + weight[i];\n                    \n                    double old_contrib = (group_weight[heaviest_g] - mean) * (group_weight[heaviest_g] - mean) +\n                                        (group_weight[lightest_g] - mean) * (group_weight[lightest_g] - mean);\n                    double new_contrib = (new_w_h - mean) * (new_w_h - mean) +\n                                        (new_w_l - mean) * (new_w_l - mean);\n                    \n                    if (new_contrib < old_contrib - 1e-9) {\n                        assignment[i] = lightest_g;\n                        assignment[j] = heaviest_g;\n                        \n                        auto it_i = find(groups[heaviest_g].begin(), groups[heaviest_g].end(), i);\n                        auto it_j = find(groups[lightest_g].begin(), groups[lightest_g].end(), j);\n                        *it_i = j;\n                        *it_j = i;\n                        \n                        group_weight[heaviest_g] = new_w_h;\n                        group_weight[lightest_g] = new_w_l;\n                        \n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Validate all assignments are in valid range\n    for (int i = 0; i < N; i++) {\n        if (assignment[i] < 0) assignment[i] = 0;\n        if (assignment[i] >= D) assignment[i] = D - 1;\n    }\n    \n    // Output 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\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    \n    int bps = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<int> box_stack(n + 1);\n    vector<int> box_height(n + 1);\n    vector<bool> removed(n + 1, false);\n    \n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < bps; j++) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            box_stack[box] = i;\n            box_height[box] = j;\n        }\n    }\n    \n    vector<pair<int, int>> ops;\n    \n    auto update_positions = [&](int s) {\n        for (size_t i = 0; i < stacks[s].size(); i++) {\n            int b = stacks[s][i];\n            box_stack[b] = s;\n            box_height[b] = (int)i;\n        }\n    };\n    \n    // Estimate how many times a box will need to be moved before access\n    auto estimate_rehandles = [&](int box, int dest_stack, int current_target) -> int {\n        if (removed[box] || box <= current_target) return 0;\n        \n        int access_time = box - current_target;\n        int dest_size = (int)stacks[dest_stack].size();\n        \n        // Count boxes in dest stack that will be accessed before this box\n        int blocking = 0;\n        for (int b : stacks[dest_stack]) {\n            if (!removed[b] && b > current_target && b < box) {\n                blocking++;\n            }\n        }\n        \n        // Each blocking box means one extra move\n        return blocking;\n    };\n    \n    auto find_best_destination = [&](int exclude_stack, const vector<int>& moving_boxes, int current_target) -> int {\n        int best = -1;\n        long long best_score = -1000000000000LL;\n        \n        int current_empty = 0;\n        for (int i = 0; i < m; i++) {\n            if (stacks[i].empty()) current_empty++;\n        }\n        \n        for (int d = 0; d < m; d++) {\n            if (d == exclude_stack) continue;\n            \n            long long score = 0;\n            int dest_size = (int)stacks[d].size();\n            \n            // === CRITICAL: Empty stacks are extremely valuable ===\n            if (stacks[d].empty()) {\n                score += 50000000;\n                \n                // Preserve at least 1-2 empty stacks if possible\n                if (current_empty <= 2) {\n                    score -= 20000000;\n                }\n            }\n            \n            // === CRITICAL: Block detection for future targets (50 lookahead) ===\n            for (int f = current_target + 1; f <= min(current_target + 50, n); f++) {\n                if (removed[f]) continue;\n                if (box_stack[f] == d && box_height[f] >= dest_size) {\n                    int dist = f - current_target;\n                    // Closer = much heavier penalty\n                    score -= (long long)(8000000 - dist * 150000);\n                }\n            }\n            \n            // === Score moving boxes by access time ===\n            int soon_count = 0;\n            int total_rehandles = 0;\n            \n            for (int b : moving_boxes) {\n                if (removed[b]) continue;\n                \n                int access_time = b - current_target;\n                \n                if (access_time <= 5) {\n                    score -= 1000000;  // Very soon - expensive to bury\n                    soon_count++;\n                } else if (access_time <= 15) {\n                    score -= 400000;   // Soon\n                } else if (access_time <= 30) {\n                    score += 15000;    // Medium\n                } else if (access_time <= 60) {\n                    score += 30000;    // Long\n                } else {\n                    score += 50000;    // Very long - good for grouping\n                }\n                \n                // Estimate re-handling cost\n                total_rehandles += estimate_rehandles(b, d, current_target);\n            }\n            \n            // Penalty for estimated re-handling\n            score -= (long long)total_rehandles * 100000;\n            \n            // If we have soon boxes, STRONGLY prefer empty stack\n            if (soon_count > 0) {\n                if (stacks[d].empty()) {\n                    score += 5000000;\n                } else {\n                    score -= 2000000;\n                }\n            }\n            \n            // === Destination top box analysis ===\n            if (!stacks[d].empty()) {\n                int dest_top = stacks[d].back();\n                if (dest_top > current_target + 100) {\n                    score += 100000;\n                } else if (dest_top > current_target + 50) {\n                    score += 50000;\n                } else if (dest_top > current_target + 20) {\n                    score += 10000;\n                } else if (dest_top > current_target) {\n                    score -= 150000;\n                } else {\n                    score -= 800000;\n                }\n            } else {\n                // Empty stack - check if moving boxes have good access time spread\n                int min_access = n, max_access = 0;\n                for (int b : moving_boxes) {\n                    if (!removed[b]) {\n                        int access = b - current_target;\n                        min_access = min(min_access, access);\n                        max_access = max(max_access, access);\n                    }\n                }\n                if (max_access - min_access < 50) {\n                    score += 150000;  // Good grouping - similar access times\n                }\n            }\n            \n            // === Stack balance ===\n            score -= (long long)stacks[d].size() * 8000;\n            \n            // Bonus for filling smaller stacks\n            int min_nonempty = n + 1;\n            for (int i = 0; i < m; i++) {\n                if (i != exclude_stack && !stacks[i].empty()) {\n                    min_nonempty = min(min_nonempty, (int)stacks[i].size());\n                }\n            }\n            if (min_nonempty <= n && stacks[d].size() == (size_t)min_nonempty) {\n                score += 40000;\n            }\n            \n            // === Maintain workspace (softer penalties) ===\n            int would_be_empty = current_empty - (stacks[d].empty() ? 1 : 0);\n            if (would_be_empty >= 2) {\n                score += 20000;\n            } else if (would_be_empty == 0) {\n                score -= 50000;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best = d;\n            }\n        }\n        \n        if (best == -1) {\n            for (int d = 0; d < m; d++) {\n                if (d != exclude_stack) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n        \n        return best;\n    };\n    \n    for (int target = 1; target <= n; target++) {\n        if (removed[target]) continue;\n        \n        int s = box_stack[target];\n        int h = box_height[target];\n        int top = (int)stacks[s].size() - 1;\n        \n        if (h == top) {\n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        } else {\n            vector<int> moving_boxes;\n            for (int i = h + 1; i <= top; i++) {\n                moving_boxes.push_back(stacks[s][i]);\n            }\n            \n            int dest = find_best_destination(s, moving_boxes, target);\n            \n            int move_box = moving_boxes[0];\n            ops.push_back({move_box, dest + 1});\n            \n            stacks[s].resize(h + 1);\n            update_positions(s);\n            \n            for (int b : moving_boxes) {\n                stacks[dest].push_back(b);\n            }\n            update_positions(dest);\n            \n            ops.push_back({target, 0});\n            stacks[s].pop_back();\n            removed[target] = true;\n            update_positions(s);\n        }\n    }\n    \n    for (const auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n    \n    vector<vector<int>> d(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    const int DI[] = {-1, 0, 1, 0};\n    const int DJ[] = {0, 1, 0, -1};\n    const char DIR[] = {'U', 'R', 'D', 'L'};\n    \n    // Check if move is valid (no wall)\n    auto can_move = [&](int i, int j, int dir) -> bool {\n        int ni = i + DI[dir], nj = j + DJ[dir];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        \n        if (dir == 0 && i > 0 && h[i-1][j] == '1') return false;\n        if (dir == 1 && v[i][j] == '1') return false;\n        if (dir == 2 && h[i][j] == '1') return false;\n        if (dir == 3 && j > 0 && v[i][j-1] == '1') return false;\n        \n        return true;\n    };\n    \n    // BFS to find shortest path from (si,sj) to (ti,tj)\n    auto find_path = [&](int si, int sj, int ti, int tj) -> string {\n        if (si == ti && sj == tj) return \"\";\n        \n        vector<vector<int>> bd(N, vector<int>(N, -1));\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n        vector<vector<int>> pdir(N, vector<int>(N, -1));\n        queue<pair<int,int>> bq;\n        \n        bd[si][sj] = 0;\n        bq.push({si, sj});\n        \n        while (!bq.empty()) {\n            auto [i, j] = bq.front();\n            bq.pop();\n            \n            if (i == ti && j == tj) break;\n            \n            for (int dir = 0; dir < 4; dir++) {\n                if (can_move(i, j, dir)) {\n                    int ni = i + DI[dir], nj = j + DJ[dir];\n                    if (bd[ni][nj] == -1) {\n                        bd[ni][nj] = bd[i][j] + 1;\n                        parent[ni][nj] = {i, j};\n                        pdir[ni][nj] = dir;\n                        bq.push({ni, nj});\n                    }\n                }\n            }\n        }\n        \n        if (bd[ti][tj] == -1) return \"\";\n        \n        string path = \"\";\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path += DIR[pdir[ci][cj]];\n            auto [pi, pj] = parent[ci][cj];\n            ci = pi;\n            cj = pj;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    // Create priority list of squares (higher d = higher priority for revisits)\n    vector<tuple<int, int, int>> squares;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            squares.push_back({d[i][j], i, j});\n        }\n    }\n    sort(squares.rbegin(), squares.rend());\n    \n    // DFS to create initial route that visits all squares and returns to (0,0)\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string route = \"\";\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        // Sort neighbors by d value (visit high-d squares first in spanning tree)\n        vector<pair<int, int>> neighbors;\n        for (int dir = 0; dir < 4; dir++) {\n            if (can_move(i, j, dir)) {\n                int ni = i + DI[dir], nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    neighbors.push_back({d[ni][nj], dir});\n                }\n            }\n        }\n        sort(neighbors.rbegin(), neighbors.rend());\n        \n        for (auto [val, dir] : neighbors) {\n            int ni = i + DI[dir], nj = j + DJ[dir];\n            route += DIR[dir];\n            dfs(ni, nj);\n            // Return: opposite direction - this ensures we return to (i,j)\n            int opp_dir = (dir + 2) % 4;\n            route += DIR[opp_dir];\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Verify the route ends at (0,0)\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    // If not at (0,0), add return path\n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        route += back;\n    }\n    \n    // Now optimize: add revisits to high-priority squares\n    // Strategy: insert round-trips to high-d squares at strategic points\n    const int MAX_LEN = 100000;\n    \n    if ((int)route.length() < MAX_LEN - 1000) {\n        // Calculate current visit counts\n        vector<vector<int>> visit_count(N, vector<int>(N, 0));\n        int pi = 0, pj = 0;\n        visit_count[0][0]++;\n        \n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            visit_count[pi][pj]++;\n        }\n        \n        // Try to add revisits to high-priority squares\n        // We'll insert round-trips at positions where we're close to target squares\n        string optimized = route;\n        \n        // Find all positions in the route\n        vector<pair<int,int>> positions;\n        positions.push_back({0, 0});\n        pi = 0; pj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    pi += DI[dir];\n                    pj += DJ[dir];\n                    break;\n                }\n            }\n            positions.push_back({pi, pj});\n        }\n        \n        // Add revisits to top priority squares\n        for (auto [val, ti, tj] : squares) {\n            if ((int)optimized.length() >= MAX_LEN - 500) break;\n            \n            // Find the closest position in route to this square\n            int best_idx = -1;\n            int best_dist = N * N;\n            for (int idx = 0; idx < (int)positions.size(); idx++) {\n                int dist = abs(positions[idx].first - ti) + abs(positions[idx].second - tj);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_idx = idx;\n                }\n            }\n            \n            if (best_idx >= 0 && best_dist < N) {\n                // Check if we should add a revisit\n                int current_visits = visit_count[ti][tj];\n                int target_visits = max(2, (int)(val * optimized.length() / 50000));\n                \n                if (current_visits < target_visits) {\n                    // Insert a round-trip to (ti, tj) at position best_idx\n                    int pi_pos = positions[best_idx].first;\n                    int pj_pos = positions[best_idx].second;\n                    \n                    string to_target = find_path(pi_pos, pj_pos, ti, tj);\n                    string back = find_path(ti, tj, pi_pos, pj_pos);\n                    \n                    if (!to_target.empty() && !back.empty() && \n                        (int)optimized.length() + (int)to_target.length() + (int)back.length() < MAX_LEN - 100) {\n                        // Insert at position best_idx\n                        string new_route = optimized.substr(0, best_idx);\n                        new_route += to_target + back;\n                        new_route += optimized.substr(best_idx);\n                        optimized = new_route;\n                        visit_count[ti][tj]++;\n                        \n                        // Update positions (simplified - just add the detour positions)\n                        // This is approximate but should work for validation\n                    }\n                }\n            }\n        }\n        \n        route = optimized;\n    }\n    \n    // Final validation: ensure route ends at (0,0)\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        string back = find_path(ci, cj, 0, 0);\n        if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n            route += back;\n        } else {\n            // Truncate and add return path\n            route = route.substr(0, MAX_LEN - (int)back.length() - 10);\n            route += back;\n        }\n    }\n    \n    // Final validation: ensure all squares visited\n    vector<vector<bool>> final_visited(N, vector<bool>(N, false));\n    int vi = 0, vj = 0;\n    final_visited[0][0] = true;\n    \n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                vi += DI[dir];\n                vj += DJ[dir];\n                break;\n            }\n        }\n        if (vi < 0 || vi >= N || vj < 0 || vj >= N) {\n            // Invalid move - this shouldn't happen\n            cerr << \"Invalid move detected!\" << endl;\n            return 1;\n        }\n        final_visited[vi][vj] = true;\n    }\n    \n    // If any square not visited, we have a problem - but DFS should have visited all\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!final_visited[i][j]) {\n                cerr << \"Square (\" << i << \",\" << j << \") not visited!\" << endl;\n                // Try to add it if possible\n                if ((int)route.length() < MAX_LEN - 500) {\n                    string to_sq = find_path(0, 0, i, j);\n                    string back = find_path(i, j, 0, 0);\n                    if (!to_sq.empty() && !back.empty()) {\n                        route = to_sq + back + route;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure length constraint\n    if ((int)route.length() > MAX_LEN) {\n        route = route.substr(0, MAX_LEN);\n        // Re-validate end position\n        ci = 0; cj = 0;\n        for (char c : route) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == c) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n        }\n        if (ci != 0 || cj != 0) {\n            string back = find_path(ci, cj, 0, 0);\n            if ((int)route.length() + (int)back.length() <= MAX_LEN) {\n                route += back;\n            }\n        }\n    }\n    \n    // One final check\n    ci = 0; cj = 0;\n    for (char c : route) {\n        for (int dir = 0; dir < 4; dir++) {\n            if (DIR[dir] == c) {\n                ci += DI[dir];\n                cj += DJ[dir];\n                break;\n            }\n        }\n    }\n    \n    if (ci != 0 || cj != 0) {\n        // This is a critical error - truncate to make it valid\n        cerr << \"Warning: Route does not end at (0,0), truncating\" << endl;\n        // Find the last position that was at (0,0)\n        int last_zero = 0;\n        ci = 0; cj = 0;\n        for (int idx = 0; idx < (int)route.length(); idx++) {\n            for (int dir = 0; dir < 4; dir++) {\n                if (DIR[dir] == route[idx]) {\n                    ci += DI[dir];\n                    cj += DJ[dir];\n                    break;\n                }\n            }\n            if (ci == 0 && cj == 0) {\n                last_zero = idx + 1;\n            }\n        }\n        route = route.substr(0, last_zero);\n    }\n    \n    cout << route << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<string> grid;\nvector<string> targets;\nvector<vector<pair<int, int>>> char_positions;\nvector<vector<int>> overlap;\n\ninline int dist(pair<int, int> p1, pair<int, int> p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\nint calc_overlap(const string& a, const string& b) {\n    int max_ov = 0;\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = 1; len <= max_len; len++) {\n        if (a.substr(a.size() - len) == b.substr(0, len)) {\n            max_ov = len;\n        }\n    }\n    return max_ov;\n}\n\n// Build solution with look-ahead position selection\npair<string, vector<pair<int, int>>> build_solution(const vector<int>& order, int& total_cost, int lookahead = 2) {\n    string S;\n    S.reserve(1000);\n    vector<pair<int, int>> positions;\n    positions.reserve(5000);\n    pair<int, int> cur_pos = {si, sj};\n    total_cost = 0;\n    \n    for (int idx : order) {\n        const string& t = targets[idx];\n        int overlap_len = 0;\n        \n        if ((int)S.size() >= 4) {\n            for (int len = min(5, (int)S.size()); len >= 1; len--) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    if (S[S.size() - len + k] != t[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    overlap_len = len;\n                    break;\n                }\n            }\n        }\n        \n        for (int i = overlap_len; i < 5; i++) {\n            char c = t[i];\n            int c_idx = c - 'A';\n            const auto& positions_c = char_positions[c_idx];\n            \n            pair<int, int> best_pos = positions_c[0];\n            double best_score = 1e9;\n            \n            // Collect next characters for look-ahead\n            vector<int> next_chars;\n            int temp_i = i + 1;\n            int temp_idx = idx;\n            while ((int)next_chars.size() < lookahead) {\n                if (temp_i < 5) {\n                    next_chars.push_back(targets[temp_idx][temp_i] - 'A');\n                    temp_i++;\n                } else {\n                    bool found = false;\n                    for (int k = idx + 1; k < (int)order.size() && (int)next_chars.size() < lookahead; k++) {\n                        next_chars.push_back(targets[order[k]][0] - 'A');\n                        found = true;\n                        break;\n                    }\n                    if (!found) break;\n                }\n            }\n            \n            for (auto& pos : positions_c) {\n                double score = dist(cur_pos, pos);\n                \n                pair<int, int> prev_pos = pos;\n                for (size_t k = 0; k < next_chars.size(); k++) {\n                    int next_c = next_chars[k];\n                    int min_d = INT_MAX;\n                    pair<int, int> best_next = char_positions[next_c][0];\n                    for (auto& np : char_positions[next_c]) {\n                        int d = dist(prev_pos, np);\n                        if (d < min_d) {\n                            min_d = d;\n                            best_next = np;\n                        }\n                    }\n                    score += min_d * (1.0 / (k + 1));\n                    prev_pos = best_next;\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_pos = pos;\n                }\n            }\n            \n            total_cost += dist(cur_pos, best_pos) + 1;\n            positions.push_back(best_pos);\n            S += c;\n            cur_pos = best_pos;\n        }\n    }\n    \n    return {S, positions};\n}\n\ninline bool check_coverage(const string& S) {\n    for (int i = 0; i < M; i++) {\n        if (S.find(targets[i]) == string::npos) return false;\n    }\n    return true;\n}\n\nvector<int> build_greedy_order(mt19937& rng, bool randomize = false, int start_override = -1) {\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    \n    uniform_int_distribution<int> dist_int(0, M - 1);\n    int start = (start_override >= 0) ? (start_override % M) : (randomize ? dist_int(rng) : 0);\n    \n    order.push_back(start);\n    used[start] = true;\n    \n    for (int step = 1; step < M; step++) {\n        int last = order.back();\n        vector<pair<int, int>> candidates;\n        candidates.reserve(M - step);\n        \n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                candidates.push_back({overlap[last][i], i});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first > b.first;\n        });\n        \n        int top_k = randomize ? min((int)candidates.size(), 30) : 1;\n        uniform_int_distribution<int> pick_dist(0, top_k - 1);\n        int pick_idx = randomize ? pick_dist(rng) : 0;\n        int best_next = candidates[pick_idx].second;\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\n// Weighted swap candidate selection based on overlap deficit\nint select_swap_position(const vector<int>& order, mt19937& rng) {\n    uniform_int_distribution<int> uniform_dist(0, M - 2);\n    \n    // 50% chance: weighted by low overlap\n    // 50% chance: uniform random\n    if (rng() % 2 == 0) {\n        vector<pair<int, int>> weighted;\n        weighted.reserve(M - 1);\n        for (int i = 0; i < M - 1; i++) {\n            int weight = 5 - overlap[order[i]][order[i + 1]];  // Lower overlap = higher weight\n            weight = max(1, weight);\n            for (int w = 0; w < weight; w++) {\n                weighted.push_back({i, weight});\n            }\n        }\n        if (!weighted.empty()) {\n            uniform_int_distribution<int> w_dist(0, weighted.size() - 1);\n            return weighted[w_dist(rng)].first;\n        }\n    }\n    return uniform_dist(rng);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    grid.resize(N);\n    char_positions.resize(26);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> grid[i];\n        for (int j = 0; j < N; j++) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> targets[i];\n    }\n    \n    overlap.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) {\n                overlap[i][j] = calc_overlap(targets[i], targets[j]);\n            }\n        }\n    }\n    \n    auto get_elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> best_order;\n    vector<pair<int, int>> best_positions;\n    int best_cost = INT_MAX;\n    bool best_valid = false;\n    \n    // Phase 1: Generate diverse initial solutions (0-300ms)\n    int trial = 0;\n    while (get_elapsed_ms() < 300) {\n        bool randomize = (trial % 2 != 0);\n        vector<int> order = build_greedy_order(rng, randomize, trial);\n        \n        int cost;\n        auto [S, positions] = build_solution(order, cost, 2);\n        bool valid = check_coverage(S) && (int)positions.size() <= 5000;\n        \n        if (valid && cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n            best_positions = positions;\n            best_valid = true;\n        } else if (!best_valid && (int)positions.size() <= 5000) {\n            best_cost = cost;\n            best_order = order;\n            best_positions = positions;\n        }\n        trial++;\n    }\n    \n    // Phase 2: Aggressive adjacent swap local search (300-900ms) - MAIN OPTIMIZATION\n    if (best_valid) {\n        int no_improve_count = 0;\n        \n        while (get_elapsed_ms() < 900 && no_improve_count < 10) {\n            bool improved = false;\n            \n            for (int iter = 0; iter < 500 && get_elapsed_ms() < 900; iter++) {\n                int i = select_swap_position(best_order, rng);\n                \n                vector<int> new_order = best_order;\n                swap(new_order[i], new_order[i + 1]);\n                \n                int cost;\n                auto [S, positions] = build_solution(new_order, cost, 2);\n                \n                if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                    improved = true;\n                    no_improve_count = 0;\n                }\n            }\n            \n            if (!improved) no_improve_count++;\n        }\n    }\n    \n    // Phase 3: Wide 2-opt local search (900-1350ms)\n    if (best_valid) {\n        while (get_elapsed_ms() < 1350) {\n            bool improved = false;\n            \n            for (int i = 0; i < M - 2 && get_elapsed_ms() < 1350; i++) {\n                // Try wider range\n                for (int j = i + 2; j < min(i + 50, M); j++) {\n                    vector<int> new_order = best_order;\n                    reverse(new_order.begin() + i + 1, new_order.begin() + j + 1);\n                    \n                    int cost;\n                    auto [S, positions] = build_solution(new_order, cost, 2);\n                    \n                    if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost - 3) {\n                        best_cost = cost;\n                        best_order = new_order;\n                        best_positions = positions;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Phase 4: Simulated annealing with tighter parameters (1350-1750ms)\n    if (best_valid) {\n        double temperature = best_cost * 0.15;  // Lower starting temp\n        double cooling_rate = 0.9998;  // Slower cooling\n        uniform_real_distribution<double> dist_real(0.0, 1.0);\n        \n        vector<int> current_order = best_order;\n        int current_cost = best_cost;\n        \n        while (get_elapsed_ms() < 1750) {\n            int i = select_swap_position(current_order, rng);\n            int j = i + 1 + (rng() % min(20, M - i - 1));\n            j = min(j, M - 1);\n            \n            vector<int> new_order = current_order;\n            swap(new_order[i], new_order[j]);\n            \n            int cost;\n            auto [S, positions] = build_solution(new_order, cost, 2);\n            \n            bool accept = false;\n            if ((int)positions.size() <= 5000 && check_coverage(S)) {\n                if (cost < current_cost) {\n                    accept = true;\n                } else if (temperature > 20) {\n                    double delta = (double)(cost - current_cost);\n                    double prob = exp(-delta / temperature);\n                    if (dist_real(rng) < prob) {\n                        accept = true;\n                    }\n                }\n            }\n            \n            if (accept) {\n                current_order = new_order;\n                current_cost = cost;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    auto [S2, positions2] = build_solution(best_order, best_cost, 3);\n                    best_positions = positions2;\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n    }\n    \n    // Phase 5: Final intensive hill climbing (1750-1950ms)\n    if (best_valid && get_elapsed_ms() < 1950) {\n        uniform_int_distribution<int> swap_dist(0, M - 2);\n        \n        while (get_elapsed_ms() < 1950) {\n            bool improved = false;\n            \n            for (int iter = 0; iter < 300 && get_elapsed_ms() < 1950; iter++) {\n                // Mix of adjacent and distant swaps\n                int i, j;\n                if (rng() % 3 == 0) {\n                    // Distant swap\n                    i = swap_dist(rng);\n                    j = swap_dist(rng);\n                    if (i > j) swap(i, j);\n                    if (i == j) continue;\n                } else {\n                    // Adjacent swap (more productive)\n                    i = select_swap_position(best_order, rng);\n                    j = i + 1;\n                }\n                \n                vector<int> new_order = best_order;\n                swap(new_order[i], new_order[j]);\n                \n                int cost;\n                auto [S, positions] = build_solution(new_order, cost, 2);\n                \n                if ((int)positions.size() <= 5000 && check_coverage(S) && cost < best_cost) {\n                    best_cost = cost;\n                    best_order = new_order;\n                    best_positions = positions;\n                    improved = true;\n                }\n            }\n            \n            if (!improved) break;\n        }\n    }\n    \n    // Final rebuild with best look-ahead\n    if (best_valid) {\n        int cost;\n        auto [S, positions] = build_solution(best_order, cost, 3);\n        best_positions = positions;\n    }\n    \n    // Fallback\n    if (best_positions.empty()) {\n        pair<int, int> cur_pos = {si, sj};\n        for (int i = 0; i < M; i++) {\n            for (char c : targets[i]) {\n                int c_idx = c - 'A';\n                pair<int, int> best_pos = char_positions[c_idx][0];\n                for (auto& pos : char_positions[c_idx]) {\n                    if (dist(cur_pos, pos) < dist(cur_pos, best_pos)) {\n                        best_pos = pos;\n                    }\n                }\n                best_positions.push_back(best_pos);\n                cur_pos = best_pos;\n            }\n        }\n    }\n    \n    for (auto& p : best_positions) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    int N, M;\n    double eps;\n    \n    // Read input\n    cin >> N >> M >> eps;\n    \n    vector<vector<pair<int, int> > > shapes(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; ++i) {\n            cin >> shapes[k][i].first >> shapes[k][i].second;\n        }\n    }\n    \n    // Simple strategy: drill every square\n    vector<pair<int, int> > oil_cells;\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                oil_cells.push_back(make_pair(i, j));\n            }\n        }\n    }\n    \n    // Output answer\n    cout << \"a \" << (int)oil_cells.size();\n    for (size_t i = 0; i < oil_cells.size(); ++i) {\n        cout << \" \" << oil_cells[i].first << \" \" << oil_cells[i].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 <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Global constants\nconst int W = 1000;\n\n// Problem data\nint D, N;\nvector<vector<int>> a; // a[d][k]\n\n// Grid dimensions\nint R, C;\n\n// State: H[d][r], W[d][c]\n// Using vector of vectors\nvector<vector<int>> H;\nvector<vector<int>> W_vec; // Renamed to W_vec to avoid conflict with constant W\n\n// Mapping from k to (r, c)\npair<int, int> get_rc(int k) {\n    return {k / C, k % C};\n}\n\n// Calculate total cost\nlong long calculate_cost() {\n    long long total_cost = 0;\n    \n    // Area costs\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                total_cost += 100LL * (a[d][k] - area);\n            }\n        }\n    }\n    \n    // Partition costs\n    for (int d = 1; d < D; ++d) {\n        // Horizontal lines\n        int y_prev = 0;\n        int y_curr = 0;\n        for (int r = 0; r < R; ++r) {\n            y_prev += H[d-1][r];\n            y_curr += H[d][r];\n            total_cost += (long long)W * abs(y_prev - y_curr);\n        }\n        // Vertical lines\n        int x_prev = 0;\n        int x_curr = 0;\n        for (int c = 0; c < C; ++c) {\n            x_prev += W_vec[d-1][c];\n            x_curr += W_vec[d][c];\n            total_cost += (long long)W * abs(x_prev - x_curr);\n        }\n    }\n    \n    return total_cost;\n}\n\n// Calculate delta cost for a change in H[d][r] or W_vec[d][c]\n// This is more efficient for SA\nlong long calculate_delta_cost(int d, int type, int idx, int delta) {\n    // type 0: H, 1: W_vec\n    long long delta_cost = 0;\n    \n    // Area cost change for day d\n    if (type == 0) { // H[d][idx] changes by delta\n        int r = idx;\n        int old_h = H[d][r];\n        int new_h = old_h + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kr == r) {\n                long long old_area = (long long)old_h * W_vec[d][kc];\n                long long new_area = (long long)new_h * W_vec[d][kc];\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    } else { // W_vec[d][idx] changes by delta\n        int c = idx;\n        int old_w = W_vec[d][c];\n        int new_w = old_w + delta;\n        for (int k = 0; k < N; ++k) {\n            auto [kr, kc] = get_rc(k);\n            if (kc == c) {\n                long long old_area = (long long)H[d][kr] * old_w;\n                long long new_area = (long long)H[d][kr] * new_w;\n                long long old_pen = 0, new_pen = 0;\n                if (old_area < a[d][k]) old_pen = 100LL * (a[d][k] - old_area);\n                if (new_area < a[d][k]) new_pen = 100LL * (a[d][k] - new_area);\n                delta_cost += (new_pen - old_pen);\n            }\n        }\n    }\n    \n    // Partition cost change\n    // Affected days: d (with d-1) and d+1 (with d)\n    // If d=0, only d+1. But L_0=0, so partition cost starts from d=1.\n    // Partition cost between d-1 and d depends on cumulative sums at d-1 and d.\n    // Changing H[d][idx] changes cumulative sums for r >= idx on day d.\n    \n    auto update_partition = [&](int day_idx, int type_p, int idx_p, int delta_p) {\n        // day_idx is the day being modified (d)\n        // We need to compare with day_idx-1 and day_idx+1\n        long long cost_change = 0;\n        \n        // Compare with day_idx - 1\n        if (day_idx > 0) {\n            int sum_prev = 0;\n            int sum_curr = 0;\n            // We only need to sum from idx_p to end because before idx_p sums are same\n            // But wait, cumulative sum at r depends on H[0]...H[r].\n            // If H[idx] changes, all cumulative sums Y_r for r > idx change.\n            // Y_idx also changes.\n            // So for all r from idx to R-1, Y_r changes by delta_p.\n            // Cost adds W * |delta_p| for each such line.\n            // Number of lines affected: R - idx_p.\n            // Wait, lines are at Y_1, ..., Y_R.\n            // Y_r = sum(H[0]...H[r-1]).\n            // If H[idx] changes, Y_r changes for r > idx.\n            // So lines Y_{idx+1} ... Y_R change.\n            // Count = R - idx.\n            // But Y_R is at W (fixed sum), so Y_R doesn't change?\n            // We enforce sum H = W. So if H[idx] += delta, some H[other] -= delta.\n            // So Y_R remains W.\n            // So lines affected are those between idx and the 'other' index.\n            // This makes delta calculation complex if we swap.\n            // Let's stick to full cost recalc for partition if needed, or simplify.\n            // Given N is small, full partition cost recalc for affected days is fast.\n            // Affected days: d-1 (boundary d-1|d) and d (boundary d|d+1).\n            // Just recalc partition cost for these two boundaries.\n        }\n        return cost_change;\n    };\n\n    // Simpler approach: Recalculate partition cost for boundaries involving day d.\n    // Boundaries: (d-1, d) and (d, d+1).\n    // Store previous partition cost for these boundaries to subtract.\n    // But implementing this cleanly is verbose.\n    // Given the speed of O(N) area calc, O(R+C) partition calc is also fast.\n    // Let's just calculate the delta for partition explicitly.\n    \n    // Partition cost contribution of day d with d-1:\n    // Sum_r W * |Y_{d,r} - Y_{d-1,r}|\n    // If H[d][idx] changes by delta, Y_{d,r} changes by delta for r > idx.\n    // (Assuming we adjust another H[d][other] to keep sum constant).\n    // If we do swap move (H[idx]+=1, H[other]-=1), then Y_r changes by 1 for r in (min, max].\n    // This is getting complicated for delta.\n    // Given 3 seconds, we can afford O(R+C) per step.\n    // Let's implement a function that recalculates partition cost for day d boundaries.\n    \n    return delta_cost; // Placeholder, will implement full delta in SA loop or use full cost for safety if fast enough\n}\n\n// Function to calculate partition cost between day d1 and d2\nlong long calc_partition_between(int d1, int d2) {\n    long long cost = 0;\n    int y1 = 0, y2 = 0;\n    for (int r = 0; r < R; ++r) {\n        y1 += H[d1][r];\n        y2 += H[d2][r];\n        cost += (long long)W * abs(y1 - y2);\n    }\n    int x1 = 0, x2 = 0;\n    for (int c = 0; c < C; ++c) {\n        x1 += W_vec[d1][c];\n        x2 += W_vec[d2][c];\n        cost += (long long)W * abs(x1 - x2);\n    }\n    return cost;\n}\n\n// Global current cost\nlong long current_cost = 0;\n\nvoid update_cost_after_change(int d, const vector<int>& old_H, const vector<int>& old_W) {\n    // Recompute area cost for day d\n    // Recompute partition cost for (d-1, d) and (d, d+1)\n    // This is O(N + R + C).\n    \n    // We need to subtract old contributions and add new.\n    // To do this cleanly, we need to store per-day costs.\n    // Let's store vector<long long> area_cost(D), partition_cost(D) (cost between d-1 and d)\n    // partition_cost[0] = 0.\n    // Total = sum(area) + sum(partition).\n}\n\n// Let's use a simpler SA structure where we just recompute necessary parts.\n// Since D is small, we can store per-day area cost and per-boundary partition cost.\nvector<long long> day_area_cost;\nvector<long long> boundary_part_cost; // size D, boundary_part_cost[d] is cost between d-1 and d. [0] is 0.\n\nvoid init_costs() {\n    day_area_cost.assign(D, 0);\n    boundary_part_cost.assign(D, 0);\n    \n    for (int d = 0; d < D; ++d) {\n        long long cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                cost += 100LL * (a[d][k] - area);\n            }\n        }\n        day_area_cost[d] = cost;\n    }\n    \n    for (int d = 1; d < D; ++d) {\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n    }\n    \n    current_cost = 0;\n    for (long long c : day_area_cost) current_cost += c;\n    for (long long c : boundary_part_cost) current_cost += c;\n}\n\nvoid apply_move_and_update(int d, int type, int idx, int delta) {\n    // Apply move\n    if (type == 0) {\n        H[d][idx] += delta;\n    } else {\n        W_vec[d][idx] += delta;\n    }\n    \n    // Update day_area_cost[d]\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    // Update boundary_part_cost[d] (between d-1 and d)\n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    // Update boundary_part_cost[d+1] (between d and d+1)\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nvoid revert_move_and_update(int d, int type, int idx, int delta) {\n    // Revert\n    if (type == 0) {\n        H[d][idx] -= delta;\n    } else {\n        W_vec[d][idx] -= delta;\n    }\n    \n    // Recalculate costs (same as apply, effectively undoing the change in values)\n    long long new_area_cost = 0;\n    for (int k = 0; k < N; ++k) {\n        auto [r, c] = get_rc(k);\n        long long area = (long long)H[d][r] * W_vec[d][c];\n        if (area < a[d][k]) {\n            new_area_cost += 100LL * (a[d][k] - area);\n        }\n    }\n    current_cost -= day_area_cost[d];\n    day_area_cost[d] = new_area_cost;\n    current_cost += day_area_cost[d];\n    \n    if (d > 0) {\n        current_cost -= boundary_part_cost[d];\n        boundary_part_cost[d] = calc_partition_between(d-1, d);\n        current_cost += boundary_part_cost[d];\n    }\n    if (d < D - 1) {\n        current_cost -= boundary_part_cost[d+1];\n        boundary_part_cost[d+1] = calc_partition_between(d, d+1);\n        current_cost += boundary_part_cost[d+1];\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int W_in;\n    if (!(cin >> W_in >> D >> N)) return 0;\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    // Determine R, C\n    // Try to find R that minimizes initial area cost heuristic\n    int best_R = 1;\n    long long min_init_cost = -1;\n    \n    for (int r_try = 1; r_try <= N; ++r_try) {\n        int c_try = (N + r_try - 1) / r_try;\n        // Heuristic cost estimate\n        // Distribute W to rows/cols based on sqrt(area)\n        long long est_cost = 0;\n        // Just pick the one closest to square\n        if (min_init_cost == -1 || abs(r_try - c_try) < abs(best_R - (N + best_R - 1) / best_R)) {\n             best_R = r_try;\n        }\n    }\n    // Prefer square-ish\n    best_R = max(1, (int)round(sqrt(N)));\n    R = best_R;\n    C = (N + R - 1) / R;\n    \n    // Initialize H and W_vec\n    H.assign(D, vector<int>(R));\n    W_vec.assign(D, vector<int>(C));\n    \n    mt19937 rng(12345);\n    \n    for (int d = 0; d < D; ++d) {\n        // Calculate target \"weight\" for each row and col\n        vector<long long> row_weight(R, 0);\n        vector<long long> col_weight(C, 0);\n        \n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            // Use sqrt of area as weight\n            long long w = (long long)sqrt(a[d][k]) + 1;\n            row_weight[r] += w;\n            col_weight[c] += w;\n        }\n        \n        long long sum_rw = accumulate(row_weight.begin(), row_weight.end(), 0LL);\n        long long sum_cw = accumulate(col_weight.begin(), col_weight.end(), 0LL);\n        \n        // Distribute W\n        int rem_h = W;\n        for (int r = 0; r < R; ++r) {\n            int h = (sum_rw == 0) ? W/R : (int)((double)row_weight[r] / sum_rw * W);\n            H[d][r] = h;\n            rem_h -= h;\n        }\n        // Distribute remainder\n        int r_idx = 0;\n        while (rem_h > 0) {\n            H[d][r_idx % R]++;\n            rem_h--;\n            r_idx++;\n        }\n        // Ensure min 1\n        for(int r=0; r<R; ++r) if(H[d][r] < 1) H[d][r] = 1;\n        // Re-normalize sum to W (simple adjust)\n        int sum_h = accumulate(H[d].begin(), H[d].end(), 0);\n        if (sum_h != W) {\n            H[d][0] += (W - sum_h);\n        }\n        \n        int rem_w = W;\n        for (int c = 0; c < C; ++c) {\n            int w = (sum_cw == 0) ? W/C : (int)((double)col_weight[c] / sum_cw * W);\n            W_vec[d][c] = w;\n            rem_w -= w;\n        }\n        int c_idx = 0;\n        while (rem_w > 0) {\n            W_vec[d][c_idx % C]++;\n            rem_w--;\n            c_idx++;\n        }\n        for(int c=0; c<C; ++c) if(W_vec[d][c] < 1) W_vec[d][c] = 1;\n        int sum_w = accumulate(W_vec[d].begin(), W_vec[d].end(), 0);\n        if (sum_w != W) {\n            W_vec[d][0] += (W - sum_w);\n        }\n    }\n    \n    init_costs();\n    \n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double T = 10000.0;\n    double T_end = 1.0;\n    double alpha = 0.99995;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break; // Leave margin\n        \n        // Pick move\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        int type = uniform_int_distribution<int>(0, 1)(rng); // 0: H, 1: W\n        int dim = (type == 0) ? R : C;\n        int idx = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        // Pick another index to swap with to maintain sum\n        int idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        while (idx2 == idx) idx2 = uniform_int_distribution<int>(0, dim-1)(rng);\n        \n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 1)(rng)) delta = -1;\n        \n        // Check validity (must be >= 1)\n        if (type == 0) {\n            if (H[d][idx] + delta < 1 || H[d][idx2] - delta < 1) continue;\n        } else {\n            if (W_vec[d][idx] + delta < 1 || W_vec[d][idx2] - delta < 1) continue;\n        }\n        \n        // Apply first change\n        if (type == 0) H[d][idx] += delta;\n        else W_vec[d][idx] += delta;\n        \n        // Calculate cost delta roughly? \n        // No, let's just apply both and calc cost.\n        if (type == 0) H[d][idx2] -= delta;\n        else W_vec[d][idx2] -= delta;\n        \n        // We need to calculate new cost efficiently.\n        // Since we changed two indices, we can just recompute day_area_cost[d] and boundaries.\n        // Store old values to revert if rejected.\n        int old_val1 = (type == 0) ? H[d][idx] - delta : W_vec[d][idx] - delta;\n        int old_val2 = (type == 0) ? H[d][idx2] + delta : W_vec[d][idx2] + delta;\n        \n        long long old_day_cost = day_area_cost[d];\n        long long old_bound1 = (d > 0) ? boundary_part_cost[d] : 0;\n        long long old_bound2 = (d < D-1) ? boundary_part_cost[d+1] : 0;\n        \n        // Recompute area cost\n        long long new_area_cost = 0;\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            long long area = (long long)H[d][r] * W_vec[d][c];\n            if (area < a[d][k]) {\n                new_area_cost += 100LL * (a[d][k] - area);\n            }\n        }\n        \n        long long new_bound1 = 0, new_bound2 = 0;\n        if (d > 0) new_bound1 = calc_partition_between(d-1, d);\n        if (d < D-1) new_bound2 = calc_partition_between(d, d+1);\n        \n        long long delta_E = (new_area_cost - old_day_cost) + (new_bound1 - old_bound1) + (new_bound2 - old_bound2);\n        \n        bool accept = false;\n        if (delta_E <= 0) accept = true;\n        else {\n            double p = exp(-delta_E / T);\n            if (uniform_real_distribution<double>(0, 1)(rng) < p) accept = true;\n        }\n        \n        if (accept) {\n            current_cost += delta_E;\n            day_area_cost[d] = new_area_cost;\n            if (d > 0) boundary_part_cost[d] = new_bound1;\n            if (d < D-1) boundary_part_cost[d+1] = new_bound2;\n        } else {\n            // Revert\n            if (type == 0) {\n                H[d][idx] = old_val1;\n                H[d][idx2] = old_val2;\n            } else {\n                W_vec[d][idx] = old_val1;\n                W_vec[d][idx2] = old_val2;\n            }\n        }\n        \n        T *= alpha;\n        iter++;\n    }\n    \n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [r, c] = get_rc(k);\n            int i_start = 0;\n            for (int i = 0; i < r; ++i) i_start += H[d][i];\n            int i_end = i_start + H[d][r];\n            \n            int j_start = 0;\n            for (int j = 0; j < c; ++j) j_start += W_vec[d][j];\n            int j_end = j_start + W_vec[d][c];\n            \n            cout << i_start << \" \" << j_start << \" \" << i_end << \" \" << j_end << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\nusing ll = long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int STAMP_SIZE = 3;\nconst int POS_LIMIT = 7;\n\nll A[N][N];\nll S[M][STAMP_SIZE][STAMP_SIZE];\nll Grid[N][N];\nll GridMod[N][N];\nll CurrentScore = 0;\n\nstruct Op {\n    uint8_t m, p, q;\n};\n\nstruct FastRNG {\n    uint64_t state;\n    FastRNG(uint64_t seed) : state(seed) {}\n    uint64_t next() {\n        state ^= state << 13;\n        state ^= state >> 7;\n        state ^= state << 17;\n        return state;\n    }\n    int nextInt(int max) { return next() % max; }\n    double nextDouble() { return (next() >> 11) * (1.0 / (uint64_t(1) << 53)); }\n};\n\ninline ll get_mod(ll v) {\n    ll r = v % MOD;\n    return r < 0 ? r + MOD : r;\n}\n\ninline ll calc_delta(int m, int p, int q, int delta) {\n    ll change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            ll new_val = Grid[r][c] + delta * S[m][i][j];\n            change += get_mod(new_val) - GridMod[r][c];\n        }\n    }\n    return change;\n}\n\ninline void apply_op(int m, int p, int q, int delta) {\n    ll score_change = 0;\n    for (int i = 0; i < STAMP_SIZE; ++i) {\n        for (int j = 0; j < STAMP_SIZE; ++j) {\n            int r = p + i, c = q + j;\n            Grid[r][c] += delta * S[m][i][j];\n            ll old_mod = GridMod[r][c];\n            GridMod[r][c] = get_mod(Grid[r][c]);\n            score_change += GridMod[r][c] - old_mod;\n        }\n    }\n    CurrentScore += score_change;\n}\n\nvoid init_grid() {\n    CurrentScore = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Grid[i][j] = A[i][j];\n            GridMod[i][j] = get_mod(A[i][j]);\n            CurrentScore += GridMod[i][j];\n        }\n    }\n}\n\nll run_sa(uint64_t seed, double time_limit, vector<Op>& ops) {\n    FastRNG rng(seed);\n    init_grid();\n    ops.clear();\n    \n    // Greedy initialization\n    for (int step = 0; step < K; ++step) {\n        ll best_delta = 0;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < POS_LIMIT; ++p) {\n                for (int q = 0; q < POS_LIMIT; ++q) {\n                    ll d = calc_delta(m, p, q, 1);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_m = m; best_p = p; best_q = q;\n                    }\n                }\n            }\n        }\n        \n        if (best_delta <= 0) break;\n        apply_op(best_m, best_p, best_q, 1);\n        ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n    }\n    \n    ll best_score = CurrentScore;\n    vector<Op> best_ops = ops;\n    \n    auto start = chrono::steady_clock::now();\n    ll T_start = 1000000000LL;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        double progress = elapsed / time_limit;\n        ll T = (ll)(T_start * exp(-progress * 6.0));\n        if (T < 100) T = 100;\n        \n        int move = rng.nextInt(100);\n        \n        if (ops.empty()) {\n            int m = rng.nextInt(M);\n            int p = rng.nextInt(POS_LIMIT);\n            int q = rng.nextInt(POS_LIMIT);\n            ll delta = calc_delta(m, p, q, 1);\n            if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                apply_op(m, p, q, 1);\n                ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        } else if (ops.size() >= K) {\n            if (move < 70) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        } else {\n            if (move < 50) {\n                // Change\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                \n                ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    apply_op(m, p, q, 1);\n                    ops[idx] = {(uint8_t)m, (uint8_t)p, (uint8_t)q};\n                }\n            } else if (move < 80) {\n                // Add\n                int m = rng.nextInt(M);\n                int p = rng.nextInt(POS_LIMIT);\n                int q = rng.nextInt(POS_LIMIT);\n                ll delta = calc_delta(m, p, q, 1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(m, p, q, 1);\n                    ops.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n                }\n            } else {\n                // Remove\n                int idx = rng.nextInt(ops.size());\n                Op old = ops[idx];\n                ll delta = calc_delta(old.m, old.p, old.q, -1);\n                if (delta > 0 || rng.nextDouble() < exp((double)delta / T)) {\n                    apply_op(old.m, old.p, old.q, -1);\n                    ops[idx] = ops.back();\n                    ops.pop_back();\n                }\n            }\n        }\n        \n        if (CurrentScore > best_score) {\n            best_score = CurrentScore;\n            best_ops = ops;\n        }\n    }\n    \n    ops = best_ops;\n    return best_score;\n}\n\nvoid final_refine(vector<Op>& ops, double time_limit) {\n    auto start = chrono::steady_clock::now();\n    \n    // Initialize grid with current operations ONCE\n    init_grid();\n    for (const auto& op : ops) {\n        apply_op(op.m, op.p, op.q, 1);\n    }\n    \n    // Single continuous refinement loop (no grid reset!)\n    bool improved = true;\n    while (improved) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed >= time_limit) break;\n        \n        improved = false;\n        \n        ll best_delta = 0;\n        int best_type = -1, best_idx = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n        \n        // Try ALL changes\n        for (int idx = 0; idx < (int)ops.size(); ++idx) {\n            Op old = ops[idx];\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < POS_LIMIT; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        if (m == old.m && p == old.p && q == old.q) continue;\n                        ll delta = calc_delta(m, p, q, 1) + calc_delta(old.m, old.p, old.q, -1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 0;\n                            best_idx = idx;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try removes\n        for (int idx = 0; idx < (int)ops.size(); ++idx) {\n            Op old = ops[idx];\n            ll delta = calc_delta(old.m, old.p, old.q, -1);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_type = 1;\n                best_idx = idx;\n            }\n        }\n        \n        // Try adds\n        if (ops.size() < K) {\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < POS_LIMIT; ++p) {\n                    for (int q = 0; q < POS_LIMIT; ++q) {\n                        ll delta = calc_delta(m, p, q, 1);\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_type = 2;\n                            best_m = m; best_p = p; best_q = q;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (best_delta > 0) {\n            improved = true;\n            if (best_type == 0) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                apply_op(best_m, best_p, best_q, 1);\n                ops[best_idx] = {(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q};\n            } else if (best_type == 1) {\n                Op old = ops[best_idx];\n                apply_op(old.m, old.p, old.q, -1);\n                ops[best_idx] = ops.back();\n                ops.pop_back();\n            } else {\n                apply_op(best_m, best_p, best_q, 1);\n                ops.push_back({(uint8_t)best_m, (uint8_t)best_p, (uint8_t)best_q});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, m_in, k_in;\n    cin >> n_in >> m_in >> k_in;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    for (int m = 0; m < M; ++m)\n        for (int i = 0; i < STAMP_SIZE; ++i)\n            for (int j = 0; j < STAMP_SIZE; ++j)\n                cin >> S[m][i][j];\n\n    vector<Op> best_ops;\n    ll best_score = 0;\n    \n    // 3 SA runs @ 0.55s each = 1.65s\n    double sa_time = 0.55;\n    for (int run = 0; run < 3; ++run) {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + run * 1000000 + run * 12345;\n        vector<Op> ops;\n        ll score = run_sa(seed, sa_time, ops);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n    \n    // Final refinement @ 0.30s (continuous, no reset)\n    final_refine(best_ops, 0.30);\n    \n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << (int)op.m << \" \" << (int)op.p << \" \" << (int)op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dchar[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int id;\n    int r, c;\n    int holding;\n    bool is_large;\n};\n\nclass Solver {\n    int grid[N][N];\n    Crane cranes[N];\n    vector<int> inputs[N];\n    int input_idx[N];\n    int next_dispatch[N];\n    int total_dispatched;\n    vector<string> ans;\n    int turn;\n\npublic:\n    Solver(const vector<vector<int>>& A) {\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) grid[i][j] = -1;\n            cranes[i].id = i;\n            cranes[i].r = i;\n            cranes[i].c = 0;\n            cranes[i].holding = -1;\n            cranes[i].is_large = (i == 0);\n            input_idx[i] = 0;\n            next_dispatch[i] = i * N;\n            for(int j=0; j<N; ++j) inputs[i].push_back(A[i][j]);\n        }\n        total_dispatched = 0;\n        turn = 0;\n        ans.resize(N);\n    }\n\n    void receive_containers() {\n        for(int i=0; i<N; ++i) {\n            if(input_idx[i] < N) {\n                bool has_container = (grid[i][0] != -1);\n                bool crane_holding = false;\n                for(int k=0; k<N; ++k) {\n                    if(cranes[k].r == i && cranes[k].c == 0 && cranes[k].holding != -1) {\n                        crane_holding = true;\n                        break;\n                    }\n                }\n                if(!has_container && !crane_holding) {\n                    grid[i][0] = inputs[i][input_idx[i]];\n                    input_idx[i]++;\n                }\n            }\n        }\n    }\n\n    void dispatch_containers() {\n        for(int i=0; i<N; ++i) {\n            if(grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                grid[i][N-1] = -1;\n                total_dispatched++;\n                if(cid == next_dispatch[i]) {\n                    next_dispatch[i]++;\n                }\n            }\n        }\n    }\n\n    bool can_move(int crane_idx, int nr, int nc, const vector<pair<int,int>>& next_pos) {\n        if(nr < 0 || nr >= N || nc < 0 || nc >= N) return false;\n        for(int k=0; k<crane_idx; ++k) {\n            if(next_pos[k].first == nr && next_pos[k].second == nc) return false;\n            if(next_pos[k].first == cranes[crane_idx].r && next_pos[k].second == cranes[crane_idx].c) {\n                if(nr == cranes[k].r && nc == cranes[k].c) return false;\n            }\n        }\n        for(int k=crane_idx+1; k<N; ++k) {\n            if(cranes[k].r == nr && cranes[k].c == nc) return false;\n        }\n        return true;\n    }\n\n    bool valid_cell_for_carry(int crane_idx, int r, int c) {\n        if(cranes[crane_idx].holding == -1 || cranes[crane_idx].is_large) return true;\n        return grid[r][c] == -1;\n    }\n\n    int get_container_priority(int cid) {\n        int target_row = cid / N;\n        int expected = next_dispatch[target_row];\n        if(cid == expected) return 3;\n        if(cid < expected + N) return 2;\n        return 1;\n    }\n\n    void solve() {\n        while(turn < MAX_TURNS && total_dispatched < N*N) {\n            turn++;\n            receive_containers();\n            \n            vector<char> moves(N, '.');\n            vector<pair<int,int>> next_pos(N);\n            for(int i=0; i<N; ++i) next_pos[i] = {cranes[i].r, cranes[i].c};\n\n            // Find all containers and their priorities\n            struct ContainerInfo {\n                int id, r, c, target_row, priority;\n            };\n            vector<ContainerInfo> containers;\n            for(int i=0; i<N; ++i) {\n                for(int j=0; j<N; ++j) {\n                    if(grid[i][j] != -1) {\n                        containers.push_back({grid[i][j], i, j, grid[i][j]/N, get_container_priority(grid[i][j])});\n                    }\n                }\n            }\n            sort(containers.begin(), containers.end(), [](const ContainerInfo& a, const ContainerInfo& b) {\n                return a.priority > b.priority;\n            });\n\n            for(int i=0; i<N; ++i) {\n                Crane& cr = cranes[i];\n                long long best_score = -1e18;\n                char best_move = '.';\n                int nr = cr.r, nc = cr.c;\n\n                // Base score\n                long long base_score = 0;\n                if(cr.holding != -1) {\n                    int t_row = cr.holding / N;\n                    base_score -= (abs(cr.r - t_row) + abs(cr.c - (N-1))) * 10;\n                    if(cr.holding == next_dispatch[t_row]) base_score += 5000;\n                }\n\n                // Try P (Pick up)\n                if(cr.holding == -1 && grid[cr.r][cr.c] != -1) {\n                    int cid = grid[cr.r][cr.c];\n                    int t_row = cid / N;\n                    long long s = base_score;\n                    int prio = get_container_priority(cid);\n                    if(prio == 3) s += 20000;\n                    else if(prio == 2) s += 5000;\n                    else s += 1000;\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = 'P';\n                        nr = cr.r; nc = cr.c;\n                    }\n                }\n\n                // Try Q (Place/Dispatch)\n                if(cr.holding != -1 && grid[cr.r][cr.c] == -1) {\n                    int t_row = cr.holding / N;\n                    long long s = base_score;\n                    if(cr.r == t_row && cr.c == N-1) {\n                        if(cr.holding == next_dispatch[t_row]) s += 35000;\n                        else s += 15000;\n                    } else if(cr.c == N-1) {\n                        s += 8000;\n                    } else if(cr.c >= 2 && cr.c <= N-2) {\n                        // Buffer - prefer storing containers in their target row\n                        if(cr.r == t_row) s += 500;\n                        else s -= 500;\n                    } else {\n                        s -= 3000;\n                    }\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = 'Q';\n                        nr = cr.r; nc = cr.c;\n                    }\n                }\n\n                // Try moves\n                for(int d=0; d<4; ++d) {\n                    int tr = cr.r + dr[d];\n                    int tc = cr.c + dc[d];\n                    if(!can_move(i, tr, tc, next_pos)) continue;\n                    if(!valid_cell_for_carry(i, tr, tc)) continue;\n\n                    long long s = 0;\n                    if(cr.holding != -1) {\n                        int t_row = cr.holding / N;\n                        int dist = abs(tr - t_row) + abs(tc - (N-1));\n                        s -= dist * 10;\n                        if(cr.holding == next_dispatch[t_row]) s += 7000;\n                        if(tr == t_row && tc == N-1) s += 20000;\n                        if(tc == N-1 && tr != t_row) s -= 8000;\n                        // Prefer buffer in target row\n                        if(tc >= 2 && tc <= N-2 && tr == t_row) s += 1000;\n                    } else {\n                        // Empty - prioritize high-priority containers\n                        int best_container_dist = 10000;\n                        for(const auto& cont : containers) {\n                            if(cont.c == 0) {\n                                int d = abs(tr - cont.r) + abs(tc - 0);\n                                if(cont.priority == 3) d -= 200;\n                                else if(cont.priority == 2) d -= 50;\n                                if(d < best_container_dist) best_container_dist = d;\n                            }\n                        }\n                        s -= best_container_dist * 8;\n                        \n                        // Look for buffered containers that are high priority\n                        for(const auto& cont : containers) {\n                            if(cont.c >= 1 && cont.c <= N-2 && cont.priority >= 2) {\n                                int d = abs(tr - cont.r) + abs(tc - cont.c);\n                                s -= d * 5;\n                            }\n                        }\n                        \n                        // Large crane should help move between rows\n                        if(cr.is_large) {\n                            for(int r=0; r<N; ++r) {\n                                if(grid[r][1] != -1 || grid[r][2] != -1 || grid[r][3] != -1) {\n                                    int cid = -1;\n                                    if(grid[r][1] != -1) cid = grid[r][1];\n                                    else if(grid[r][2] != -1) cid = grid[r][2];\n                                    else if(grid[r][3] != -1) cid = grid[r][3];\n                                    if(cid != -1 && cid == next_dispatch[r]) {\n                                        int d = abs(tr - r) + abs(tc - 1);\n                                        s -= d * 3;\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if(s > best_score) {\n                        best_score = s;\n                        best_move = dchar[d];\n                        nr = tr; nc = tc;\n                    }\n                }\n\n                moves[i] = best_move;\n                if(best_move == 'P' || best_move == 'Q' || best_move == '.') {\n                    next_pos[i] = {cr.r, cr.c};\n                } else {\n                    next_pos[i] = {nr, nc};\n                }\n            }\n\n            // Execute\n            for(int i=0; i<N; ++i) {\n                ans[i] += moves[i];\n                Crane& cr = cranes[i];\n                char m = moves[i];\n                if(m == 'P') {\n                    cr.holding = grid[cr.r][cr.c];\n                    grid[cr.r][cr.c] = -1;\n                } else if(m == 'Q') {\n                    grid[cr.r][cr.c] = cr.holding;\n                    cr.holding = -1;\n                } else if(m == 'U') cr.r--;\n                else if(m == 'D') cr.r++;\n                else if(m == 'L') cr.c--;\n                else if(m == 'R') cr.c++;\n            }\n\n            dispatch_containers();\n        }\n\n        size_t max_len = 0;\n        for(const auto& s : ans) max_len = max(max_len, s.size());\n        if(max_len == 0) max_len = 1;\n        for(int i=0; i<N; ++i) {\n            while(ans[i].size() < max_len) ans[i] += '.';\n        }\n    }\n\n    void print_ans() {\n        for(int i=0; i<N; ++i) {\n            cout << ans[i] << endl;\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.print_ans();\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <string>\n#include <cstdlib>\n\nusing namespace std;\n\n// Structure to represent grid coordinates\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Coord& o) const { return !(*this == o); }\n};\n\n// Manhattan distance between two coordinates\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint N;\nint h[25][25];\nvector<Coord> sources;\nvector<Coord> sinks;\n\n// Flow targets for each source cell: list of {sink_coord, amount}\nstruct FlowTarget {\n    Coord sink;\n    int amount;\n};\nvector<FlowTarget> source_flows[25][25];\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\n    // Read input and identify sources (h > 0) and sinks (h < 0)\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    // Working copy of heights to track remaining supply/demand\n    int cur_h[25][25];\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            cur_h[i][j] = h[i][j];\n    \n    // Indices of active sources and sinks\n    vector<int> src_idx(sources.size());\n    iota(src_idx.begin(), src_idx.end(), 0);\n    vector<int> snk_idx(sinks.size());\n    iota(snk_idx.begin(), snk_idx.end(), 0);\n\n    // Greedy Flow Calculation\n    // Repeatedly pick the pair (source, sink) with minimum distance and transfer soil.\n    // This approximates the Minimum Cost Flow / Earth Mover's Distance.\n    while (!src_idx.empty() && !snk_idx.empty()) {\n        int s_choice = -1;\n        int k_choice = -1;\n        int min_d = 1e9;\n\n        // Find the pair with minimum Manhattan distance\n        for (int s : src_idx) {\n            for (int k : snk_idx) {\n                int d = dist(sources[s], sinks[k]);\n                if (d < min_d) {\n                    min_d = d;\n                    s_choice = s;\n                    k_choice = k;\n                }\n            }\n        }\n        \n        if (s_choice == -1) break;\n\n        Coord u = sources[s_choice];\n        Coord v = sinks[k_choice];\n        // Transfer as much as possible\n        int amount = min(cur_h[u.r][u.c], -cur_h[v.r][v.c]);\n        \n        source_flows[u.r][u.c].push_back({v, amount});\n        \n        cur_h[u.r][u.c] -= amount;\n        cur_h[v.r][v.c] += amount;\n        \n        // Remove exhausted source or sink from active lists\n        if (cur_h[u.r][u.c] == 0) {\n            for(int i=0; i<src_idx.size(); ++i) {\n                if(src_idx[i] == s_choice) {\n                    src_idx[i] = src_idx.back();\n                    src_idx.pop_back();\n                    break;\n                }\n            }\n        }\n        if (cur_h[v.r][v.c] == 0) {\n            for(int i=0; i<snk_idx.size(); ++i) {\n                if(snk_idx[i] == k_choice) {\n                    snk_idx[i] = snk_idx.back();\n                    snk_idx.pop_back();\n                    break;\n                }\n            }\n        }\n    }\n\n    vector<string> ops;\n    Coord cur = {0, 0}; // Truck starts at (0,0)\n\n    // List of sources that have soil to transport\n    vector<Coord> active_sources;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!source_flows[i][j].empty()) {\n                active_sources.push_back({i, j});\n            }\n        }\n    }\n\n    // Order sources using Nearest Neighbor heuristic to minimize empty travel\n    vector<bool> visited_source(active_sources.size(), false);\n    int sources_remaining = active_sources.size();\n\n    while (sources_remaining > 0) {\n        int best_idx = -1;\n        int min_d = 1e9;\n        for (int i = 0; i < active_sources.size(); ++i) {\n            if (!visited_source[i]) {\n                int d = dist(cur, active_sources[i]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n        }\n\n        if (best_idx == -1) break;\n\n        Coord u = active_sources[best_idx];\n        visited_source[best_idx] = true;\n        sources_remaining--;\n\n        // Move truck to source u\n        while (cur != u) {\n            if (cur.r < u.r) { cur.r++; ops.push_back(\"D\"); }\n            else if (cur.r > u.r) { cur.r--; ops.push_back(\"U\"); }\n            else if (cur.c < u.c) { cur.c++; ops.push_back(\"R\"); }\n            else if (cur.c > u.c) { cur.c--; ops.push_back(\"L\"); }\n        }\n\n        // Calculate total load to pick up at u\n        int total_load = 0;\n        for (auto& flow : source_flows[u.r][u.c]) {\n            total_load += flow.amount;\n        }\n\n        // Load soil\n        ops.push_back(\"+\" + to_string(total_load));\n\n        // Visit assigned sinks for this source\n        // Order sinks using Nearest Neighbor to minimize loaded travel\n        vector<FlowTarget> targets = source_flows[u.r][u.c];\n        vector<bool> visited_target(targets.size(), false);\n        int targets_remaining = targets.size();\n\n        while (targets_remaining > 0) {\n            int best_t = -1;\n            int min_td = 1e9;\n            for (int i = 0; i < targets.size(); ++i) {\n                if (!visited_target[i]) {\n                    int d = dist(cur, targets[i].sink);\n                    if (d < min_td) {\n                        min_td = d;\n                        best_t = i;\n                    }\n                }\n            }\n            \n            Coord v = targets[best_t].sink;\n            // Move truck to sink v\n            while (cur != v) {\n                if (cur.r < v.r) { cur.r++; ops.push_back(\"D\"); }\n                else if (cur.r > v.r) { cur.r--; ops.push_back(\"U\"); }\n                else if (cur.c < v.c) { cur.c++; ops.push_back(\"R\"); }\n                else if (cur.c > v.c) { cur.c--; ops.push_back(\"L\"); }\n            }\n\n            // Unload soil\n            int amt = targets[best_t].amount;\n            ops.push_back(\"-\" + to_string(amt));\n            \n            visited_target[best_t] = true;\n            targets_remaining--;\n        }\n    }\n\n    // Output the sequence of operations\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 <cmath>\n#include <random>\n#include <set>\n\nusing namespace std;\n\nstruct Position {\n    int priority;\n    int i;\n    int j;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n    \n    int seed_count = 2 * N * (N - 1);\n    int grid_size = N * N;\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    \n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n    \n    mt19937 rng(42);\n    \n    vector<int> global_max(M, 0);\n    for (int d = 0; d < M; d++) {\n        for (int i = 0; i < seed_count; i++) {\n            global_max[d] = max(global_max[d], X[i][d]);\n        }\n    }\n    \n    vector<int> prev_best_seeds;\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<int> dim_max(M, 0);\n        vector<vector<int>> dim_top_seeds(M);\n        \n        for (int d = 0; d < M; d++) {\n            vector<pair<int, int>> dim_values;\n            for (int i = 0; i < seed_count; i++) {\n                dim_values.push_back({X[i][d], i});\n            }\n            sort(dim_values.begin(), dim_values.end(), greater<pair<int,int>>());\n            dim_max[d] = dim_values[0].first;\n            \n            for (size_t i = 0; i < min((size_t)5, dim_values.size()); i++) {\n                dim_top_seeds[d].push_back(dim_values[i].second);\n            }\n        }\n        \n        // Count dimensions near global max\n        int dims_near_global = 0;\n        for (int d = 0; d < M; d++) {\n            if (global_max[d] > 0 && (double)dim_max[d] / global_max[d] >= 0.92) {\n                dims_near_global++;\n            }\n        }\n        \n        // Turn-aware parameters (simpler than before)\n        bool is_early_turn = (turn < T / 2);\n        bool is_final_turn = (turn >= T - 2);\n        \n        vector<pair<double, int>> seed_score(seed_count);\n        vector<int> seed_total(seed_count, 0);\n        vector<int> seed_dim_excellence(seed_count, 0);\n        \n        for (int i = 0; i < seed_count; i++) {\n            double score = 0;\n            int total = 0;\n            int dim_excellence_count = 0;\n            \n            for (int d = 0; d < M; d++) {\n                total += X[i][d];\n                \n                if (dim_max[d] > 0) {\n                    double ratio = (double)X[i][d] / dim_max[d];\n                    \n                    if (X[i][d] == dim_max[d]) {\n                        score += 28.0;\n                        dim_excellence_count++;\n                    } else if (ratio >= 0.98) {\n                        score += 16.0;\n                    } else if (ratio >= 0.95) {\n                        score += 12.0;\n                    } else if (ratio >= 0.90) {\n                        score += 8.0;\n                    } else if (ratio >= 0.85) {\n                        score += 5.0;\n                    } else if (ratio >= 0.75) {\n                        score += 2.0;\n                    }\n                    \n                    score += ratio * ratio * 7.0;\n                }\n            }\n            \n            score += total * 0.028;\n            \n            if (turn > 0 && find(prev_best_seeds.begin(), prev_best_seeds.end(), i) != prev_best_seeds.end()) {\n                score += 4.0 * (is_final_turn ? 0.8 : 0.4);\n            }\n            \n            score += dim_excellence_count * 7.0 * (is_early_turn ? 1.0 : 0.5);\n            \n            // Bonus for difficult dimensions\n            for (int d = 0; d < M; d++) {\n                if (global_max[d] > 0 && (double)dim_max[d] / global_max[d] < 0.90) {\n                    if (X[i][d] >= dim_max[d] * 0.95) {\n                        score += 10.0;\n                    } else if (X[i][d] >= dim_max[d] * 0.85) {\n                        score += 5.0;\n                    }\n                }\n            }\n            \n            seed_score[i] = {score, i};\n            seed_total[i] = total;\n            seed_dim_excellence[i] = dim_excellence_count;\n        }\n        \n        sort(seed_score.begin(), seed_score.end(), [](const auto& a, const auto& b) {\n            if (abs(a.first - b.first) > 0.01) return a.first > b.first;\n            return a.second < b.second;\n        });\n        \n        vector<int> selected;\n        vector<bool> selected_flag(seed_count, false);\n        \n        // Ensure all dimensions have best seed\n        for (int d = 0; d < M; d++) {\n            if (!dim_top_seeds[d].empty()) {\n                int seed_id = dim_top_seeds[d][0];\n                if (!selected_flag[seed_id] && (int)selected.size() < grid_size) {\n                    selected.push_back(seed_id);\n                    selected_flag[seed_id] = true;\n                }\n            }\n        }\n        \n        // Add 2nd best for all dimensions\n        for (int d = 0; d < M; d++) {\n            if (dim_top_seeds[d].size() >= 2) {\n                int seed_id = dim_top_seeds[d][1];\n                if (!selected_flag[seed_id] && (int)selected.size() < grid_size - 2) {\n                    selected.push_back(seed_id);\n                    selected_flag[seed_id] = true;\n                }\n            }\n        }\n        \n        // Add seeds with multiple dimensional excellence\n        for (int i = 0; i < seed_count && (int)selected.size() < grid_size - 1; i++) {\n            int seed_id = seed_score[i].second;\n            if (!selected_flag[seed_id] && seed_dim_excellence[seed_id] >= 2) {\n                selected.push_back(seed_id);\n                selected_flag[seed_id] = true;\n            }\n        }\n        \n        // Fill with highest scored\n        for (const auto& p : seed_score) {\n            if ((int)selected.size() >= grid_size) break;\n            if (!selected_flag[p.second]) {\n                selected.push_back(p.second);\n                selected_flag[p.second] = true;\n            }\n        }\n        \n        auto calc_offspring_potential = [&](int i, int j) -> int {\n            int potential = 0;\n            for (int d = 0; d < M; d++) {\n                potential += max(X[i][d], X[j][d]);\n            }\n            return potential;\n        };\n        \n        auto calc_compatibility = [&](int i, int j) -> double {\n            double comp = 0;\n            for (int d = 0; d < M; d++) {\n                comp += (X[i][d] + X[j][d]) / 2.0;\n            }\n            return comp;\n        };\n        \n        vector<Position> positions;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int neighbors = 0;\n                const int di[] = {-1, 1, 0, 0};\n                const int dj[] = {0, 0, -1, 1};\n                for (int dir = 0; dir < 4; dir++) {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        neighbors++;\n                    }\n                }\n                int center_dist = abs(i - N/2) + abs(j - N/2);\n                positions.push_back({neighbors * 10 - center_dist, i, j});\n            }\n        }\n        sort(positions.begin(), positions.end(), [](const Position& a, const Position& b) {\n            return a.priority > b.priority;\n        });\n        \n        int max_total = 0;\n        for (int si : selected) {\n            max_total = max(max_total, seed_total[si]);\n        }\n        \n        vector<vector<int>> best_A;\n        int best_potential = -1;\n        \n        // Balanced number of attempts\n        int num_attempts = is_final_turn ? 12 : (is_early_turn ? max(10, 15 - turn) : 8);\n        \n        for (int attempt = 0; attempt < num_attempts; attempt++) {\n            mt19937 attempt_rng(42 + attempt * 7 + turn * 3);\n            \n            vector<vector<int>> A(N, vector<int>(N, -1));\n            vector<bool> placed(selected.size(), false);\n            \n            vector<pair<double, int>> seed_order;\n            for (size_t i = 0; i < selected.size(); i++) {\n                int si = selected[i];\n                double order_score = 0;\n                \n                if (attempt == 0) {\n                    order_score = seed_total[si];\n                } else if (attempt == 1) {\n                    order_score = seed_score[si].first;\n                } else if (attempt == 2) {\n                    order_score = seed_dim_excellence[si] * 2800 + seed_total[si];\n                } else if (attempt == 3) {\n                    bool is_best_any = false;\n                    for (int d = 0; d < M; d++) {\n                        if (X[si][d] == dim_max[d]) {\n                            is_best_any = true;\n                            break;\n                        }\n                    }\n                    order_score = (is_best_any ? 4500 : 0) + seed_total[si];\n                } else if (attempt == 4) {\n                    int diff_score = 0;\n                    for (int d = 0; d < M; d++) {\n                        if (global_max[d] > 0 && (double)dim_max[d] / global_max[d] < 0.90) {\n                            diff_score += X[si][d];\n                        }\n                    }\n                    order_score = diff_score * 3 + seed_total[si];\n                } else {\n                    order_score = seed_score[si].first + (double)(attempt_rng() % 1200);\n                }\n                \n                seed_order.push_back({order_score, (int)i});\n            }\n            \n            sort(seed_order.begin(), seed_order.end(), [](const pair<double,int>& a, const pair<double,int>& b) {\n                if (abs(a.first - b.first) > 0.01) return a.first > b.first;\n                return a.second < b.second;\n            });\n            \n            for (size_t idx = 0; idx < seed_order.size(); idx++) {\n                int si = seed_order[idx].second;\n                int seed_id = selected[si];\n                \n                if (placed[si]) continue;\n                \n                int best_pos_idx = -1;\n                double best_pos_score = -1e9;\n                \n                for (size_t pidx = 0; pidx < positions.size(); pidx++) {\n                    int pi = positions[pidx].i;\n                    int pj = positions[pidx].j;\n                    if (A[pi][pj] != -1) continue;\n                    \n                    double pos_score = 0;\n                    int neighbor_count = 0;\n                    int max_pot = 0;\n                    \n                    const int di[] = {-1, 1, 0, 0};\n                    const int dj[] = {0, 0, -1, 1};\n                    \n                    for (int dir = 0; dir < 4; dir++) {\n                        int ni = pi + di[dir];\n                        int nj = pj + dj[dir];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1) {\n                            pos_score += calc_compatibility(seed_id, A[ni][nj]);\n                            max_pot = max(max_pot, calc_offspring_potential(seed_id, A[ni][nj]));\n                            neighbor_count++;\n                        }\n                    }\n                    \n                    if (neighbor_count > 0) {\n                        pos_score /= neighbor_count;\n                        pos_score += max_pot * 0.002;\n                    }\n                    \n                    int available = 0;\n                    for (int dir = 0; dir < 4; dir++) {\n                        int ni = pi + di[dir];\n                        int nj = pj + dj[dir];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] == -1) {\n                            available++;\n                        }\n                    }\n                    pos_score += available * 0.3;\n                    \n                    if (attempt > 0) {\n                        pos_score += (double)(attempt_rng() % 250) / 1000.0;\n                    }\n                    \n                    if (pos_score > best_pos_score) {\n                        best_pos_score = pos_score;\n                        best_pos_idx = (int)pidx;\n                    }\n                }\n                \n                if (best_pos_idx >= 0) {\n                    A[positions[best_pos_idx].i][positions[best_pos_idx].j] = seed_id;\n                    placed[si] = true;\n                }\n            }\n            \n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1) {\n                        for (size_t si = 0; si < selected.size(); si++) {\n                            if (!placed[si]) {\n                                A[i][j] = selected[si];\n                                placed[si] = true;\n                                goto filled;\n                            }\n                        }\n                        filled:;\n                    }\n                }\n            }\n            \n            int current_potential = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1) continue;\n                    if (j + 1 < N && A[i][j+1] != -1) {\n                        current_potential += calc_offspring_potential(A[i][j], A[i][j+1]);\n                    }\n                    if (i + 1 < N && A[i+1][j] != -1) {\n                        current_potential += calc_offspring_potential(A[i][j], A[i+1][j]);\n                    }\n                }\n            }\n            \n            // Moderate optimization (not over-aggressive)\n            bool improved = true;\n            int max_swaps = is_final_turn ? 220 : (is_early_turn ? 180 : 160);\n            int swap_count = 0;\n            \n            while (improved && swap_count < max_swaps) {\n                improved = false;\n                swap_count++;\n                \n                current_potential = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (A[i][j] == -1) continue;\n                        if (j + 1 < N && A[i][j+1] != -1) {\n                            current_potential += calc_offspring_potential(A[i][j], A[i][j+1]);\n                        }\n                        if (i + 1 < N && A[i+1][j] != -1) {\n                            current_potential += calc_offspring_potential(A[i][j], A[i+1][j]);\n                        }\n                    }\n                }\n                \n                struct SwapOption {\n                    int i1, j1, i2, j2;\n                    int gain;\n                };\n                vector<SwapOption> swap_options;\n                \n                for (int i1 = 0; i1 < N; i1++) {\n                    for (int j1 = 0; j1 < N; j1++) {\n                        if (A[i1][j1] == -1) continue;\n                        for (int i2 = i1; i2 < N; i2++) {\n                            int j2_start = (i2 == i1 ? j1 + 1 : 0);\n                            for (int j2 = j2_start; j2 < N; j2++) {\n                                if (A[i2][j2] == -1) continue;\n                                if (i1 == i2 && j1 == j2) continue;\n                                \n                                int total1 = seed_total[A[i1][j1]];\n                                int total2 = seed_total[A[i2][j2]];\n                                if (total1 < max_total * 0.25 && total2 < max_total * 0.25) continue;\n                                \n                                int current_edge_pot = 0;\n                                const int di[] = {-1, 1, 0, 0};\n                                const int dj[] = {0, 0, -1, 1};\n                                \n                                for (int dir = 0; dir < 4; dir++) {\n                                    int ni = i1 + di[dir];\n                                    int nj = j1 + dj[dir];\n                                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1 && !(ni == i2 && nj == j2)) {\n                                        current_edge_pot += calc_offspring_potential(A[i1][j1], A[ni][nj]);\n                                    }\n                                }\n                                for (int dir = 0; dir < 4; dir++) {\n                                    int ni = i2 + di[dir];\n                                    int nj = j2 + dj[dir];\n                                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1 && !(ni == i1 && nj == j1)) {\n                                        current_edge_pot += calc_offspring_potential(A[i2][j2], A[ni][nj]);\n                                    }\n                                }\n                                \n                                int new_edge_pot = 0;\n                                for (int dir = 0; dir < 4; dir++) {\n                                    int ni = i1 + di[dir];\n                                    int nj = j1 + dj[dir];\n                                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1 && !(ni == i2 && nj == j2)) {\n                                        new_edge_pot += calc_offspring_potential(A[i2][j2], A[ni][nj]);\n                                    }\n                                }\n                                for (int dir = 0; dir < 4; dir++) {\n                                    int ni = i2 + di[dir];\n                                    int nj = j2 + dj[dir];\n                                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[ni][nj] != -1 && !(ni == i1 && nj == j1)) {\n                                        new_edge_pot += calc_offspring_potential(A[i1][j1], A[ni][nj]);\n                                    }\n                                }\n                                \n                                int gain = new_edge_pot - current_edge_pot;\n                                if (gain > 0) {\n                                    swap_options.push_back({i1, j1, i2, j2, gain});\n                                }\n                            }\n                        }\n                    }\n                }\n                \n                if (!swap_options.empty()) {\n                    auto best_swap = max_element(swap_options.begin(), swap_options.end(), \n                        [](const SwapOption& a, const SwapOption& b) { return a.gain < b.gain; });\n                    \n                    swap(A[best_swap->i1][best_swap->j1], A[best_swap->i2][best_swap->j2]);\n                    current_potential += best_swap->gain;\n                    improved = true;\n                }\n            }\n            \n            if (current_potential > best_potential) {\n                best_potential = current_potential;\n                best_A = A;\n            }\n        }\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << best_A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        vector<pair<int, int>> new_totals;\n        \n        for (int i = 0; i < seed_count; i++) {\n            int total = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                total += X[i][j];\n                global_max[j] = max(global_max[j], X[i][j]);\n            }\n            new_totals.push_back({total, i});\n        }\n        \n        sort(new_totals.begin(), new_totals.end(), greater<pair<int,int>>());\n        prev_best_seeds.clear();\n        for (int i = 0; i < min(15, seed_count); i++) {\n            prev_best_seeds.push_back(new_totals[i].second);\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n};\n\nint dist(Point a, Point b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> S(N), T(N);\n    for (int i = 0; i < N; i++) cin >> S[i];\n    for (int i = 0; i < N; i++) cin >> T[i];\n    \n    // Collect source and target positions\n    vector<Point> sources, targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (S[i][j] == '1') sources.push_back({i, j});\n            if (T[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n    \n    // OPTIMIZED: Choose edge length based on problem characteristics\n    int V_prime = 2;\n    int edge_len;\n    \n    // For smaller grids or dense problems, use shorter reach\n    // For larger grids or sparse problems, use longer reach\n    if (N <= 20) {\n        edge_len = min(2, N - 1);\n    } else if (N <= 25) {\n        edge_len = min(3, N - 1);\n    } else {\n        edge_len = min(4, N - 1);\n    }\n    if (edge_len < 1) edge_len = 1;\n    \n    cout << V_prime << \"\\n\";\n    cout << 0 << \" \" << edge_len << \"\\n\";\n    \n    // Initial root position - center of sources\n    int root_x = 0, root_y = 0;\n    if (!sources.empty()) {\n        int sum_x = 0, sum_y = 0;\n        for (auto& p : sources) {\n            sum_x += p.x;\n            sum_y += p.y;\n        }\n        root_x = max(0, min(N - 1, sum_x / (int)sources.size()));\n        root_y = max(0, min(N - 1, sum_y / (int)sources.size()));\n    }\n    cout << root_x << \" \" << root_y << \"\\n\";\n    \n    // Exact game state tracking\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    vector<vector<bool>> is_target(N, vector<bool>(N, false));\n    vector<vector<bool>> target_done(N, vector<bool>(N, false));\n    \n    int remaining_takoyaki = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = (S[i][j] == '1' ? 1 : 0);\n            is_target[i][j] = (T[i][j] == '1');\n            if (grid[i][j] == 1 && is_target[i][j]) {\n                target_done[i][j] = true;\n            } else if (grid[i][j] == 1) {\n                remaining_takoyaki++;\n            }\n        }\n    }\n    \n    int delivered = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (is_target[i][j] && grid[i][j] == 1) {\n                delivered++;\n            }\n        }\n    }\n    \n    // Single fingertip state\n    int fp_dir = 0;\n    bool holding = false;\n    Point carry_target = {-1, -1};\n    Point current_source = {-1, -1};\n    \n    // Track recent movement to avoid oscillation\n    int last_move_dir = -1;\n    int same_move_count = 0;\n    \n    auto get_fp_pos = [&]() -> Point {\n        return {root_x + DX[fp_dir] * edge_len, \n                root_y + DY[fp_dir] * edge_len};\n    };\n    \n    auto in_bounds = [&](int x, int y) -> bool {\n        return x >= 0 && x < N && y >= 0 && y < N;\n    };\n    \n    auto find_nearest_takoyaki = [&](Point from) -> Point {\n        Point best = {-1, -1};\n        int best_d = 1e9;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 1) {\n                    int d = dist(from, {i, j});\n                    if (d < best_d) {\n                        best_d = d;\n                        best = {i, j};\n                    }\n                }\n            }\n        }\n        return best;\n    };\n    \n    auto find_nearest_unfilled_target = [&](Point from) -> Point {\n        Point best = {-1, -1};\n        int best_d = 1e9;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (is_target[i][j] && !target_done[i][j]) {\n                    int d = dist(from, {i, j});\n                    if (d < best_d) {\n                        best_d = d;\n                        best = {i, j};\n                    }\n                }\n            }\n        }\n        return best;\n    };\n    \n    vector<string> commands;\n    int turns = 0;\n    int max_turns = 95000;\n    \n    while (delivered + (holding ? 1 : 0) < M && turns < max_turns) {\n        string cmd(4, '.');\n        \n        Point fp_pos = get_fp_pos();\n        \n        bool do_pickup = false;\n        bool do_place = false;\n        int move_dir = -1;\n        int rotate_to = -1;\n        \n        if (holding) {\n            // Try to place at target\n            if (carry_target.x >= 0 && in_bounds(carry_target.x, carry_target.y) &&\n                is_target[carry_target.x][carry_target.y] && \n                !target_done[carry_target.x][carry_target.y] &&\n                fp_pos == carry_target) {\n                \n                do_place = true;\n            }\n            \n            if (!do_place && carry_target.x >= 0 && in_bounds(carry_target.x, carry_target.y) &&\n                !target_done[carry_target.x][carry_target.y]) {\n                \n                // Move toward target\n                int ideal_rx = carry_target.x - DX[fp_dir] * edge_len;\n                int ideal_ry = carry_target.y - DY[fp_dir] * edge_len;\n                \n                if (root_x < ideal_rx) move_dir = 1;\n                else if (root_x > ideal_rx) move_dir = 3;\n                else if (root_y < ideal_ry) move_dir = 0;\n                else if (root_y > ideal_ry) move_dir = 2;\n                \n                // PROACTIVE rotation: Check if rotating would reduce total moves\n                int curr_dist = dist(fp_pos, carry_target);\n                int best_dist = curr_dist;\n                int best_dir = fp_dir;\n                for (int d = 0; d < 4; d++) {\n                    Point test = {root_x + DX[d] * edge_len, root_y + DY[d] * edge_len};\n                    int d_to_target = dist(test, carry_target);\n                    if (d_to_target < best_dist) {\n                        best_dist = d_to_target;\n                        best_dir = d;\n                    }\n                }\n                \n                // Rotate if it significantly helps (reduces distance by 2+)\n                if (best_dir != fp_dir && best_dist <= curr_dist - 2) {\n                    int diff = (best_dir - fp_dir + 4) % 4;\n                    if (diff == 1) rotate_to = 0;\n                    else if (diff == 3) rotate_to = 1;\n                }\n            } else if (!do_place) {\n                // Target invalid - find new one\n                carry_target = find_nearest_unfilled_target(fp_pos);\n            }\n        } else {\n            // Try to pick up takoyaki\n            if (in_bounds(fp_pos.x, fp_pos.y) && grid[fp_pos.x][fp_pos.y] == 1) {\n                do_pickup = true;\n            } else {\n                // Check if current source is still valid\n                bool source_valid = false;\n                if (current_source.x >= 0 && in_bounds(current_source.x, current_source.y) && \n                    grid[current_source.x][current_source.y] == 1) {\n                    source_valid = true;\n                }\n                \n                if (!source_valid) {\n                    current_source = find_nearest_takoyaki(fp_pos);\n                }\n                \n                if (current_source.x >= 0) {\n                    // Move toward source\n                    int ideal_rx = current_source.x - DX[fp_dir] * edge_len;\n                    int ideal_ry = current_source.y - DY[fp_dir] * edge_len;\n                    \n                    if (root_x < ideal_rx) move_dir = 1;\n                    else if (root_x > ideal_rx) move_dir = 3;\n                    else if (root_y < ideal_ry) move_dir = 0;\n                    else if (root_y > ideal_ry) move_dir = 2;\n                    \n                    // PROACTIVE rotation for source too\n                    int curr_dist = dist(fp_pos, current_source);\n                    int best_dist = curr_dist;\n                    int best_dir = fp_dir;\n                    for (int d = 0; d < 4; d++) {\n                        Point test = {root_x + DX[d] * edge_len, root_y + DY[d] * edge_len};\n                        int d_to_src = dist(test, current_source);\n                        if (d_to_src < best_dist) {\n                            best_dist = d_to_src;\n                            best_dir = d;\n                        }\n                    }\n                    \n                    if (best_dir != fp_dir && best_dist <= curr_dist - 2) {\n                        int diff = (best_dir - fp_dir + 4) % 4;\n                        if (diff == 1) rotate_to = 0;\n                        else if (diff == 3) rotate_to = 1;\n                    }\n                }\n            }\n        }\n        \n        // Avoid oscillation: if moving same direction many times, consider alternatives\n        if (move_dir >= 0) {\n            if (move_dir == last_move_dir) {\n                same_move_count++;\n            } else {\n                same_move_count = 0;\n                last_move_dir = move_dir;\n            }\n            \n            // If stuck moving same direction too long, try perpendicular\n            if (same_move_count > edge_len * 2) {\n                // Reset and let algorithm find new path\n                same_move_count = 0;\n                if (holding) {\n                    carry_target = find_nearest_unfilled_target(fp_pos);\n                } else {\n                    current_source = find_nearest_takoyaki(fp_pos);\n                }\n            }\n        }\n        \n        // EXECUTE\n        if (move_dir >= 0) {\n            int nx = root_x + DX[move_dir];\n            int ny = root_y + DY[move_dir];\n            if (in_bounds(nx, ny)) {\n                cmd[0] = DIR_CHAR[move_dir];\n                root_x = nx;\n                root_y = ny;\n            }\n        }\n        \n        if (rotate_to >= 0) {\n            cmd[1] = (rotate_to == 0 ? 'R' : 'L');\n            fp_dir = (rotate_to == 0) ? ((fp_dir + 1) % 4) : ((fp_dir + 3) % 4);\n        }\n        \n        fp_pos = get_fp_pos();\n        \n        if (do_pickup && in_bounds(fp_pos.x, fp_pos.y) && grid[fp_pos.x][fp_pos.y] == 1) {\n            cmd[3] = 'P';\n            holding = true;\n            grid[fp_pos.x][fp_pos.y] = 0;\n            remaining_takoyaki--;\n            current_source = {-1, -1};\n            carry_target = find_nearest_unfilled_target(fp_pos);\n        } else if (do_place && carry_target.x >= 0 && in_bounds(carry_target.x, carry_target.y) &&\n                   fp_pos == carry_target && !target_done[carry_target.x][carry_target.y]) {\n            cmd[3] = 'P';\n            holding = false;\n            target_done[carry_target.x][carry_target.y] = true;\n            delivered++;\n            carry_target = {-1, -1};\n        }\n        \n        // Check completion - use remaining_takoyaki counter for efficiency\n        if (remaining_takoyaki == 0 && !holding) break;\n        \n        // Break deadlock\n        if (cmd == \"....\") {\n            for (int d = 0; d < 4; d++) {\n                int nx = root_x + DX[d];\n                int ny = root_y + DY[d];\n                if (in_bounds(nx, ny)) {\n                    cmd[0] = DIR_CHAR[d];\n                    root_x = nx;\n                    root_y = ny;\n                    break;\n                }\n            }\n        }\n        \n        commands.push_back(cmd);\n        turns++;\n    }\n    \n    for (const string& c : commands) {\n        cout << c << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\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\nstruct GridCell {\n    int m;\n    int s;\n    int score() const { return m - s; }\n};\n\n// Global data\nint GW, GH;\nint CELL_SIZE;\nvector<vector<GridCell>> grid;\nvector<vector<bool>> selected;\nvector<Point> mackerels, sardines;\n\n// Directions\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {-1, 0, 1, 0};\n\nstruct PQElement {\n    int r, c;\n    int score;\n    bool operator<(const PQElement& other) const {\n        return score < other.score;\n    }\n};\n\n// Time tracking\nchrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 1.80;\n\ndouble getElapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\nbool timeRemaining() {\n    return getElapsed() < TIME_LIMIT;\n}\n\n// Initialize grid\nvoid initGrid(int cell_size) {\n    CELL_SIZE = cell_size;\n    GW = MAX_COORD / CELL_SIZE + 1;\n    GH = MAX_COORD / CELL_SIZE + 1;\n    \n    grid.assign(GH, vector<GridCell>(GW, {0, 0}));\n    selected.assign(GH, vector<bool>(GW, false));\n    \n    for (const auto& p : mackerels) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].m++;\n        }\n    }\n    for (const auto& p : sardines) {\n        int c = p.x / CELL_SIZE;\n        int r = p.y / CELL_SIZE;\n        if (c >= 0 && c < GW && r >= 0 && r < GH) {\n            grid[r][c].s++;\n        }\n    }\n}\n\n// Build polygon from selected cells\nvector<Point> buildPolygonFromCells() {\n    struct Edge {\n        int x1, y1, x2, y2;\n    };\n    \n    vector<Edge> edges;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                int x1 = c * CELL_SIZE;\n                int y1 = r * CELL_SIZE;\n                int x2 = (c + 1) * CELL_SIZE;\n                int y2 = (r + 1) * CELL_SIZE;\n                \n                if (r == 0 || !selected[r-1][c]) edges.push_back({x1, y1, x2, y1});\n                if (r == GH - 1 || !selected[r+1][c]) edges.push_back({x1, y2, x2, y2});\n                if (c == 0 || !selected[r][c-1]) edges.push_back({x1, y1, x1, y2});\n                if (c == GW - 1 || !selected[r][c+1]) edges.push_back({x2, y1, x2, y2});\n            }\n        }\n    }\n    \n    if (edges.empty()) return {};\n    \n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    for (const auto& e : edges) {\n        adj[{e.x1, e.y1}].push_back({e.x2, e.y2});\n        adj[{e.x2, e.y2}].push_back({e.x1, e.y1});\n    }\n    \n    Point start = {edges[0].x1, edges[0].y1};\n    for (const auto& e : edges) {\n        for (int k = 0; k < 2; k++) {\n            Point p = {k == 0 ? e.x1 : e.x2, k == 0 ? e.y1 : e.y2};\n            if (p.y < start.y || (p.y == start.y && p.x < start.x)) {\n                start = p;\n            }\n        }\n    }\n    \n    vector<Point> poly;\n    Point current = start;\n    Point prev = {-1000000, -1000000};\n    \n    for (int iter = 0; iter < (int)edges.size() * 2 + 10; ++iter) {\n        poly.push_back(current);\n        \n        auto it = adj.find({current.x, current.y});\n        if (it == adj.end()) break;\n        \n        Point next = {-1, -1};\n        long long best_cross = (long long)4e18;\n        \n        for (const auto& neighbor : it->second) {\n            Point np = {neighbor.first, neighbor.second};\n            if (np.x == prev.x && np.y == prev.y) continue;\n            \n            long long dx1 = current.x - prev.x;\n            long long dy1 = current.y - prev.y;\n            long long dx2 = np.x - current.x;\n            long long dy2 = np.y - current.y;\n            long long cross = dx1 * dy2 - dy1 * dx2;\n            \n            if (next.x == -1 || cross < best_cross) {\n                next = np;\n                best_cross = cross;\n            }\n        }\n        \n        if (next.x == -1) break;\n        if (next.x == start.x && next.y == start.y && poly.size() > 3) break;\n        \n        prev = current;\n        current = next;\n    }\n    \n    if (poly.size() > 1 && poly.front() == poly.back()) {\n        poly.pop_back();\n    }\n    \n    return poly;\n}\n\n// Simplify polygon\nvector<Point> simplifyPolygon(const vector<Point>& poly) {\n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> result;\n    result.push_back(poly[0]);\n    \n    for (size_t i = 1; i < poly.size() - 1; ++i) {\n        Point p1 = result.back();\n        Point p2 = poly[i];\n        Point p3 = poly[i + 1];\n        \n        bool collinear = (p1.x == p2.x && p2.x == p3.x) || (p1.y == p2.y && p2.y == p3.y);\n        if (!collinear) result.push_back(p2);\n    }\n    \n    result.push_back(poly.back());\n    \n    vector<Point> final_result;\n    for (const auto& p : result) {\n        if (final_result.empty() || final_result.back() != p) {\n            final_result.push_back(p);\n        }\n    }\n    \n    return final_result;\n}\n\n// Calculate score from grid (fast)\nlong long calculateGridScore() {\n    long long score = 0;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                score += grid[r][c].score();\n            }\n        }\n    }\n    return max(0LL, score + 1);\n}\n\n// Calculate exact score using point-in-polygon\nbool isInside(const vector<Point>& poly, int px, int py) {\n    if (poly.size() < 3) return false;\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        \n        if (xi == xj && px == xi && py >= min(yi, yj) && py <= max(yi, yj)) return true;\n        if (yi == yj && py == yi && px >= min(xi, xj) && px <= max(xi, xj)) return true;\n\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\nlong long calculateExactScore(const vector<Point>& poly) {\n    if (poly.size() < 4) return 0;\n    \n    long long a = 0, b = 0;\n    for (const auto& p : mackerels) {\n        if (isInside(poly, p.x, p.y)) a++;\n    }\n    for (const auto& p : sardines) {\n        if (isInside(poly, p.x, p.y)) b++;\n    }\n    return max(0LL, a - b + 1);\n}\n\n// Validate polygon\nbool validatePolygon(const vector<Point>& poly) {\n    if (poly.size() < 4 || poly.size() > MAX_VERTICES) return false;\n    \n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        \n        if (p1.x != p2.x && p1.y != p2.y) return false;\n        if (p1 == p2) return false;\n        if (p1.x < 0 || p1.x > MAX_COORD || p1.y < 0 || p1.y > MAX_COORD) return false;\n    }\n    \n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    \n    return perim <= MAX_PERIMETER;\n}\n\n// Calculate perimeter of selected region\nlong long calculatePerimeter() {\n    long long perim = 0;\n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (selected[r][c]) {\n                if (r == 0 || !selected[r-1][c]) perim += CELL_SIZE;\n                if (r == GH - 1 || !selected[r+1][c]) perim += CELL_SIZE;\n                if (c == 0 || !selected[r][c-1]) perim += CELL_SIZE;\n                if (c == GW - 1 || !selected[r][c+1]) perim += CELL_SIZE;\n            }\n        }\n    }\n    return perim;\n}\n\n// Fast cell-in-polygon check\nbool cellInsidePolygon(int r, int c, int cell_size, const vector<Point>& poly) {\n    if (poly.size() < 3) return false;\n    int px = c * cell_size + cell_size / 2;\n    int py = r * cell_size + cell_size / 2;\n    \n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        int xi = poly[i].x, yi = poly[i].y;\n        int xj = poly[j].x, yj = poly[j].y;\n        if (((yi > py) != (yj > py)) &&\n            (px < (long long)(xj - xi) * (py - yi) / (yj - yi) + xi)) {\n            inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Grow region\nvector<Point> growRegion(int start_r, int start_c, int cell_size, int negative_threshold = 0) {\n    initGrid(cell_size);\n    \n    for (int r = 0; r < GH; ++r)\n        for (int c = 0; c < GW; ++c)\n            selected[r][c] = false;\n    \n    if (start_r < 0 || start_r >= GH || start_c < 0 || start_c >= GW) return {};\n    \n    selected[start_r][start_c] = true;\n    \n    priority_queue<PQElement> pq;\n    vector<vector<bool>> in_pq(GH, vector<bool>(GW, false));\n    \n    auto addNeighbors = [&](int r, int c) {\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && !selected[nr][nc] && !in_pq[nr][nc]) {\n                in_pq[nr][nc] = true;\n                pq.push({nr, nc, grid[nr][nc].score()});\n            }\n        }\n    };\n    \n    addNeighbors(start_r, start_c);\n    \n    long long current_perimeter = 4LL * CELL_SIZE;\n    \n    int check_interval = 50;\n    int checks = 0;\n    while (!pq.empty()) {\n        if (++checks % check_interval == 0 && !timeRemaining()) break;\n        \n        PQElement top = pq.top();\n        pq.pop();\n        \n        int r = top.r, c = top.c;\n        if (selected[r][c]) continue;\n        if (grid[r][c].score() < negative_threshold) continue;\n        \n        int shared = 0;\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DY[i];\n            int nc = c + DX[i];\n            if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                shared++;\n            }\n        }\n        long long new_perimeter = current_perimeter + 4LL * CELL_SIZE - 2LL * shared * CELL_SIZE;\n        \n        if (new_perimeter > MAX_PERIMETER - 100) continue;\n        \n        selected[r][c] = true;\n        current_perimeter = new_perimeter;\n        \n        addNeighbors(r, c);\n    }\n    \n    vector<Point> poly = buildPolygonFromCells();\n    poly = simplifyPolygon(poly);\n    \n    return poly;\n}\n\n// Local search\nvector<Point> localSearch(vector<Point> poly, int cell_size, int max_iters) {\n    if (poly.size() < 4 || !timeRemaining() || max_iters <= 0) return poly;\n    \n    initGrid(cell_size);\n    for (int r = 0; r < GH; ++r)\n        for (int c = 0; c < GW; ++c)\n            selected[r][c] = false;\n    \n    for (int r = 0; r < GH; ++r) {\n        for (int c = 0; c < GW; ++c) {\n            if (cellInsidePolygon(r, c, cell_size, poly)) {\n                selected[r][c] = true;\n            }\n        }\n    }\n    \n    long long best_score = calculateGridScore();\n    \n    for (int iter = 0; iter < max_iters; ++iter) {\n        if (!timeRemaining()) break;\n        \n        bool improved = false;\n        \n        // Try adding boundary cells with positive score\n        for (int r = 0; r < GH && !improved; ++r) {\n            for (int c = 0; c < GW && !improved; ++c) {\n                if (selected[r][c]) continue;\n                if (grid[r][c].score() <= 0) continue;\n                \n                bool adjacent = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DY[i];\n                    int nc = c + DX[i];\n                    if (nr >= 0 && nr < GH && nc >= 0 && nc < GW && selected[nr][nc]) {\n                        adjacent = true;\n                        break;\n                    }\n                }\n                if (!adjacent) continue;\n                \n                selected[r][c] = true;\n                long long new_perim = calculatePerimeter();\n                if (new_perim <= MAX_PERIMETER) {\n                    long long new_score = calculateGridScore();\n                    if (new_score > best_score) {\n                        best_score = new_score;\n                        improved = true;\n                    } else {\n                        selected[r][c] = false;\n                    }\n                } else {\n                    selected[r][c] = false;\n                }\n            }\n        }\n        \n        if (improved) continue;\n        \n        // Try removing boundary cells with negative score\n        for (int r = 0; r < GH && !improved; ++r) {\n            for (int c = 0; c < GW && !improved; ++c) {\n                if (!selected[r][c]) continue;\n                if (grid[r][c].score() >= 0) continue;\n                \n                bool on_boundary = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DY[i];\n                    int nc = c + DX[i];\n                    if (nr < 0 || nr >= GH || nc < 0 || nc >= GW || !selected[nr][nc]) {\n                        on_boundary = true;\n                        break;\n                    }\n                }\n                if (!on_boundary) continue;\n                \n                selected[r][c] = false;\n                long long new_score = calculateGridScore();\n                if (new_score >= best_score) {\n                    best_score = new_score;\n                    improved = true;\n                } else {\n                    selected[r][c] = true;\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    poly = buildPolygonFromCells();\n    poly = simplifyPolygon(poly);\n    \n    return poly;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    start_time = chrono::high_resolution_clock::now();\n\n    int 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    vector<Point> best_poly;\n    long long best_score = 0;\n    \n    // Proven stable configuration: 6 cell sizes\n    vector<int> cell_sizes = {200, 400, 600, 800, 1000, 1500};\n    \n    for (int cell_size : cell_sizes) {\n        if (!timeRemaining()) break;\n        \n        initGrid(cell_size);\n        \n        // Find candidates\n        vector<pair<int, pair<int, int>>> candidates;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                int sc = grid[r][c].score();\n                if (sc >= 0) {\n                    candidates.push_back({sc, {r, c}});\n                }\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<pair<int, pair<int, int>>>());\n        \n        // Adaptive starting points based on elapsed time (slightly increased)\n        double elapsed = getElapsed();\n        int max_starts = 16;\n        if (elapsed > 1.35) max_starts = 11;\n        if (elapsed > 1.55) max_starts = 7;\n        if (elapsed > 1.70) max_starts = 4;\n        max_starts = min((int)candidates.size(), max_starts);\n        \n        for (int i = 0; i < max_starts && timeRemaining(); ++i) {\n            int r = candidates[i].second.first;\n            int c = candidates[i].second.second;\n            \n            vector<Point> poly = growRegion(r, c, cell_size, 0);\n            \n            if (validatePolygon(poly)) {\n                long long score = calculateGridScore();\n                if (score > best_score) {\n                    best_score = score;\n                    best_poly = poly;\n                }\n                \n                // Local search on top candidates with good time remaining\n                if (i < 3 && elapsed < 1.55 && score >= max(1LL, best_score * 90 / 100)) {\n                    int ls_iters = 15;\n                    if (elapsed > 1.35) ls_iters = 8;\n                    \n                    vector<Point> optimized = localSearch(poly, cell_size, ls_iters);\n                    if (validatePolygon(optimized)) {\n                        long long opt_score = calculateGridScore();\n                        if (opt_score > best_score) {\n                            best_score = opt_score;\n                            best_poly = optimized;\n                        }\n                    }\n                }\n            }\n            \n            // Try negative threshold only for top candidate\n            if (i == 0 && timeRemaining()) {\n                vector<Point> poly2 = growRegion(r, c, cell_size, -2);\n                if (validatePolygon(poly2)) {\n                    long long score2 = calculateGridScore();\n                    if (score2 > best_score) {\n                        best_score = score2;\n                        best_poly = poly2;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback\n    if (best_poly.size() < 4) {\n        initGrid(500);\n        int best_r = 0, best_c = 0, best_cell_score = -1e9;\n        for (int r = 0; r < GH; ++r) {\n            for (int c = 0; c < GW; ++c) {\n                if (grid[r][c].score() > best_cell_score) {\n                    best_cell_score = grid[r][c].score();\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        best_poly = {\n            {best_c * 500, best_r * 500},\n            {(best_c + 1) * 500, best_r * 500},\n            {(best_c + 1) * 500, (best_r + 1) * 500},\n            {best_c * 500, (best_r + 1) * 500}\n        };\n    }\n    \n    if (!validatePolygon(best_poly)) {\n        best_poly = {{0, 0}, {500, 0}, {500, 500}, {0, 500}};\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>\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n    double aspect;\n    long long area;\n};\n\nstruct Placement {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n};\n\nstruct Solution {\n    vector<Placement> placements;\n    long long estimated_score;\n    long long measured_score;\n    int turn_found;\n};\n\nint N;\nvector<Rectangle> rects;\nvector<Placement> placements;\nvector<pair<int, int>> pos;\nvector<pair<int, int>> dim;\n\nstruct TabuEntry {\n    int rect_id;\n    int rotation;\n    char direction;\n    int base;\n    int expire_turn;\n};\nvector<TabuEntry> tabu_list;\nint tabu_tenure = 5;\n\nvoid clear_state() {\n    placements.clear();\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n}\n\nvoid add_placement(int rect_id, int rotation, char direction, int base) {\n    placements.push_back({rect_id, rotation, direction, base});\n}\n\npair<int, int> simulate_fast() {\n    pos.assign(N, {-1, -1});\n    dim.assign(N, {-1, -1});\n    int max_x = 0, max_y = 0;\n    \n    for (size_t idx = 0; idx < placements.size(); idx++) {\n        const auto& p = placements[idx];\n        int w = rects[p.rect_id].w_obs;\n        int h = rects[p.rect_id].h_obs;\n        \n        if (p.rotation == 1) swap(w, h);\n        dim[p.rect_id] = {w, h};\n        \n        int x = 0, y = 0;\n        \n        if (p.direction == 'U') {\n            if (p.base == -1) {\n                x = 0;\n            } else {\n                x = pos[p.base].first + dim[p.base].first;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else {\n            if (p.base == -1) {\n                y = 0;\n            } else {\n                y = pos[p.base].second + dim[p.base].second;\n            }\n            for (size_t i = 0; i < idx; i++) {\n                int rid = placements[i].rect_id;\n                int px = pos[rid].first, py = pos[rid].second;\n                int pw = dim[rid].first, ph = dim[rid].second;\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        pos[p.rect_id] = {x, y};\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\nbool is_tabu(int rect_id, int rotation, char direction, int base, int current_turn) {\n    for (const auto& t : tabu_list) {\n        if (t.rect_id == rect_id && t.expire_turn > current_turn) {\n            if (t.rotation == rotation && t.direction == direction && t.base == base) {\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nvoid add_tabu(int rect_id, int rotation, char direction, int base, int current_turn) {\n    tabu_list.push_back({rect_id, rotation, direction, base, current_turn + tabu_tenure});\n    if (tabu_list.size() > 120) {\n        tabu_list.erase(tabu_list.begin(), tabu_list.begin() + 60);\n    }\n}\n\n// Get boundary rectangles (those touching max_x or max_y)\nvector<int> get_boundary_rects(int max_x, int max_y) {\n    vector<int> boundary;\n    int tolerance = 1000;\n    for (int i = 0; i < N; i++) {\n        if (pos[i].first >= 0) {\n            if (pos[i].first + dim[i].first >= max_x - tolerance ||\n                pos[i].second + dim[i].second >= max_y - tolerance) {\n                boundary.push_back(i);\n            }\n        }\n    }\n    return boundary;\n}\n\nvector<int> get_candidate_bases(int rect_idx, int max_candidates, int strategy = 0, \n                                  int current_max_x = 0, int current_max_y = 0) {\n    vector<int> candidates;\n    candidates.push_back(-1);\n    \n    if (rect_idx == 0) return candidates;\n    \n    vector<pair<long long, int>> scored_bases;\n    for (int i = 0; i < rect_idx && i < N; i++) {\n        if (pos[i].first >= 0) {\n            long long score;\n            if (strategy == 0) {\n                // Corner preference\n                score = (long long)pos[i].first + pos[i].second;\n            } else if (strategy == 1) {\n                // Area preference\n                score = -(long long)dim[i].first * dim[i].second;\n            } else if (strategy == 2) {\n                // Dimension matching\n                int w = rects[rect_idx].w_obs, h = rects[rect_idx].h_obs;\n                score = -abs(dim[i].first - w) - abs(dim[i].second - h);\n            } else {\n                // Boundary preference (prefer rectangles at packaging boundary)\n                bool at_boundary = (pos[i].first + dim[i].first >= current_max_x - 5000) ||\n                                   (pos[i].second + dim[i].second >= current_max_y - 5000);\n                score = at_boundary ? -1000000 : ((long long)pos[i].first + pos[i].second);\n            }\n            scored_bases.push_back({score, i});\n        }\n    }\n    \n    sort(scored_bases.begin(), scored_bases.end());\n    \n    for (int i = 0; i < min((int)scored_bases.size(), max_candidates - 1); i++) {\n        candidates.push_back(scored_bases[i].second);\n    }\n    \n    return candidates;\n}\n\nlong long evaluate_placement() {\n    auto dims = simulate_fast();\n    long long score = (long long)dims.first + dims.second;\n    long long diff = abs(dims.first - dims.second);\n    score += diff / 10;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    auto get_elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    rects.resize(N);\n    long long total_area = 0;\n    int max_dim = 0;\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n        rects[i].aspect = (double)rects[i].w_obs / rects[i].h_obs;\n        rects[i].area = (long long)rects[i].w_obs * rects[i].h_obs;\n        total_area += rects[i].area;\n        max_dim = max(max_dim, max(rects[i].w_obs, rects[i].h_obs));\n    }\n    \n    vector<Solution> population;\n    Solution best_solution;\n    best_solution.measured_score = LLONG_MAX;\n    best_solution.turn_found = -1;\n    \n    // Multiple random seeds for diversity\n    vector<mt19937> rngs;\n    for (int s = 0; s < 3; s++) {\n        rngs.push_back(mt19937(chrono::steady_clock::now().time_since_epoch().count() + s * 1000));\n    }\n    int rng_index = 0;\n    auto& rng = rngs[rng_index];\n    \n    const double TIME_LIMIT = 2.7;\n    \n    int phase1_end = (int)(T * 0.30);  // Exploration\n    int phase2_end = (int)(T * 0.65);  // Intensive SA\n    // phase3: exploitation (35% of turns)\n    \n    int last_improvement_turn = 0;\n    int consecutive_no_improve = 0;\n    \n    for (int turn = 0; turn < T; turn++) {\n        if (get_elapsed() > TIME_LIMIT) {\n            break;\n        }\n        \n        clear_state();\n        \n        double time_remaining = TIME_LIMIT - get_elapsed();\n        \n        // Switch random seed periodically for diversity\n        if (turn > 0 && turn % 10 == 0) {\n            rng_index = (rng_index + 1) % 3;\n        }\n        \n        // Phase 3: Pure exploitation\n        if (turn >= phase2_end) {\n            if (!best_solution.placements.empty()) {\n                placements = best_solution.placements;\n                cout << \"# Turn \" << turn << \" (exploit) best=\" << best_solution.measured_score << \"\\n\";\n                cout << N << \"\\n\";\n                for (const auto& p : placements) {\n                    cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n                }\n                cout.flush();\n                \n                int W_meas, H_meas;\n                cin >> W_meas >> H_meas;\n                long long measured_score = (long long)W_meas + H_meas;\n                \n                if (measured_score < best_solution.measured_score) {\n                    best_solution.measured_score = measured_score;\n                    cout << \"# Updated best: \" << measured_score << \"\\n\";\n                }\n            }\n            continue;\n        }\n        \n        // Adaptive parameters\n        int strategy;\n        int max_bases;\n        int sa_iters;\n        double initial_temp;\n        double cooling_rate;\n        \n        if (turn < phase1_end) {\n            strategy = turn % 4;\n            max_bases = 12;\n            sa_iters = 40;\n            initial_temp = 1200.0;\n            cooling_rate = 0.91;\n        } else {\n            strategy = (turn - phase1_end) % 4;\n            \n            if (turn - last_improvement_turn <= 3) {\n                max_bases = 14;\n                sa_iters = 80;\n                cooling_rate = 0.96;\n            } else if (turn - last_improvement_turn <= 6) {\n                max_bases = 10;\n                sa_iters = 60;\n                cooling_rate = 0.94;\n            } else {\n                max_bases = 8;\n                sa_iters = 50;\n                cooling_rate = 0.92;\n            }\n            initial_temp = 700.0;\n            \n            // Population restart with rotation\n            if (!population.empty() && turn % 2 == 0) {\n                int selection = uniform_int_distribution<>(0, 100)(rng);\n                if (selection < 50 && population.size() >= 1) {\n                    placements = population[0].placements;  // Best\n                } else if (selection < 80 && population.size() >= 2) {\n                    placements = population[uniform_int_distribution<>(0, 1)(rng)].placements;\n                } else if (population.size() >= 1) {\n                    // Mutated version of best\n                    placements = population[0].placements;\n                    int num_mutations = uniform_int_distribution<>(1, N/4)(rng);\n                    for (int m = 0; m < num_mutations; m++) {\n                        int idx = uniform_int_distribution<>(0, N-1)(rng);\n                        int mut_type = uniform_int_distribution<>(0, 2)(rng);\n                        if (mut_type == 0) {\n                            placements[idx].rotation = 1 - placements[idx].rotation;\n                        } else if (mut_type == 1) {\n                            placements[idx].direction = (placements[idx].direction == 'U') ? 'L' : 'U';\n                        } else {\n                            placements[idx].base = -1;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Greedy construction if not restarting\n        if (placements.empty() || (int)placements.size() != N) {\n            clear_state();\n            for (int i = 0; i < N; i++) {\n                int best_rot = 0;\n                char best_dir = 'U';\n                int best_base = -1;\n                long long best_local = LLONG_MAX;\n                \n                auto dims = simulate_fast();\n                vector<int> bases = get_candidate_bases(i, max_bases, strategy, dims.first, dims.second);\n                \n                for (int rot = 0; rot < 2; rot++) {\n                    for (char dir : {'U', 'L'}) {\n                        for (int base : bases) {\n                            if (is_tabu(i, rot, dir, base, turn)) continue;\n                            \n                            add_placement(i, rot, dir, base);\n                            long long score = evaluate_placement();\n                            \n                            if (score < best_local) {\n                                best_local = score;\n                                best_rot = rot;\n                                best_dir = dir;\n                                best_base = base;\n                            }\n                            \n                            placements.pop_back();\n                        }\n                    }\n                }\n                \n                add_placement(i, best_rot, best_dir, best_base);\n            }\n        }\n        \n        // Get current bounding box for boundary detection\n        auto current_dims = simulate_fast();\n        int current_max_x = current_dims.first;\n        int current_max_y = current_dims.second;\n        \n        // Get boundary rectangles for focused modification\n        vector<int> boundary_rects = get_boundary_rects(current_max_x, current_max_y);\n        \n        // Simulated Annealing with Tabu\n        double temperature = initial_temp;\n        long long current_score = evaluate_placement();\n        int actual_sa_iters = min(sa_iters, (int)(time_remaining * 150));\n        \n        for (int sa_iter = 0; sa_iter < actual_sa_iters; sa_iter++) {\n            temperature *= cooling_rate;\n            \n            // Select rectangle to modify (bias toward boundary)\n            int i;\n            if (!boundary_rects.empty() && uniform_real_distribution<>(0, 1)(rng) < 0.75) {\n                i = boundary_rects[uniform_int_distribution<>(0, (int)boundary_rects.size()-1)(rng)];\n            } else {\n                i = uniform_int_distribution<>(0, N-1)(rng);\n            }\n            \n            int orig_rot = placements[i].rotation;\n            char orig_dir = placements[i].direction;\n            int orig_base = placements[i].base;\n            \n            int move_type = uniform_int_distribution<>(0, 2)(rng);\n            vector<int> test_bases = get_candidate_bases(i, 6, strategy, current_max_x, current_max_y);\n            \n            long long new_score = LLONG_MAX;\n            int new_rot = orig_rot;\n            char new_dir = orig_dir;\n            int new_base = orig_base;\n            \n            if (move_type == 0) {\n                int try_rot = 1 - orig_rot;\n                if (!is_tabu(i, try_rot, orig_dir, orig_base, turn)) {\n                    placements[i].rotation = try_rot;\n                    new_score = evaluate_placement();\n                    new_rot = try_rot;\n                }\n            } else if (move_type == 1) {\n                char try_dir = (orig_dir == 'U') ? 'L' : 'U';\n                if (!is_tabu(i, orig_rot, try_dir, orig_base, turn)) {\n                    placements[i].direction = try_dir;\n                    new_score = evaluate_placement();\n                    new_dir = try_dir;\n                }\n            } else if (!test_bases.empty()) {\n                int try_base = test_bases[uniform_int_distribution<>(0, (int)test_bases.size()-1)(rng)];\n                if (!is_tabu(i, orig_rot, orig_dir, try_base, turn)) {\n                    placements[i].base = try_base;\n                    new_score = evaluate_placement();\n                    new_base = try_base;\n                }\n            }\n            \n            if (new_score < LLONG_MAX) {\n                double delta = new_score - current_score;\n                \n                if (delta < 0 || (temperature > 1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(rng))) {\n                    if (delta < 0) {\n                        current_score = new_score;\n                        placements[i].rotation = new_rot;\n                        placements[i].direction = new_dir;\n                        placements[i].base = new_base;\n                    } else {\n                        placements[i].rotation = orig_rot;\n                        placements[i].direction = orig_dir;\n                        placements[i].base = orig_base;\n                    }\n                    add_tabu(i, orig_rot, orig_dir, orig_base, turn);\n                } else {\n                    placements[i].rotation = orig_rot;\n                    placements[i].direction = orig_dir;\n                    placements[i].base = orig_base;\n                }\n            } else {\n                placements[i].rotation = orig_rot;\n                placements[i].direction = orig_dir;\n                placements[i].base = orig_base;\n            }\n        }\n        \n        auto final_dims = simulate_fast();\n        long long estimated_score = (long long)final_dims.first + final_dims.second;\n        \n        cout << \"# Turn \" << turn << \" strat=\" << strategy << \" est=\" << estimated_score \n             << \" time=\" << get_elapsed() << \" pop=\" << population.size() << \"\\n\";\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.rect_id << \" \" << p.rotation << \" \" << p.direction << \" \" << p.base << \"\\n\";\n        }\n        cout.flush();\n        \n        int W_meas, H_meas;\n        cin >> W_meas >> H_meas;\n        long long measured_score = (long long)W_meas + H_meas;\n        \n        if (measured_score < best_solution.measured_score) {\n            best_solution.measured_score = measured_score;\n            best_solution.placements = placements;\n            best_solution.turn_found = turn;\n            best_solution.estimated_score = estimated_score;\n            last_improvement_turn = turn;\n            consecutive_no_improve = 0;\n            cout << \"# *** New best: \" << measured_score << \" turn \" << turn << \" ***\\n\";\n        } else {\n            consecutive_no_improve++;\n        }\n        \n        // Reset tabu if stagnating\n        if (consecutive_no_improve > 5 && turn < phase2_end) {\n            tabu_list.clear();\n            consecutive_no_improve = 0;\n            // Switch to different random seed\n            rng_index = (rng_index + 1) % 3;\n            cout << \"# Tabu reset, switching seed\\n\";\n        }\n        \n        // Add to population (top 5)\n        Solution sol;\n        sol.placements = placements;\n        sol.estimated_score = estimated_score;\n        sol.measured_score = measured_score;\n        sol.turn_found = turn;\n        \n        population.push_back(sol);\n        sort(population.begin(), population.end(), [](const Solution& a, const Solution& b) {\n            return a.estimated_score < b.estimated_score;\n        });\n        if (population.size() > 5) {\n            population.resize(5);\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nstruct Solution {\n    vector<bool> is_root;\n    vector<int> dist;\n    long long score;\n};\n\nSolution run_optimization(int N, int M, int H, const vector<int>& A, \n                          const vector<vector<int>>& adj, \n                          mt19937& rng, double time_limit) {\n    \n    auto start_time = chrono::steady_clock::now();\n    auto get_elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    vector<bool> is_root(N, true);\n    vector<int> dist(N, 0);\n    vector<int> q_arr(N);\n    \n    // Optimized BFS with pre-allocated array\n    auto compute_distances = [&]() -> bool {\n        fill(dist.begin(), dist.end(), -1);\n        int q_head = 0, q_tail = 0;\n        \n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) {\n                dist[i] = 0;\n                q_arr[q_tail++] = i;\n            }\n        }\n        \n        if (q_tail == 0) return false;\n        \n        int max_d = 0;\n        while (q_head < q_tail) {\n            int u = q_arr[q_head++];\n            \n            if (dist[u] > max_d) {\n                max_d = dist[u];\n                if (max_d > H) return false;\n            }\n            \n            for (int v : adj[u]) {\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    q_arr[q_tail++] = v;\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            if (dist[i] == -1 || dist[i] > H) return false;\n        }\n        \n        return true;\n    };\n    \n    auto calc_score = [&]() -> long long {\n        long long score = 1;\n        for (int i = 0; i < N; ++i) {\n            score += (long long)(dist[i] + 1) * A[i];\n        }\n        return score;\n    };\n    \n    compute_distances();\n    long long current_score = calc_score();\n    long long best_score = current_score;\n    vector<bool> best_roots = is_root;\n    vector<int> best_dist = dist;\n    \n    // Phase 1: Fast greedy (single pass)\n    {\n        vector<int> roots;\n        roots.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) roots.push_back(i);\n        }\n        \n        // Sort by beauty descending\n        sort(roots.begin(), roots.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        \n        // Light shuffle on top elements\n        for (size_t i = 0; i < 50 && i < roots.size(); ++i) {\n            size_t j = i + rng() % min((size_t)4, roots.size() - i);\n            swap(roots[i], roots[j]);\n        }\n        \n        for (int u : roots) {\n            if (roots.size() <= 1) break;\n            is_root[u] = false;\n            if (compute_distances()) {\n                long long new_score = calc_score();\n                if (new_score >= current_score) {\n                    current_score = new_score;\n                } else {\n                    is_root[u] = true;\n                }\n            } else {\n                is_root[u] = true;\n            }\n        }\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            best_roots = is_root;\n            best_dist = dist;\n        }\n    }\n    \n    // Phase 2: Simulated Annealing (88% of time)\n    double sa_limit = time_limit * 0.88;\n    double T = 600.0;\n    int iterations = 0;\n    \n    while (get_elapsed() < sa_limit) {\n        double progress = get_elapsed() / sa_limit;\n        T = max(0.001, 600.0 * pow(1.0 - progress, 2.0));\n        \n        // Early exit if temperature is very low\n        if (T < 0.1 && iterations > 1000) break;\n        \n        int move_type = rng() % 4;\n        \n        if (move_type < 3) {\n            // Remove root (75%)\n            vector<int> roots;\n            roots.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n            }\n            \n            if (roots.size() > 1) {\n                int idx;\n                if (rng() % 2 == 0) {\n                    // Beauty-weighted (50%)\n                    int best_idx = 0, best_val = -1;\n                    for (size_t i = 0; i < min((size_t)10, roots.size()); ++i) {\n                        if (A[roots[i]] > best_val) {\n                            best_val = A[roots[i]];\n                            best_idx = i;\n                        }\n                    }\n                    idx = best_idx;\n                } else {\n                    // Random (50%)\n                    idx = rng() % roots.size();\n                }\n                \n                int u = roots[idx];\n                is_root[u] = false;\n                \n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                    }\n                } else {\n                    is_root[u] = true;\n                }\n            }\n        } else {\n            // Swap (25%)\n            vector<int> roots, non_roots;\n            roots.reserve(N);\n            non_roots.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (is_root[i]) roots.push_back(i);\n                else non_roots.push_back(i);\n            }\n            \n            if (!roots.empty() && !non_roots.empty() && roots.size() > 1) {\n                int u = roots[rng() % roots.size()];\n                int w = non_roots[rng() % non_roots.size()];\n                \n                is_root[u] = false;\n                is_root[w] = true;\n                \n                if (compute_distances()) {\n                    long long new_score = calc_score();\n                    double delta = (double)(new_score - current_score);\n                    \n                    if (delta >= 0 || exp(delta / T) > (double)rng() / rng.max()) {\n                        current_score = new_score;\n                        if (current_score > best_score) {\n                            best_score = current_score;\n                            best_roots = is_root;\n                            best_dist = dist;\n                        }\n                    } else {\n                        is_root[u] = true;\n                        is_root[w] = false;\n                    }\n                } else {\n                    is_root[u] = true;\n                    is_root[w] = false;\n                }\n            }\n        }\n        \n        iterations++;\n    }\n    \n    // Phase 3: Simple refinement (12% of time)\n    is_root = best_roots;\n    dist = best_dist;\n    current_score = best_score;\n    \n    while (get_elapsed() < time_limit) {\n        vector<int> roots;\n        roots.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (is_root[i]) roots.push_back(i);\n        }\n        \n        if (roots.size() <= 1) break;\n        \n        int u = roots[rng() % roots.size()];\n        is_root[u] = false;\n        \n        if (compute_distances()) {\n            long long new_score = calc_score();\n            if (new_score > current_score) {\n                current_score = new_score;\n                best_score = current_score;\n                best_roots = is_root;\n                best_dist = dist;\n            } else {\n                is_root[u] = true;\n            }\n        } else {\n            is_root[u] = true;\n        }\n    }\n    \n    Solution sol;\n    sol.is_root = move(best_roots);\n    sol.dist = move(best_dist);\n    sol.score = best_score;\n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\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\n    // Skip coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    unsigned int base_seed = chrono::steady_clock::now().time_since_epoch().count();\n    \n    // Run four optimizations with ~0.48 sec each (proven optimal)\n    mt19937 rng1(base_seed);\n    Solution sol1 = run_optimization(N, M, H, A, adj, rng1, 0.48);\n    \n    mt19937 rng2(base_seed + 54321);\n    Solution sol2 = run_optimization(N, M, H, A, adj, rng2, 0.48);\n    \n    mt19937 rng3(base_seed + 98765);\n    Solution sol3 = run_optimization(N, M, H, A, adj, rng3, 0.48);\n    \n    mt19937 rng4(base_seed + 11111);\n    Solution sol4 = run_optimization(N, M, H, A, adj, rng4, 0.48);\n    \n    // Pick the best solution\n    const Solution* best = &sol1;\n    if (sol2.score > best->score) best = &sol2;\n    if (sol3.score > best->score) best = &sol3;\n    if (sol4.score > best->score) best = &sol4;\n    \n    // Final validation\n    vector<bool> is_root = best->is_root;\n    vector<int> dist = best->dist;\n    vector<int> q_arr(N);\n    \n    // Re-run BFS to ensure dist is correct\n    fill(dist.begin(), dist.end(), -1);\n    int q_head = 0, q_tail = 0;\n    for (int i = 0; i < N; ++i) {\n        if (is_root[i]) {\n            dist[i] = 0;\n            q_arr[q_tail++] = i;\n        }\n    }\n    while (q_head < q_tail) {\n        int u = q_arr[q_head++];\n        for (int v : adj[u]) {\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q_arr[q_tail++] = v;\n            }\n        }\n    }\n    \n    // Fallback if invalid\n    bool valid = true;\n    for (int i = 0; i < N; ++i) {\n        if (dist[i] > H || dist[i] < 0) {\n            valid = false;\n            break;\n        }\n    }\n    \n    if (!valid) {\n        fill(is_root.begin(), is_root.end(), true);\n        fill(dist.begin(), dist.end(), 0);\n    }\n    \n    // Reconstruct parent pointers\n    vector<int> P(N);\n    for (int v = 0; v < N; ++v) {\n        if (is_root[v]) {\n            P[v] = -1;\n        } else {\n            int d = dist[v];\n            int parent = -1;\n            for (int u : adj[v]) {\n                if (dist[u] == d - 1) {\n                    parent = u;\n                    break;\n                }\n            }\n            if (parent == -1) {\n                P[v] = -1;\n            } else {\n                P[v] = parent;\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nint N;\nvector<string> board;\n\nstruct Operation {\n    char dir;\n    int idx;\n    Operation(char d, int i) : dir(d), idx(i) {}\n};\n\nstruct OniInfo {\n    int r, c, dir, cost;\n    OniInfo(int r_, int c_, int d_, int cost_) : r(r_), c(c_), dir(d_), cost(cost_) {}\n};\n\nstruct BatchItem {\n    int r, c, cost;\n    BatchItem(int r_, int c_, int cost_) : r(r_), c(c_), cost(cost_) {}\n};\n\n// Check if direction is safe for removing piece at (r, c)\n// dir: 0=up, 1=down, 2=left, 3=right\nbool is_safe_direction(int r, int c, int dir, const vector<string>& bd) {\n    if (dir == 0) { // up\n        for (int i = 0; i < r; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 1) { // down\n        for (int i = r + 1; i < N; i++) {\n            if (bd[i][c] == 'o') return false;\n        }\n        return true;\n    } else if (dir == 2) { // left\n        for (int j = 0; j < c; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    } else { // right\n        for (int j = c + 1; j < N; j++) {\n            if (bd[r][j] == 'o') return false;\n        }\n        return true;\n    }\n}\n\n// Apply shift operation to board\nvoid apply_shift(vector<string>& bd, char dir, int idx) {\n    if (dir == 'U') {\n        for (int i = 0; i < N - 1; i++) {\n            bd[i][idx] = bd[i + 1][idx];\n        }\n        bd[N - 1][idx] = '.';\n    } else if (dir == 'D') {\n        for (int i = N - 1; i > 0; i--) {\n            bd[i][idx] = bd[i - 1][idx];\n        }\n        bd[0][idx] = '.';\n    } else if (dir == 'L') {\n        for (int j = 0; j < N - 1; j++) {\n            bd[idx][j] = bd[idx][j + 1];\n        }\n        bd[idx][N - 1] = '.';\n    } else if (dir == 'R') {\n        for (int j = N - 1; j > 0; j--) {\n            bd[idx][j] = bd[idx][j - 1];\n        }\n        bd[idx][0] = '.';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n    }\n    \n    vector<Operation> ops;\n    vector<string> current_board = board;\n    \n    // Count Fukunokami in each row and column\n    vector<int> fuku_in_row(N, 0), fuku_in_col(N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (current_board[i][j] == 'o') {\n                fuku_in_row[i]++;\n                fuku_in_col[j]++;\n            }\n        }\n    }\n    \n    while (true) {\n        // Find all remaining Oni\n        vector<OniInfo> oni_list;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (current_board[i][j] == 'x') {\n                    for (int dir = 0; dir < 4; dir++) {\n                        if (is_safe_direction(i, j, dir, current_board)) {\n                            int cost;\n                            if (dir == 0) cost = i + 1;\n                            else if (dir == 1) cost = N - i;\n                            else if (dir == 2) cost = j + 1;\n                            else cost = N - j;\n                            oni_list.emplace_back(i, j, dir, cost);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (oni_list.empty()) break;\n        \n        // Group by (idx, dir) for batch processing\n        // idx is row for left/right (dir 2,3), col for up/down (dir 0,1)\n        vector<vector<BatchItem>> batches(4 * N);\n        \n        for (const auto& oni : oni_list) {\n            int idx = (oni.dir < 2) ? oni.c : oni.r; // col for up/down, row for left/right\n            batches[oni.dir * N + idx].emplace_back(oni.r, oni.c, oni.cost);\n        }\n        \n        // Find best batch: maximize (oni_count / cost)\n        int best_batch = -1;\n        double best_score = -1;\n        int best_max_shift = 0;\n        \n        for (int b = 0; b < 4 * N; b++) {\n            if (batches[b].empty()) continue;\n            \n            int dir = b / N;\n            int idx = b % N;\n            \n            // Calculate cost for this batch\n            int max_shift = 0;\n            for (const auto& item : batches[b]) {\n                max_shift = max(max_shift, item.cost);\n            }\n            \n            // Check if we need to restore (if there are Fukunokami in this row/col)\n            int restore_cost = 0;\n            if (dir < 2) { // column operation\n                if (fuku_in_col[idx] > 0) restore_cost = max_shift;\n            } else { // row operation\n                if (fuku_in_row[idx] > 0) restore_cost = max_shift;\n            }\n            \n            int total_cost = max_shift + restore_cost;\n            int count = batches[b].size();\n            \n            double score = (double)count / total_cost;\n            if (score > best_score) {\n                best_score = score;\n                best_batch = b;\n                best_max_shift = max_shift;\n            }\n        }\n        \n        if (best_batch == -1) break;\n        \n        int dir = best_batch / N;\n        int idx = best_batch % N;\n        auto& batch = batches[best_batch];\n        \n        // Sort batch by cost (remove closest to edge first)\n        sort(batch.begin(), batch.end(), [](const BatchItem& a, const BatchItem& b) {\n            return a.cost < b.cost;\n        });\n        \n        // Determine shift direction character\n        char shift_dir, restore_dir;\n        if (dir == 0) { shift_dir = 'U'; restore_dir = 'D'; }\n        else if (dir == 1) { shift_dir = 'D'; restore_dir = 'U'; }\n        else if (dir == 2) { shift_dir = 'L'; restore_dir = 'R'; }\n        else { shift_dir = 'R'; restore_dir = 'L'; }\n        \n        // Apply shifts\n        for (int k = 0; k < best_max_shift; k++) {\n            ops.emplace_back(shift_dir, idx);\n            apply_shift(current_board, shift_dir, idx);\n        }\n        \n        // Update Fukunokami counts\n        if (dir < 2) {\n            // Column operation - Fukunokami in this column may have shifted or been removed\n            int new_count = 0;\n            for (int i = 0; i < N; i++) {\n                if (current_board[i][idx] == 'o') new_count++;\n            }\n            fuku_in_col[idx] = new_count;\n        } else {\n            // Row operation\n            int new_count = 0;\n            for (int j = 0; j < N; j++) {\n                if (current_board[idx][j] == 'o') new_count++;\n            }\n            fuku_in_row[idx] = new_count;\n        }\n        \n        // Restore if needed\n        if ((dir < 2 && fuku_in_col[idx] > 0) || (dir >= 2 && fuku_in_row[idx] > 0)) {\n            for (int k = 0; k < best_max_shift; k++) {\n                ops.emplace_back(restore_dir, idx);\n                apply_shift(current_board, restore_dir, idx);\n            }\n        }\n    }\n    \n    // Output operations\n    for (auto& op : ops) {\n        cout << op.dir << \" \" << op.idx << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    long long L;\n    cin >> N >> L;\n    \n    vector<long long> T(N);\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n    \n    // Use fixed seed for reproducibility, or time-based for variety\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Create weighted candidate distribution based on target frequencies\n    vector<int> weighted_candidates;\n    for (int i = 0; i < N; i++) {\n        // Higher target = more likely to be chosen as next cleaner\n        int weight = max(1, (int)(T[i] / 500 + 1));\n        for (int j = 0; j < weight; j++) {\n            weighted_candidates.push_back(i);\n        }\n    }\n    \n    // Initialize a and b arrays\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; i++) {\n        a[i] = weighted_candidates[rng() % weighted_candidates.size()];\n        b[i] = weighted_candidates[rng() % weighted_candidates.size()];\n    }\n    \n    // Simulation function\n    auto simulate = [&]() -> vector<long long> {\n        vector<long long> count(N, 0);\n        int current = 0;\n        \n        for (long long week = 0; week < L; week++) {\n            count[current]++;\n            // t = count[current] is the number of times current has cleaned\n            // If t is odd (1st, 3rd, 5th...), use a[current]\n            // If t is even (2nd, 4th, 6th...), use b[current]\n            if (count[current] % 2 == 1) {\n                current = a[current];\n            } else {\n                current = b[current];\n            }\n        }\n        \n        return count;\n    };\n    \n    // Error calculation\n    auto calcError = [&](const vector<long long>& actual) -> long long {\n        long long error = 0;\n        for (int i = 0; i < N; i++) {\n            error += abs(actual[i] - T[i]);\n        }\n        return error;\n    };\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_error = 1e18;\n    vector<int> best_a = a, best_b = b;\n    \n    // Main optimization loop\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        \n        // Stop with buffer time for output\n        if (elapsed > 1950) break;\n        \n        // Evaluate current solution\n        vector<long long> actual = simulate();\n        long long error = calcError(actual);\n        \n        // Track best solution\n        if (error < best_error) {\n            best_error = error;\n            best_a = a;\n            best_b = b;\n        }\n        \n        // Local search: modify one parameter\n        int i = rng() % N;\n        int choice = rng() % 2;  // 0 = modify a[i], 1 = modify b[i]\n        int old_val = (choice == 0) ? a[i] : b[i];\n        \n        // Try new value from weighted candidates\n        int new_val = weighted_candidates[rng() % weighted_candidates.size()];\n        \n        if (choice == 0) {\n            a[i] = new_val;\n        } else {\n            b[i] = new_val;\n        }\n        \n        // Evaluate new solution\n        vector<long long> new_actual = simulate();\n        long long new_error = calcError(new_actual);\n        \n        // Simulated annealing acceptance criterion\n        if (new_error < error) {\n            // Always accept improvements\n        } else {\n            // Accept worse solutions with decreasing probability over time\n            double progress = (double)elapsed / 2000.0;\n            double temperature = 1000.0 * (1.0 - progress);\n            temperature = max(1.0, temperature);\n            \n            double acceptance_prob = exp(-(double)(new_error - error) / temperature);\n            \n            if ((double)rng() / rng.max() > acceptance_prob) {\n                // Revert change\n                if (choice == 0) {\n                    a[i] = old_val;\n                } else {\n                    b[i] = old_val;\n                }\n            }\n        }\n    }\n    \n    // Output best solution found\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 <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <chrono>\n#include <random>\n#include <iomanip>\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 weight;\n    double confidence; // 1.0 for query edges, <1.0 for estimated\n    bool fromQuery;\n};\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(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        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        return true;\n    }\n};\n\n// Hilbert curve distance for better spatial locality\nint hilbertDist(int x, int y, int order = 14) {\n    int d = 0;\n    for (int s = 1 << (order - 1); s > 0; s >>= 1) {\n        int rx = (x & s) > 0;\n        int ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (rx == 0) {\n            if (ry == 1) {\n                x = (1 << order) - 1 - x;\n                y = (1 << order) - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// Minimum possible distance between two rectangles\nint minRectDist(const City& a, const City& b) {\n    int dx = 0, dy = 0;\n    if (a.rx < b.lx) dx = b.lx - a.rx;\n    else if (b.rx < a.lx) dx = a.lx - b.rx;\n    \n    if (a.ry < b.ly) dy = b.ly - a.ry;\n    else if (b.ry < a.ly) dy = a.ly - b.ry;\n    \n    return (int)floor(sqrt(dx * dx + dy * dy));\n}\n\n// Estimated distance using centers (more optimistic)\nint centerDist(const City& a, const City& b) {\n    double dx = a.cx - b.cx;\n    double dy = a.cy - b.cy;\n    return (int)floor(sqrt(dx * dx + dy * dy));\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, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    \n    vector<int> G(M);\n    for (int i = 0; i < M; i++) {\n        cin >> G[i];\n    }\n    \n    vector<City> cities(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 Hilbert curve distance for better spatial locality\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int ha = hilbertDist((int)cities[a].cx, (int)cities[a].cy);\n        int hb = hilbertDist((int)cities[b].cx, (int)cities[b].cy);\n        return ha < hb;\n    });\n    \n    // Assign cities to groups based on spatial ordering\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n    \n    // Track all known edges globally\n    map<pair<int,int>, Edge> knownEdges;\n    vector<vector<pair<int,int>>> groupEdges(M);\n    \n    int queriesUsed = 0;\n    \n    // Calculate query priority for each group\n    // Larger groups and groups with higher uncertainty get more queries\n    vector<pair<double, int>> groupPriority(M);\n    for (int i = 0; i < M; i++) {\n        int size = groups[i].size();\n        if (size < 2) {\n            groupPriority[i] = {0.0, i};\n            continue;\n        }\n        // Priority based on: number of edges needed * uncertainty\n        double uncertainty = 0;\n        for (int j = 0; j < size && j < 10; j++) {\n            for (int k = j + 1; k < size && k < 10; k++) {\n                int minD = minRectDist(cities[groups[i][j]], cities[groups[i][k]]);\n                int cenD = centerDist(cities[groups[i][j]], cities[groups[i][k]]);\n                uncertainty += (cenD - minD + 1);\n            }\n        }\n        // More edges needed = higher priority\n        groupPriority[i] = {(size - 1) * (1.0 + uncertainty / 100.0), i};\n    }\n    sort(groupPriority.begin(), groupPriority.end(), greater<pair<double,int>>());\n    \n    // Query each group strategically\n    for (auto& [priority, gi] : groupPriority) {\n        // Time check - leave margin for output\n        auto currentTime = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(currentTime - startTime).count();\n        if (elapsed > 1850 || queriesUsed >= Q) break;\n        \n        int groupSize = groups[gi].size();\n        if (groupSize < 2) continue;\n        \n        // Calculate how many queries we can use for this group\n        int edgesNeeded = groupSize - 1;\n        int maxQueriesForGroup = min((Q - queriesUsed), (edgesNeeded + L - 2) / (L - 1));\n        \n        // Ensure we cover all cities in the group\n        vector<bool> covered(groupSize, false);\n        int queriesForThisGroup = 0;\n        \n        // First pass: ensure all cities are covered\n        for (int start = 0; start < groupSize && queriesForThisGroup < maxQueriesForGroup && queriesUsed < Q; ) {\n            int remaining = groupSize - start;\n            int chunkSize = min(L, remaining);\n            \n            if (chunkSize < 2) {\n                // Connect remaining city to previous\n                if (start > 0 && start < groupSize) {\n                    int u = groups[gi][start - 1];\n                    int v = groups[gi][start];\n                    if (u > v) swap(u, v);\n                    if (knownEdges.find({u, v}) == knownEdges.end()) {\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 0.5, false};\n                    }\n                }\n                break;\n            }\n            \n            // Make query\n            cout << \"?\" << \" \" << chunkSize;\n            for (int i = 0; i < chunkSize; i++) {\n                cout << \" \" << groups[gi][start + i];\n                covered[start + i] = true;\n            }\n            cout << endl;\n            cout.flush();\n            \n            queriesUsed++;\n            queriesForThisGroup++;\n            \n            // Read MST edges from response\n            for (int i = 0; i < chunkSize - 1; i++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                \n                // Mark as high confidence query edge\n                knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n            }\n            \n            // Move forward, overlap by 1 to ensure connectivity\n            start += chunkSize - 1;\n        }\n        \n        // Second pass: cover any missed cities with small queries\n        for (int i = 0; i < groupSize && queriesUsed < Q; i++) {\n            if (!covered[i]) {\n                // Find nearest covered city to query with\n                int bestJ = -1;\n                int bestDist = 1e9;\n                for (int j = 0; j < groupSize; j++) {\n                    if (covered[j] && j != i) {\n                        int d = centerDist(cities[groups[gi][i]], cities[groups[gi][j]]);\n                        if (d < bestDist) {\n                            bestDist = d;\n                            bestJ = j;\n                        }\n                    }\n                }\n                \n                if (bestJ >= 0) {\n                    int chunkSize = 2;\n                    if (queriesUsed < Q - 1) {\n                        // Try to add one more city if possible\n                        for (int k = 0; k < groupSize && chunkSize < L; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                chunkSize++;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    cout << \"?\" << \" \" << chunkSize << \" \" << groups[gi][i];\n                    int count = 1;\n                    if (count < chunkSize) {\n                        cout << \" \" << groups[gi][bestJ];\n                        count++;\n                        for (int k = 0; k < groupSize && count < chunkSize; k++) {\n                            if (k != i && k != bestJ && covered[k]) {\n                                cout << \" \" << groups[gi][k];\n                                count++;\n                            }\n                        }\n                    }\n                    cout << endl;\n                    cout.flush();\n                    \n                    queriesUsed++;\n                    \n                    for (int e = 0; e < chunkSize - 1; e++) {\n                        int u, v;\n                        cin >> u >> v;\n                        if (u > v) swap(u, v);\n                        knownEdges[{u, v}] = {u, v, centerDist(cities[u], cities[v]), 1.0, true};\n                    }\n                    covered[i] = true;\n                }\n            }\n        }\n    }\n    \n    // Build complete MST for each group using all available edges\n    for (int g = 0; g < M; g++) {\n        int groupSize = groups[g].size();\n        if (groupSize < 2) continue;\n        \n        vector<Edge> allEdges;\n        set<pair<int,int>> added;\n        \n        // Add all known edges for cities in this group\n        for (auto& [key, edge] : knownEdges) {\n            bool inGroup = false;\n            for (int city : groups[g]) {\n                if (city == edge.u || city == edge.v) {\n                    inGroup = true;\n                    break;\n                }\n            }\n            if (!inGroup) continue;\n            \n            // Check both endpoints are in this group\n            bool uIn = false, vIn = false;\n            for (int city : groups[g]) {\n                if (city == edge.u) uIn = true;\n                if (city == edge.v) vIn = true;\n            }\n            if (!uIn || !vIn) continue;\n            \n            if (added.find({edge.u, edge.v}) == added.end()) {\n                allEdges.push_back(edge);\n                added.insert({edge.u, edge.v});\n            }\n        }\n        \n        // Add estimated edges for missing connections\n        for (int i = 0; i < groupSize; i++) {\n            for (int j = i + 1; j < groupSize; j++) {\n                int u = groups[g][i];\n                int v = groups[g][j];\n                if (u > v) swap(u, v);\n                \n                if (added.find({u, v}) == added.end()) {\n                    int minD = minRectDist(cities[u], cities[v]);\n                    int cenD = centerDist(cities[u], cities[v]);\n                    // Use weighted average of min and center distance\n                    int estD = (minD + cenD) / 2;\n                    allEdges.push_back({u, v, estD, 0.3, false});\n                    added.insert({u, v});\n                }\n            }\n        }\n        \n        // Build MST - prefer query edges (high confidence), then by weight\n        sort(allEdges.begin(), allEdges.end(), [&](const Edge& a, const Edge& b) {\n            if (a.fromQuery != b.fromQuery) return a.fromQuery > b.fromQuery;\n            if (abs(a.confidence - b.confidence) > 0.1) return a.confidence > b.confidence;\n            return a.weight < b.weight;\n        });\n        \n        vector<pair<int,int>> mstEdges;\n        DSU dsu(N);\n        \n        for (auto& e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                mstEdges.push_back({e.u, e.v});\n                if ((int)mstEdges.size() == groupSize - 1) break;\n            }\n        }\n        \n        // Fallback: if MST is incomplete, add any remaining edges\n        if ((int)mstEdges.size() < groupSize - 1) {\n            DSU dsu2(N);\n            for (auto& e : mstEdges) {\n                dsu2.unite(e.first, e.second);\n            }\n            for (auto& e : allEdges) {\n                if (dsu2.unite(e.u, e.v)) {\n                    mstEdges.push_back({e.u, e.v});\n                    if ((int)mstEdges.size() == groupSize - 1) break;\n                }\n            }\n        }\n        \n        groupEdges[g] = mstEdges;\n    }\n    \n    // Output final answer\n    cout << \"!\" << endl;\n    cout.flush();\n    \n    for (int g = 0; g < M; g++) {\n        // Output cities in group\n        for (int i = 0; i < (int)groups[g].size(); i++) {\n            if (i > 0) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : groupEdges[g]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint cur_i, cur_j;\nvector<pair<int, int>> targets;\nset<pair<int, int>> blocks;\n\n// Direction arrays at global scope\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nbool isValid(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N && blocks.find({i, j}) == blocks.end();\n}\n\npair<int, int> getSlideEnd(int i, int j, int di, int dj) {\n    while (true) {\n        int ni = i + di, nj = j + dj;\n        if (!isValid(ni, nj)) break;\n        i = ni;\n        j = nj;\n    }\n    return {i, j};\n}\n\nint manhattan(int i1, int j1, int i2, int j2) {\n    return abs(i1 - i2) + abs(j1 - j2);\n}\n\nvoid solve() {\n    cin >> N >> M;\n    cin >> cur_i >> cur_j;\n    for (int k = 0; k < M; k++) {\n        int i, j;\n        cin >> i >> j;\n        targets.push_back({i, j});\n    }\n    \n    vector<pair<char, char>> allActions;\n    \n    for (int t = 0; t < M; t++) {\n        int ti = targets[t].first;\n        int tj = targets[t].second;\n        vector<pair<char, char>> targetActions;\n        \n        // Simple BFS to find path to target\n        queue<tuple<int, int, vector<pair<char, char>>>> q;\n        vector<pair<char, char>> emptyPath;\n        q.push({cur_i, cur_j, emptyPath});\n        \n        set<pair<int, int>> visited;\n        visited.insert({cur_i, cur_j});\n        bool found = false;\n        \n        int maxDepth = 200;\n        \n        while (!q.empty() && !found) {\n            auto [pi, pj, path] = q.front();\n            q.pop();\n            \n            if ((int)path.size() > maxDepth) continue;\n            \n            if (pi == ti && pj == tj) {\n                targetActions = path;\n                found = true;\n                break;\n            }\n            \n            // Try moves\n            for (int d = 0; d < 4; d++) {\n                int ni = pi + DI[d], nj = pj + DJ[d];\n                \n                if (isValid(ni, nj) && !visited.count({ni, nj})) {\n                    visited.insert({ni, nj});\n                    auto newPath = path;\n                    newPath.emplace_back('M', DIR_CHAR[d]);\n                    q.push({ni, nj, newPath});\n                }\n                \n                // Try slides\n                auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                if ((si != pi || sj != pj) && !visited.count({si, sj})) {\n                    visited.insert({si, sj});\n                    auto newPath = path;\n                    newPath.emplace_back('S', DIR_CHAR[d]);\n                    q.push({si, sj, newPath});\n                }\n            }\n        }\n        \n        // Fallback: greedy approach if BFS fails\n        if (!found) {\n            int pi = cur_i, pj = cur_j;\n            \n            while (pi != ti || pj != tj) {\n                bool moved = false;\n                \n                // Try slides first\n                for (int d = 0; d < 4; d++) {\n                    auto [si, sj] = getSlideEnd(pi, pj, DI[d], DJ[d]);\n                    \n                    if (si == ti && sj == tj) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                    \n                    int oldDist = manhattan(pi, pj, ti, tj);\n                    int newDist = manhattan(si, sj, ti, tj);\n                    \n                    if (newDist < oldDist && (si != pi || sj != pj)) {\n                        targetActions.emplace_back('S', DIR_CHAR[d]);\n                        pi = si;\n                        pj = sj;\n                        moved = true;\n                        break;\n                    }\n                }\n                \n                if (!moved) {\n                    // Use move\n                    if (pi < ti) {\n                        targetActions.emplace_back('M', 'D');\n                        pi++;\n                    } else if (pi > ti) {\n                        targetActions.emplace_back('M', 'U');\n                        pi--;\n                    } else if (pj < tj) {\n                        targetActions.emplace_back('M', 'R');\n                        pj++;\n                    } else if (pj > tj) {\n                        targetActions.emplace_back('M', 'L');\n                        pj--;\n                    }\n                }\n                \n                if ((int)targetActions.size() > maxDepth) break;\n            }\n        }\n        \n        // Execute actions and update blocks\n        for (auto& action : targetActions) {\n            char act = action.first;\n            char dir = action.second;\n            \n            if (act == 'M') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        cur_i += DI[d];\n                        cur_j += DJ[d];\n                        break;\n                    }\n                }\n            } else if (act == 'S') {\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        tie(cur_i, cur_j) = getSlideEnd(cur_i, cur_j, DI[d], DJ[d]);\n                        break;\n                    }\n                }\n            } else if (act == 'A') {\n                int bi = cur_i, bj = cur_j;\n                for (int d = 0; d < 4; d++) {\n                    if (DIR_CHAR[d] == dir) {\n                        bi += DI[d];\n                        bj += DJ[d];\n                        break;\n                    }\n                }\n                if (blocks.count({bi, bj})) blocks.erase({bi, bj});\n                else blocks.insert({bi, bj});\n            }\n            allActions.emplace_back(act, dir);\n        }\n    }\n    \n    for (auto& action : allActions) {\n        cout << action.first << \" \" << action.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}"}}}