USACO Camelot Help

Problem Info

The problem is called Camelot and can be found here.

Question

My code outputs the wrong answer for a test case and I have no idea why.

What I’ve Tried

I have downloaded the test data and tried it out, but it outputs the wrong answer. I have written another solution that is a bit more like brute force, but it outputs the same incorrect answer.

My Work

/*
ID: REDACTED
LANG: C++
TASK: camelot
*/
#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <algorithm>

std::vector<std::vector<int>> make_neighbors(int rows, int cols) {
    std::vector<std::vector<int>> moves = {{-1, -2}, {-2, -1}, {1, -2}, {-2, 1}, {2, -1}, {-1, 2}, {1, 2}, {2, 1}}, neighbors(rows * cols, std::vector<int>());
    int new_row, new_col;
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            for (std::vector<int> move : moves) {
                new_row = row + move[0];
                new_col = col + move[1];
                if (new_row >= 0 && new_row < rows && new_col >= 0 && new_col < cols) {
                    neighbors[row * cols + col].push_back(new_row * cols + new_col);
                }
            }
        }
    }
    return neighbors;
}

std::vector<std::vector<int>> find_distances(int rows, int cols) {
    std::vector<std::vector<int>> knight_distance(rows * cols, std::vector<int>(rows * cols, 1e6)), neighbors = make_neighbors(rows, cols);
    std::queue<int> unsearched;
    int distance, current;
    for (int square = 0; square < rows * cols; square++) {
        unsearched = std::queue<int>();
        unsearched.push(square);
        knight_distance[square][square] = 0;
        while (unsearched.empty() == 0) {
            current = unsearched.front();
            distance = knight_distance[square][current];
            unsearched.pop();
            for (int next_position : neighbors[current]) {
                if (knight_distance[square][next_position] == 1e6) {
                    unsearched.push(next_position);
                    knight_distance[square][next_position] = distance + 1;
                }
            }
        }
    }
    return knight_distance;
}

int min_moves(int rows, int cols, std::vector<int> king, std::vector<std::vector<int>> knights) {
    std::vector<std::vector<int>> knight_distance = find_distances(rows, cols);
    int current_moves, knight_pos, total_moves = 1e6, extra_moves, king_distance, king_to_target, gather_square;
    for (int target = 0; target < rows * cols; target++) {
        king_to_target = std::max(std::abs(king[0] - target / cols), std::abs(king[1] - target % cols));
        current_moves = 0;
        extra_moves = 1e6;
        for (std::vector<int> &knight : knights) {
            current_moves += knight_distance[knight[0] * cols + knight[1]][target];
        }
        for (int gather_i = std::max(0, king[0] - 2); gather_i <= std::min(rows - 1, king[0] + 2); gather_i++) {
            for (int gather_j = std::max(0, king[1] - 2); gather_j <= std::min(rows - 1, king[1] + 2); gather_j++) {
                gather_square = gather_i * cols + gather_j;
                king_distance = std::max(std::abs(king[0] - gather_i), std::abs(king[1] - gather_j));
                for (std::vector<int> &knight : knights) {
                    knight_pos = knight[0] * cols + knight[1];
                    if (knight_distance[knight_pos][gather_square] + knight_distance[gather_square][target] - knight_distance[knight_pos][target] + king_distance < extra_moves) {
                        extra_moves = knight_distance[knight_pos][gather_square] + knight_distance[gather_square][target] - knight_distance[knight_pos][target] + king_distance;
                    }
                }
            }
        }
        extra_moves = std::min(extra_moves, king_to_target);
        total_moves = std::min(total_moves, current_moves + extra_moves);
    }
    return total_moves;
}

int main() {
    std::freopen("camelot.in", "r", stdin);
    std::freopen("camelot.out", "w", stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int rows, cols, row, col;
    char letter_row;
    std::cin >> rows >> cols;
    std::vector<int> king;
    std::cin >> letter_row >> col;
    row = letter_row - 'A';
    king = {row, col - 1};
    std::vector<std::vector<int>> knights;
    while (std::cin >> letter_row >> col) {
        row = letter_row - 'A';
        knights.push_back({row, col - 1});
    }
    int result = min_moves(rows, cols, king, knights);
    std::cout << result << "\n";
    return 0;
}

The code uses BFS to find the distance between two squares if you are traveling by a knight. Then, it loops through all possible squares where all the pieces could end. For each of these squares, it looks at if a knight and a king meet up at a square, and then move to the ending square would be better. I don’t think the issue is in restricting the intermediate squares which a knight and a king meet up, since unrestricting the squares doesn’t change the output.

Here is the result when I submit it.