Submission #32167323


Source Code Expand

#include <bits/stdc++.h>
using pii=std::pair<int,int>;
using namespace std;

const int maxnsq = 105, GRID_CHOOSE_TIMEOUT_MILLIS = 1400, OVERALL_SAFETY_TIMEOUT_MILLIS = 2700;

enum direction { left_bit, up_bit, right_bit, down_bit };
vector<int> direction_iterable = {left_bit, up_bit, right_bit, down_bit};
pii dirs[4] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
map<pii, char> movement_to_direction_character_map = {
    {{0, -1}, 'L'}, 
    {{-1, 0}, 'U'}, 
    {{0, 1}, 'R'}, 
    {{1, 0}, 'D'}
};

class InvalidStateException : public exception
{
    string _msg;
  public:
    InvalidStateException(const string& msg) : _msg(msg) {}

    virtual const char* what() const noexcept override { return _msg.c_str(); }
}; 

class SlidingPuzzleSolverState
{
  public:
    int n, good = 0;
    string ans;
    vector<vector<int>> current, target, fixed;
    SlidingPuzzleSolverState(int _n, vector<vector<int>> _current, vector<vector<int>> _target) : 
        n(_n), 
        current(_current), 
        target (_target)
    {
        fixed.resize(n, vector<int>(n, 0));
    }
};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
int n, t;

int is_valid(int x, int y)
{
    return x >= 0 && x < n && y >= 0 && y < n;
}

int is_valid_for_grid_generator(int x, int y)
{
    return is_valid(x, y) && !(x == 0 && y == 0);
}

int cnt_adjacent_connecting(int mask, int x, int y, vector<vector<int>>& grid_masks)
{
    int adj_cnt = 0;
    for(auto dir_bit : direction_iterable)
        if(mask & (1ll << dir_bit))
        {
            int nex = x + dirs[dir_bit].first;
            int ney = y + dirs[dir_bit].second;
            if(!is_valid_for_grid_generator(nex, ney))
                continue;
            int connecting_dir_bit = (dir_bit + 2) % 4;
            if(grid_masks[nex][ney] & (1ll << connecting_dir_bit))
                adj_cnt++;
        }
    return adj_cnt;
}

int has_adjacent_connecting(int x, int y, vector<vector<int>>& grid_masks)
{
    return cnt_adjacent_connecting(15, x, y, grid_masks) > 0;
}

int is_good_placement(int mask, int curx, int cury, int fromx, int fromy, vector<vector<int>>& grid_masks)
{
    int from_valid = (fromx == -1 && fromy == -1);
    for(auto dir_bit : direction_iterable)
        if(mask & (1ll << dir_bit))
        {
            int nex = curx + dirs[dir_bit].first;
            int ney = cury + dirs[dir_bit].second;
            if(nex == fromx && ney == fromy)
            {
                from_valid = 1;
                continue;
            }
            if(!is_valid_for_grid_generator(nex, ney) || grid_masks[nex][ney] != 0 || has_adjacent_connecting(nex, ney, grid_masks))
                return 0;
        }
    return from_valid;
}

template <typename T> T random_order(T original_list)
{
    shuffle(original_list.begin(), original_list.end(), rng);
    return original_list;
}

pair<vector<vector<int>>, int> get_random_tree(vector<int> mask_cnts)
{
    vector<vector<int>> grid_masks(n, vector<int>(n, 0));
    int comp_sz = 0;

    vector<vector<int>> visited(n, vector<int>(n));
    vector<int> mask_order(15);
    iota(mask_order.begin(), mask_order.end(), 1);
    shuffle(mask_order.begin(), mask_order.end(), rng);
    sort(mask_order.begin(), mask_order.end(), [](const int& m1, const int& m2) {
        return __builtin_popcount(m1) > __builtin_popcount(m2);
    });

    int startx = uniform_int_distribution<int>(0, n - 1)(rng);
    int starty = uniform_int_distribution<int>(0, n - 1)(rng);
    while(startx == 0 && starty == 0)
    {
        startx = uniform_int_distribution<int>(0, n - 1)(rng);
        starty = uniform_int_distribution<int>(0, n - 1)(rng);
    }
    stack<pair<pii, pii>> s; // {{curx, cury}, {fromx, fromy}}
    s.push({{startx, starty}, {-1, -1}});
    visited[startx][starty] = 1;
    while(!s.empty())
    {
        int curx, cury, fromx, fromy;
        tie(curx, cury) = s.top().first;
        tie(fromx, fromy) = s.top().second;
        s.pop();
        for(auto mask : mask_order)
            if(mask_cnts[mask] > 0 && is_good_placement(mask, curx, cury, fromx, fromy, grid_masks))
            {
                grid_masks[curx][cury] = mask;
                mask_cnts[mask]--;
                for(auto dir_bit : random_order(direction_iterable))
                    if(mask & (1ll << dir_bit))
                    {
                        int nex = curx + dirs[dir_bit].first;
                        int ney = cury + dirs[dir_bit].second;
                        if(nex == fromx && ney == fromy)
                            continue;
                        assert(!visited[nex][ney]);
                        visited[nex][ney] = 1;
                        s.push({{nex, ney}, {curx, cury}});
                    }
                comp_sz++;
                break;
            }
    }
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(!(i == 0 && j == 0) && grid_masks[i][j] == 0)
                for(int mask = 1; mask <= 15; mask++)
                    if(mask_cnts[mask] > 0 && cnt_adjacent_connecting(mask, i, j, grid_masks) == 1)
                    {
                        grid_masks[i][j] = mask;
                        mask_cnts[mask]--;
                        comp_sz++;
                        break;
                    }
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(!(i == 0 && j == 0) && grid_masks[i][j] == 0)
                for(int mask = 1; mask <= 15; mask++)
                    if(mask_cnts[mask] > 0)
                    {
                        grid_masks[i][j] = mask;
                        mask_cnts[mask]--;
                        break;
                    }
    return {grid_masks, comp_sz};
}

void calc_shortest_path(int fromx, int fromy, vector<vector<int>>& dist, vector<vector<pii>>& from, vector<vector<int>>& fixed)
{
    assert(is_valid(fromx, fromy) && !fixed[fromx][fromy]);
    queue<pii> q;
    dist[fromx][fromy] = 0;
    q.push({fromx, fromy});
    while(!q.empty())
    {
        int curx, cury;
        tie(curx, cury) = q.front();
        q.pop();
        for(auto ne : dirs)
        {
            int nex = curx + ne.first;
            int ney = cury + ne.second;
            if(is_valid(nex, ney) && !fixed[nex][ney] && dist[curx][cury] + 1 < dist[nex][ney])
            {
                dist[nex][ney] = dist[curx][cury] + 1;
                from[nex][ney] = {curx, cury};
                q.push({nex, ney});
            }
        }
    }
}

vector<pii> recover_path(int tox, int toy, vector<vector<pii>>& from)
{
    vector<pii> path;
    int atx = tox, aty = toy;
    do
    {
        path.push_back({atx, aty});
        tie(atx, aty) = from[atx][aty];
    } while(make_pair(atx, aty) != make_pair(-1, -1));
    reverse(path.begin(), path.end());
    return path;
}

vector<pii> get_shortest_path(int fromx, int fromy, int tox, int toy, vector<vector<int>>& fixed)
{
    assert(is_valid(fromx, fromy) && is_valid(tox, toy) && !fixed[fromx][fromy] && !fixed[tox][toy]);
    vector<vector<int>> dist(n, vector<int>(n, 2e9));
    vector<vector<pii>> from(n, vector<pii>(n, {-1, -1}));
    
    calc_shortest_path(fromx, fromy, dist, from, fixed);
    return recover_path(tox, toy, from);
}

vector<pii> get_path_from_closest_occurance(int tox, int toy, int target_value, vector<vector<int>>& current_grid, vector<vector<int>>& fixed)
{
    assert(is_valid(tox, toy) && !fixed[tox][toy]);
    vector<vector<int>> dist(n, vector<int>(n, 2e9));
    vector<vector<pii>> from(n, vector<pii>(n, {-1, -1}));
    
    calc_shortest_path(tox, toy, dist, from, fixed);
    int fromx = -1, fromy = -1;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(current_grid[i][j] == target_value && ((fromx == -1 && fromy == -1) || dist[i][j] < dist[fromx][fromy]))
            {
                fromx = i;
                fromy = j;
            }
    assert(fromx != -1 && fromy != -1);
    vector<pii> result = recover_path(fromx, fromy, from);
    reverse(result.begin(), result.end());
    return result;
}

string apply_and_get_operation_string(vector<pii> path, vector<vector<int>>& current_grid)
{
    assert(!path.empty());
    int current_start_val = current_grid[path[0].first][path[0].second];
    string ops;
    for(int i = 1; i < path.size(); i++)
    {
        int movex = path[i].first - path[i - 1].first;
        int movey = path[i].second - path[i - 1].second;
        assert(movement_to_direction_character_map.count({movex, movey}));
        ops += movement_to_direction_character_map[{movex, movey}];
        current_grid[path[i - 1].first][path[i - 1].second] = current_grid[path[i].first][path[i].second];
    }
    current_grid[path.back().first][path.back().second] = current_start_val;
    return ops;
}

string move_cell(vector<pii> path, vector<vector<int>>& current_grid, vector<vector<int>>& fixed, int& empty_cell_x, int& empty_cell_y)
{
    assert(!path.empty());
    int tox = path.back().first, toy = path.back().second;
    int target_value = current_grid[path[0].first][path[0].second];
    assert(target_value != 0);  // Use apply_and_get_operation_string to move the empty cell, move_cell is only for non-empty cells.
    string ops;
    for(int i = 1; i < path.size(); i++)
    {
        // Protect the value we intend to move (currently at path[i - 1]), so we don't accidentally change its position while moving the empty cell.
        fixed[path[i - 1].first][path[i - 1].second] = 1;
        // Move empty cell to target cell (the adjacent cell we intended to move the value to)
        assert(current_grid[empty_cell_x][empty_cell_y] == 0);
        ops += apply_and_get_operation_string(get_shortest_path(empty_cell_x, empty_cell_y, path[i].first, path[i].second, fixed), current_grid);
        if(current_grid[path[i].first][path[i].second] != 0)
            throw InvalidStateException("Empty cell can't be moved to required position!");
        fixed[path[i - 1].first][path[i - 1].second] = 0;
        ops += apply_and_get_operation_string({path[i], path[i - 1]}, current_grid);
        tie(empty_cell_x, empty_cell_y) = path[i - 1];
        assert(current_grid[empty_cell_x][empty_cell_y] == 0);
    }
    assert(current_grid[tox][toy] == target_value);
    return ops;
}

string fix_row(int idx, vector<vector<int>>& current, vector<vector<int>>& target, vector<vector<int>>& fixed, int& empty_cell_x, int& empty_cell_y, int safe_mode)
{
    int move_back_value = (safe_mode) ? 0 : idx - 3;

    string ans;
    // Fix last row
    for(int j = idx; j > 1; j--)
        if(!fixed[idx][j])
        {
            ans += move_cell(get_path_from_closest_occurance(idx, j, target[idx][j], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
            fixed[idx][j] = 1;
        }
    if(!fixed[idx][0] || !fixed[idx][1])
    {
        // Handle first two columns of last row
        // Written this way to prevent issues in some cases where the needed value gets stuck in the last row after the first move.
        ans += move_cell(get_path_from_closest_occurance(move_back_value, 0, target[idx][0], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[move_back_value][0] = 1;
        ans += move_cell(get_path_from_closest_occurance(idx, 0, target[idx][1], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[move_back_value][0] = 0;
        fixed[idx][0] = 1;
        ans += move_cell(get_shortest_path(move_back_value, 0, idx - 1, 0, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[idx - 1][0] = 1;
        ans += apply_and_get_operation_string(get_shortest_path(empty_cell_x, empty_cell_y, idx, 1, fixed), current);
        fixed[idx][0] = fixed[idx - 1][0] = 0;
        empty_cell_x = idx - 1;
        empty_cell_y = 0;
        ans += apply_and_get_operation_string({make_pair(idx, 1), make_pair(idx, 0), make_pair(idx - 1, 0)}, current);
        assert(current[idx][0] == target[idx][0] && current[idx][1] == target[idx][1]);
        fixed[idx][0] = fixed[idx][1] = 1;
    }
    return ans;
}

string fix_col(int idx, vector<vector<int>>& current, vector<vector<int>>& target, vector<vector<int>>& fixed, int& empty_cell_x, int& empty_cell_y, int safe_mode)
{
    int move_back_value = (safe_mode) ? 0 : idx - 3;

    string ans;
    // Fix last col
    for(int j = idx; j > 1; j--)
        if(!fixed[j][idx])
        {
            ans += move_cell(get_path_from_closest_occurance(j, idx, target[j][idx], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
            fixed[j][idx] = 1;
        }
    if(!fixed[0][idx] || !fixed[1][idx])
    {
        // Handle first two rows of last column
        // Written this way to prevent issues with the first getting stuck, should be optimizable.
        ans += move_cell(get_path_from_closest_occurance(0, move_back_value, target[0][idx], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[0][move_back_value] = 1;
        ans += move_cell(get_path_from_closest_occurance(0, idx, target[1][idx], current, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[0][move_back_value] = 0;
        fixed[0][idx] = 1;
        ans += move_cell(get_shortest_path(0, move_back_value, 0, idx - 1, fixed), current, fixed, empty_cell_x, empty_cell_y);
        fixed[0][idx - 1] = 1;
        ans += apply_and_get_operation_string(get_shortest_path(empty_cell_x, empty_cell_y, 1, idx, fixed), current);
        fixed[0][idx] = fixed[0][idx - 1] = 0;
        empty_cell_x = 0;
        empty_cell_y = idx - 1;
        ans += apply_and_get_operation_string({make_pair(1, idx), make_pair(0, idx), make_pair(0, idx - 1)}, current);
        assert(current[0][idx] == target[0][idx] && current[1][idx] == target[1][idx]);
        fixed[0][idx] = fixed[1][idx] = 1;
    }
    return ans;
}

int is_valid_3x3(int x, int y)
{
    return x >= 0 && x < 3 && y >= 0 && y < 3;
}

map<vector<vector<int>>, string> solve_3x3_op_strings;

void calculate_3x3_results()
{
    vector<vector<int>> basemask(3);
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            basemask[i].push_back(3 * i + j);
    solve_3x3_op_strings[basemask] = "";
    queue<vector<vector<int>>> q;
    q.push(basemask);
    vector<vector<int>> curmask, nemask;
    while(!q.empty())
    {
        curmask = q.front();
        q.pop();
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                if(curmask[i][j] == 0)
                    for(auto ne : dirs)
                    {
                        int nex = i + ne.first;
                        int ney = j + ne.second;
                        if(!is_valid_3x3(nex, ney))
                            continue;
                        nemask = curmask;
                        swap(nemask[i][j], nemask[nex][ney]);
                        if(!solve_3x3_op_strings.count(nemask))
                        {
                            assert(movement_to_direction_character_map.count({-ne.first, -ne.second}));
                            solve_3x3_op_strings[nemask] = solve_3x3_op_strings[curmask] + movement_to_direction_character_map[{-ne.first, -ne.second}];
                            q.push(nemask);
                        }
                    }
    }
}

string solve3x3(vector<vector<int>>& current, vector<vector<int>>& target, vector<vector<int>>& fixed)
{
    int req_rep_cnt[16] = {0};
    map<pii, int> req_pos;
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
        {
            req_pos[{target[i][j], req_rep_cnt[target[i][j]]}] = 3 * i + j;
            req_rep_cnt[target[i][j]]++;
        }
    // shuffle the duplicate matching order to ensure we don't repeatedly try the same bad reodering.
    vector<pii> order;
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            order.push_back({i, j});
    shuffle(order.begin(), order.end(), rng);   
    int base_rep_cnt[16] = {0};
    vector<vector<int>> transformation(3, vector<int>(3));
    for(auto x : order)
    {
        int i = x.first, j = x.second;
        transformation[i][j] = req_pos[{current[i][j], base_rep_cnt[current[i][j]]}];
        base_rep_cnt[current[i][j]]++;
    }
    if(solve_3x3_op_strings.count(transformation))
    {
        string res = solve_3x3_op_strings[transformation];
        reverse(res.begin(), res.end());
        if(!res.empty())
            for(int i = 0; i < 3; i++)
                for(int j = 0; j < 3; j++)
                    current[i][j] = target[i][j];
        return res;
    }
    return "";
}

vector<SlidingPuzzleSolverState> exact_slide_solver(vector<SlidingPuzzleSolverState> checkpoints)
{
    assert(!checkpoints.empty());

    int empty_cell_x = -1, empty_cell_y = -1;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(checkpoints.back().current[i][j] == 0)
            {
                assert(empty_cell_x == -1 && empty_cell_y == -1);
                empty_cell_x = i;
                empty_cell_y = j;
            }
    assert(empty_cell_x != -1 && empty_cell_y != -1);

    std::vector<string (*)(int, vector<vector<int>>&, vector<vector<int>>&, vector<vector<int>>&, int&, int&, int)> rearrangable_handlers = {
        fix_row,
        fix_col
    };
        
    string ans;
    for(int i = n - (int)(checkpoints.size()); i > 2; i--)
    {
        SlidingPuzzleSolverState curstate = checkpoints.back();
        if(uniform_int_distribution<int>(0, 1)(rng))
            shuffle(rearrangable_handlers.begin(), rearrangable_handlers.end(), rng);

        // So I have a heuristic which can get stuck at times, but 
        // works better most of the time. So lets try to use it when 
        // possible, if it fails we'll fall back to the safe version 
        // as needed.
        vector<vector<int>> current_copy, target_copy, fixed_copy;
        int empty_cell_x_copy, empty_cell_y_copy;


        for(auto handler_func : rearrangable_handlers)
        {
            current_copy = curstate.current;
            target_copy = curstate.target;
            fixed_copy = curstate.fixed;
            empty_cell_x_copy = empty_cell_x;
            empty_cell_y_copy = empty_cell_y;

            string curans;
            try 
            {
                curans = handler_func(i, curstate.current, curstate.target, curstate.fixed, empty_cell_x, empty_cell_y, 0);
            } 
            catch(InvalidStateException e)
            {
                curstate.current = current_copy;
                curstate.target = target_copy;
                curstate.fixed = fixed_copy;
                empty_cell_x = empty_cell_x_copy;
                empty_cell_y = empty_cell_y_copy;
                curans = handler_func(i, curstate.current, curstate.target, curstate.fixed, empty_cell_x, empty_cell_y, 1);
            }
            curstate.ans += curans;
        }
        checkpoints.push_back(curstate);
    }

    // Solve 3x3
    SlidingPuzzleSolverState curstate = checkpoints.back();
    curstate.ans += solve3x3(curstate.current, curstate.target, curstate.fixed);
    checkpoints.push_back(curstate);
    checkpoints.back().good = 1;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            checkpoints.back().good &= (checkpoints.back().current[i][j] == checkpoints.back().target[i][j]);
    return checkpoints;
}

// Consider the set of values {lo, lo + 1, ..., hi}.
// The probability of picking the i-th largest value in this set is 1 / (i + 1).
int get_weighted_random(int lo, int hi, int factor)
{
    assert(lo <= hi && factor >= 1);
    int res = lo;
    for(int i = 0; i < factor; i++)
        res = max(res, uniform_int_distribution<int>(lo, hi)(rng));
    return res;
}

int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    auto overall_start = chrono::high_resolution_clock::now();
    calculate_3x3_results();
    cin >> n >> t;
    vector<int> mask_cnts(16);
    vector<vector<int>> grid_masks(n, vector<int>(n));
    for(int i = 0; i < n; i++)
    {
        string s;
        cin >> s;
        for(int j = 0; j < n; j++)
        {
            grid_masks[i][j] = (s[j] >= 'a' && s[j] <= 'z') ? (s[j] - 'a' + 10) : (s[j] - '0');
            mask_cnts[grid_masks[i][j]]++;
        }
    }
    vector<vector<int>> best_grid;
    int best_score = 0;
    auto grid_choose_start = chrono::high_resolution_clock::now();
    int times = 0;
    while(best_score < n * n - 1 &&
        chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - grid_choose_start).count() < GRID_CHOOSE_TIMEOUT_MILLIS &&
        chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - overall_start).count() < OVERALL_SAFETY_TIMEOUT_MILLIS)
    {
        vector<vector<int>> cur_grid;
        int cur_score;
        tie(cur_grid, cur_score) = get_random_tree(mask_cnts);
        if(cur_score > best_score)
        {
            best_score = cur_score;
            best_grid = cur_grid;
        }
        times++;
    }
    cerr << "GENERATED " << times << " GRIDS\n";
    cerr << "Best grid has a tree of size " << best_score << " (" << (n * n - 1 - best_score) << " less than optimal)\n";

    assert(best_grid[0][0] == 0);
    for(auto row : best_grid)
        for(auto x : row)
            mask_cnts[x]--;
    for(int i = 0; i <= 15; i++)
        assert(mask_cnts[i] == 0);
    vector<SlidingPuzzleSolverState> best_checkpoints;
    SlidingPuzzleSolverState starting_state(n, grid_masks, best_grid);
    best_checkpoints.push_back(starting_state);
    int attempts = 0;
    while(chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - overall_start).count() < OVERALL_SAFETY_TIMEOUT_MILLIS)
    {
        assert(!best_checkpoints.empty());
        int take_lo = 1, take_hi = best_checkpoints.size();
        if(take_hi > 1)
            take_hi--;
        int take_actual = get_weighted_random(take_lo, take_hi, take_hi);
        vector<SlidingPuzzleSolverState> new_checkpoints = exact_slide_solver({best_checkpoints.begin(), best_checkpoints.begin() + take_actual});
        assert(new_checkpoints.size() + 1 == n);
        if(attempts == 0 || new_checkpoints.back().good > best_checkpoints.back().good || ((new_checkpoints.back().good == best_checkpoints.back().good) && new_checkpoints.back().ans.size() < best_checkpoints.back().ans.size()))
            best_checkpoints = new_checkpoints;
        attempts++;
    }
    cerr << best_checkpoints.back().ans.size() << "\t" << best_checkpoints.back().good << "\t" << attempts << "\n";
    while(best_checkpoints.back().ans.size() > t)
        best_checkpoints.back().ans.pop_back();
    assert(best_checkpoints.back().ans.size() <= t);
    cout << best_checkpoints.back().ans << "\n";
    return 0;
}

Submission Info

Submission Time
Task A - Sliding Tree Puzzle
User ExplodingFreeze
Language C++ (GCC 9.2.1)
Score 30038670
Code Size 23384 Byte
Status AC
Exec Time 2776 ms
Memory 62608 KiB

Compile Error

./Main.cpp: In function ‘std::string apply_and_get_operation_string(std::vector<std::pair<int, int> >, std::vector<std::vector<int> >&)’:
./Main.cpp:249:22: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  249 |     for(int i = 1; i < path.size(); i++)
      |                    ~~^~~~~~~~~~~~~
./Main.cpp: In function ‘std::string move_cell(std::vector<std::pair<int, int> >, std::vector<std::vector<int> >&, std::vector<std::vector<int> >&, int&, int&)’:
./Main.cpp:268:22: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  268 |     for(int i = 1; i < path.size(); i++)
      |                    ~~^~~~~~~~~~~~~
./Main.cpp: In function ‘std::string solve3x3(std::vector<std::vector<int> >&, std::vector<std::vector<int> >&, std::vector<std::vector<int> >&)’:
./Main.cpp:396:97: warning: unused parameter ‘fixed’ [-Wunused-parameter]
  396 | string solve3x3(vector<vector<int>>& current, vector<vector<int>>& target, vector<vector<int>>& fixed)
      |                                                                            ~~~~~~~~~~~~~~~~~~~~~^~~~~
./Main.cpp: In function ‘std::vector<SlidingPuzzleSolverState> exact_slide_solver(std::vector<SlidingPuzzleSolverState>)’:
./Main.cpp:481:41: warning: catching polymorphic type ‘class InvalidStateException’ by value [-Wcatch-value=]
  481 |             catch(InvalidStateException e)
      |                                         ^
In file included from /usr/include/c++/9/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:33,
                 from ./Main.cpp:1:
./Main.cpp: In function ‘int32_t main()’:
./Main.cpp:575:43: warning: comparison of integer expressions of different signedness: ‘std::vector<SlidingPuzzleSolverState>::size_type’ {aka ‘long ...

Judge Result

Set Name test_ALL
Score / Max Score 30038670 / 50000000
Status
AC × 50
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt
Case Name Status Exec Time Memory
test_0000.txt AC 2776 ms 62480 KiB
test_0001.txt AC 2771 ms 62416 KiB
test_0002.txt AC 2770 ms 62588 KiB
test_0003.txt AC 2771 ms 62596 KiB
test_0004.txt AC 2770 ms 62536 KiB
test_0005.txt AC 2772 ms 62416 KiB
test_0006.txt AC 2770 ms 62532 KiB
test_0007.txt AC 2770 ms 62416 KiB
test_0008.txt AC 2770 ms 62596 KiB
test_0009.txt AC 2770 ms 62496 KiB
test_0010.txt AC 2771 ms 62556 KiB
test_0011.txt AC 2770 ms 62492 KiB
test_0012.txt AC 2772 ms 62536 KiB
test_0013.txt AC 2772 ms 62544 KiB
test_0014.txt AC 2770 ms 62496 KiB
test_0015.txt AC 2770 ms 62452 KiB
test_0016.txt AC 2771 ms 62460 KiB
test_0017.txt AC 2770 ms 62588 KiB
test_0018.txt AC 2770 ms 62596 KiB
test_0019.txt AC 2771 ms 62524 KiB
test_0020.txt AC 2770 ms 62368 KiB
test_0021.txt AC 2770 ms 62580 KiB
test_0022.txt AC 2770 ms 62448 KiB
test_0023.txt AC 2770 ms 62512 KiB
test_0024.txt AC 2770 ms 62492 KiB
test_0025.txt AC 2771 ms 62392 KiB
test_0026.txt AC 2771 ms 62468 KiB
test_0027.txt AC 2770 ms 62448 KiB
test_0028.txt AC 2770 ms 62536 KiB
test_0029.txt AC 2769 ms 62552 KiB
test_0030.txt AC 2771 ms 62408 KiB
test_0031.txt AC 2770 ms 62520 KiB
test_0032.txt AC 2770 ms 62524 KiB
test_0033.txt AC 2770 ms 62480 KiB
test_0034.txt AC 2770 ms 62592 KiB
test_0035.txt AC 2771 ms 62412 KiB
test_0036.txt AC 2770 ms 62376 KiB
test_0037.txt AC 2772 ms 62528 KiB
test_0038.txt AC 2771 ms 62592 KiB
test_0039.txt AC 2770 ms 62588 KiB
test_0040.txt AC 2771 ms 62452 KiB
test_0041.txt AC 2770 ms 62500 KiB
test_0042.txt AC 2769 ms 62492 KiB
test_0043.txt AC 2769 ms 62452 KiB
test_0044.txt AC 2771 ms 62556 KiB
test_0045.txt AC 2771 ms 62468 KiB
test_0046.txt AC 2770 ms 62572 KiB
test_0047.txt AC 2770 ms 62576 KiB
test_0048.txt AC 2771 ms 62608 KiB
test_0049.txt AC 2770 ms 62528 KiB