Submission #66147796


Source Code Expand

#include <iostream>
#include <string>
#include <vector>
#include <tuple>
#include <chrono>
#include <algorithm>
#include <random>
#include <map>
#include <set>
#include <queue>
#include <random>
#include <chrono>
#include <cmath>
#include <climits>
#include <bitset>
#include <time.h>
// eigen
#include <Eigen/Dense>

using namespace std;
using Ps = pair<short, short>;
using vec_int = vector<int>;
using P = pair<int, int>;
using P2 = pair<P, P>;
using P3 = pair<float, int>;
using T = tuple<int, int, int>;
using T2 = tuple<float, int, int>;
using T3 = tuple<float, int, int, int, int>;
using T4 = tuple<int, int, int, int>;
using T5 = tuple<int, int, int, int, int>;
using TT = tuple<int, int, int>;
using ll = long long;
using uc = unsigned char;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int N, M;
double eps, delta;
int sx, sy;
vector<int> px, py;
vector<int> lx, ly, rx, ry;

// #pragma GCC optimize("Ofast")

std::mt19937 mt{12345};
int RAND_ARR_LEN = 100000;
int RAND_RANGE = 1000000000;
float TIME_LIMIT = 5000;
float INV_TIME_LIMIT = 1. / 1000.;
const int JOB_MAX_LEN = 1003;
std::uniform_int_distribution<int> dist(1, RAND_RANGE);

int WAITING_TASK = 1001;

void remove_val_and_pop_from_last(vec_int &A, int val)
{
    for (int i = 0; i < A.size(); i++)
    {
        if (A.at(i) == val)
        {
            A.at(i) = A.at(A.size() - 1);
            A.pop_back();
            return;
        }
    }
    throw runtime_error("trying to remove non-existing value");
}

class Rand
{
private:
    int count = 0;
    vec_int rand_arr;

public:
    Rand(){
        rep(i, RAND_ARR_LEN){
            rand_arr.push_back(dist(mt));
}
}
;
int get();
int get_rand(int from, int to);
float get_float();
}
;

int Rand::get()
{
    int num = rand_arr.at(count);
    count += 1;
    count %= RAND_ARR_LEN;
    return num;
}

int Rand::get_rand(int from, int to)
{
    int diff = to - from;
    int num = get() % diff;
    return num + from;
}

float Rand::get_float()
{
    // 0~1の間の一様乱数
    return (float)get() / (float)RAND_RANGE;
}

Rand ro;

class PseudoSet
{
private:
    vec_int index_arr;

public:
    vec_int data;
    PseudoSet() {};
    PseudoSet(int value_range)
    {
        index_arr = vec_int(value_range, -1);
    }

    bool count(int value);
    void insert(int value);
    void erase(int value);
    vec_int get_data() { return data; };
    int size() { return data.size(); };
    int get_random() { return data.at(ro.get_rand(0, size())); };
};

bool PseudoSet::count(int value)
{
    return index_arr[value] != -1;
}

void PseudoSet::insert(int value)
{
    if (count(value))
        return;
    index_arr[value] = data.size();
    data.push_back(value);
}

void PseudoSet::erase(int value)
{
    if (!count(value))
    {
        // throw runtime_error("no existing value:"+to_string(value));
        return;
    }
    int tail_value = data[data.size() - 1];
    if (value == tail_value)
    {
        data.pop_back();
        index_arr[value] = -1;
    }
    else
    {
        index_arr[tail_value] = index_arr[value];
        index_arr[value] = -1;
        data[index_arr[tail_value]] = tail_value;
        data.pop_back();
    }
}

float get_time(bool init)
{
    static std::chrono::system_clock::time_point start;
    if (init)
    {
        start = std::chrono::system_clock::now();
    }
    std::chrono::system_clock::time_point end = std::chrono::system_clock::now();
    return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); // 処理に要した時間をミリ秒に変換
}

double current_tmp(double current_time, double T0, double T1)
{
    return T1 + (T0 - T1) * (TIME_LIMIT * 0.92 - current_time) / (TIME_LIMIT * 0.92);
    // double start_time = TIME_LIMIT * 0.6;
    // double x = (current_time - start_time) / (TIME_LIMIT * 0.32);
    // return pow(T1, 1 - x) + (T0, x);
}

bool is_valid_transition(int diff, double current_time, double T0, float T1)
{
    float t = current_tmp(current_time, T0, T1);
    float rand = ro.get_float();
    // diffが正だったら常にアクセぷと
    return rand < exp(((float)diff) / t);
}

/**
 * @brief カルマンフィルタの状態を表すクラス
 *
 * @tparam StateSize 状態ベクトルのサイズ
 */
template <int StateSize>
struct KalmanState
{
    Eigen::Matrix<double, StateSize, 1> x;         // 状態ベクトル
    Eigen::Matrix<double, StateSize, StateSize> P; // 共分散行列

    KalmanState()
    {
        x.setZero();
        P.setIdentity();
    }

    KalmanState(const Eigen::Matrix<double, StateSize, 1> &state,
                const Eigen::Matrix<double, StateSize, StateSize> &covariance)
        : x(state), P(covariance) {}
};

/**
 * @brief 観測値を表すクラス
 *
 * @tparam ObservationSize 観測ベクトルのサイズ
 */
template <int ObservationSize>
struct Observation
{
    Eigen::Matrix<double, ObservationSize, 1> y; // 観測ベクトル

    Observation()
    {
        y.setZero();
    }

    explicit Observation(const Eigen::Matrix<double, ObservationSize, 1> &measurement)
        : y(measurement) {}
};

/**
 * @brief カルマンフィルタクラス
 *
 * 状態方程式: x(k+1) = A x(k) + b1 u(k) + b0 v(k)
 * 観測方程式: y(k) = C x(k) + w(k)
 *
 * @tparam StateSize 状態ベクトルのサイズ
 * @tparam InputSize 制御入力ベクトルのサイズ
 * @tparam ObservationSize 観測ベクトルのサイズ
 */
template <int StateSize, int InputSize, int ObservationSize>
class KalmanFilter
{
public:
    using StateVector = Eigen::Matrix<double, StateSize, 1>;
    using StateMatrix = Eigen::Matrix<double, StateSize, StateSize>;
    using InputVector = Eigen::Matrix<double, InputSize, 1>;
    using InputMatrix = Eigen::Matrix<double, StateSize, InputSize>;
    using ObservationVector = Eigen::Matrix<double, ObservationSize, 1>;
    using ObservationMatrix = Eigen::Matrix<double, ObservationSize, StateSize>;
    using KalmanGain = Eigen::Matrix<double, StateSize, ObservationSize>;

    /**
     * @brief コンストラクタ
     */
    KalmanFilter()
    {
        A.setIdentity();
        B1.setZero();
        B0.setZero();
        C.setZero();
    }

    /**
     * @brief パラメータ付きコンストラクタ
     *
     * @param state_transition 状態遷移行列 A
     * @param control_input 制御入力行列 B1
     * @param process_noise プロセスノイズ入力行列 B0
     * @param observation 観測行列 C
     */
    KalmanFilter(
        const StateMatrix &state_transition,
        const InputMatrix &control_input,
        const StateMatrix &process_noise,
        const ObservationMatrix &observation)
        : A(state_transition), B1(control_input), B0(process_noise),
          C(observation)
    {
    }

    /**
     * @brief システム行列の設定
     *
     * @param state_transition 状態遷移行列 A
     * @param control_input 制御入力行列 B1
     * @param process_noise プロセスノイズ入力行列 B0
     * @param observation 観測行列 C
     */
    void setSystemMatrices(
        const StateMatrix &state_transition,
        const InputMatrix &control_input,
        const StateMatrix &process_noise,
        const ObservationMatrix &observation)
    {
        A = state_transition;
        B1 = control_input;
        B0 = process_noise;
        C = observation;
    }

    /**
     * @brief 初期状態の設定
     *
     * @param initial_state 初期状態ベクトル
     * @param initial_covariance 初期共分散行列
     * @return KalmanState<StateSize> 初期化された状態
     */
    KalmanState<StateSize> initialize(
        const StateVector &initial_state,
        const StateMatrix &initial_covariance)
    {
        return KalmanState<StateSize>(initial_state, initial_covariance);
    }

    /**
     * @brief 予測ステップ(時間更新)
     *
     * @param current_state 現在の状態
     * @param control_input 制御入力 u(k)
     * @param process_noise_cov プロセスノイズ共分散行列
     * @return KalmanState<StateSize> 予測された次の状態
     */
    KalmanState<StateSize> predict(
        const KalmanState<StateSize> &current_state,
        const InputVector &control_input,
        const StateMatrix &process_noise_cov)
    {
        // 状態の予測
        StateVector predicted_x = A * current_state.x + B1 * control_input;

        // 共分散行列の予測
        StateMatrix predicted_P = A * current_state.P * A.transpose() + B0 * process_noise_cov * B0.transpose();

        return KalmanState<StateSize>(predicted_x, predicted_P);
    }

    /**
     * @brief 更新ステップ(観測更新)
     *
     * @param predicted_state 予測された状態
     * @param observation 観測値
     * @param observation_noise_cov 観測ノイズ共分散行列
     * @return KalmanState<StateSize> 更新された状態
     */
    KalmanState<StateSize> update(
        const KalmanState<StateSize> &predicted_state,
        const Observation<ObservationSize> &observation,
        const Eigen::Matrix<double, ObservationSize, ObservationSize> &observation_noise_cov)
    {
        // イノベーション(予測誤差)の計算
        ObservationVector innovation = observation.y - C * predicted_state.x;

        // イノベーション共分散行列
        Eigen::Matrix<double, ObservationSize, ObservationSize> S =
            C * predicted_state.P * C.transpose() + observation_noise_cov;

        // カルマンゲインの計算
        KalmanGain K = predicted_state.P * C.transpose() * S.inverse();

        // 状態の更新
        StateVector updated_x = predicted_state.x + K * innovation;

        // 共分散行列の更新
        StateMatrix updated_P = (StateMatrix::Identity() - K * C) * predicted_state.P;

        return KalmanState<StateSize>(updated_x, updated_P);
    }

    /**
     * @brief 予測と更新を一度に行う
     *
     * @param current_state 現在の状態
     * @param control_input 制御入力
     * @param observation 観測値
     * @param process_noise_cov プロセスノイズ共分散行列
     * @param observation_noise_cov 観測ノイズ共分散行列
     * @return KalmanState<StateSize> 更新された状態
     */
    KalmanState<StateSize> step(
        const KalmanState<StateSize> &current_state,
        const InputVector &control_input,
        const Observation<ObservationSize> &observation,
        const StateMatrix &process_noise_cov,
        const Eigen::Matrix<double, ObservationSize, ObservationSize> &observation_noise_cov)
    {
        // 予測ステップ
        KalmanState<StateSize> predicted_state = predict(current_state, control_input, process_noise_cov);

        // 更新ステップ
        return update(predicted_state, observation, observation_noise_cov);
    }

private:
    StateMatrix A;       // 状態遷移行列
    InputMatrix B1;      // 制御入力行列
    StateMatrix B0;      // プロセスノイズ入力行列
    ObservationMatrix C; // 観測行列
};

void handle_input()
{
    cin >> N >> M >> eps >> delta;
    cin >> sx >> sy;
    px.resize(N);
    py.resize(N);
    rep(i, N) cin >> px[i] >> py[i];
    rep(i, N) cerr << px[i] << " " << py[i] << endl;
    lx.resize(M);
    ly.resize(M);
    rx.resize(M);
    ry.resize(M);
    rep(i, M) cin >> lx[i] >> ly[i] >> rx[i] >> ry[i];
}

int main(int argc, char *argv[])
{
#ifdef OPTUNA_STUDY
    cerr << "optuna study, override parameters" << endl;
    T0 = stod(argv[1]);
    T1 = stod(argv[2]);
#endif
    get_time(true);
    handle_input();
    cerr << N << " " << M << " " << eps << " " << delta << endl;
    cerr << sx << " " << sy << endl;

    // カルマンフィルタの状態を作る
    // 初期の状態ベクトルは(sx, sy, 0, 0)とする
    Eigen::Matrix<double, 4, 1> initial_state = Eigen::Matrix<double, 4, 1>::Zero();
    initial_state(0) = sx;
    initial_state(1) = sy;
    // 初期の共分散行列は対角成分が1の行列にする
    Eigen::Matrix<double, 4, 4> initial_covariance = Eigen::Matrix<double, 4, 4>::Identity();
    auto ks = KalmanState<4>(initial_state, initial_covariance);

    // 状態遷移行列(A)
    Eigen::Matrix<double, 4, 4> A = Eigen::Matrix<double, 4, 4>::Identity();
    A(0, 2) = 1;
    A(1, 3) = 1;

    // 制御入力行列(B1)は、単位行列にする
    Eigen::Matrix<double, 4, 4> B1 = Eigen::Matrix<double, 4, 4>::Identity();
    B1(0, 2) = 1;
    B1(1, 3) = 1;

    // プロセスノイズ入力行列は単位行列にする
    Eigen::Matrix<double, 4, 4> B0 = Eigen::Matrix<double, 4, 4>::Identity();

    // 観測行列
    Eigen::Matrix<double, 2, 4> C = Eigen::Matrix<double, 2, 4>::Zero();
    C(0, 0) = 1;
    C(1, 1) = 1;

    // 観測のノイズは毎回壁との距離d * (delta)の標準偏差を持つ正規分布に従うことになっている
    // 毎回変わるため、updateの際に渡す

    // これでカルマンフィルタの状態を作る
    KalmanFilter<4, 4, 2> kf(A, B1, B0, C);

    // 基本的な戦略は、目標地点を最も近いところに定めて、見つかったら次のところに行くことを繰り返す
    // 3つの行動を1セットで扱い、(加速) -> x観測 -> y観測 を1セットにする
    // 3ターン目にKalmanFilterの状態を更新することにする

    // プロセスノイズとして使用する共分散行列
    Eigen::Matrix<double, 4, 4> process_noise_cov = Eigen::Matrix<double, 4, 4>::Zero();
    // process_noise_cov(0, 0) = eps * eps * 3;
    //  process_noise_cov(1, 1) = eps * eps * 3;
    process_noise_cov(0, 0) = eps * eps;
    process_noise_cov(1, 1) = eps * eps;
    process_noise_cov(2, 2) = eps * eps;
    process_noise_cov(3, 3) = eps * eps;

    int turn = 0;
    int found = 0;
    vector<bool> found_flag(N, false);

    // 最も良い訪問順序を求める
    // 10!は間に合う
    double best_distance = 1e19;
    vector<int> perm = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    vector<int> best_perm(N);
    int cnt = 0;
    do
    {
        cnt++;
        double dist = sqrt((double)(ks.x(0) - px[perm[0]]) * (double)(ks.x(0) - px[perm[0]]) + (double)(ks.x(1) - py[perm[0]]) * (double)(ks.x(1) - py[perm[0]]));
        rep(i, N - 1)
        {
            dist += sqrt((double)(px[perm[i]] - px[perm[i + 1]]) * (double)(px[perm[i]] - px[perm[i + 1]]) + (double)(py[perm[i]] - py[perm[i + 1]]) * (double)(py[perm[i]] - py[perm[i + 1]]));
        }
        if (dist < best_distance)
        {
            best_distance = dist;
            best_perm = perm;
        }
    } while (next_permutation(perm.begin(), perm.end()));
    cerr << "best_distance: " << best_distance << endl;
    double check_distance = 0;
    check_distance += sqrt((double)(ks.x(0) - px[best_perm[0]]) * (double)(ks.x(0) - px[best_perm[0]]) + (double)(ks.x(1) - py[best_perm[0]]) * (double)(ks.x(1) - py[best_perm[0]]));
    rep(i, N - 1)
    {
        double dist = sqrt((double)(px[best_perm[i]] - px[best_perm[i + 1]]) * (double)(px[best_perm[i]] - px[best_perm[i + 1]]) + (double)(py[best_perm[i]] - py[best_perm[i + 1]]) * (double)(py[best_perm[i]] - py[best_perm[i + 1]]));
        check_distance += sqrt((double)(px[best_perm[i]] - px[best_perm[i + 1]]) * (double)(px[best_perm[i]] - px[best_perm[i + 1]]) + (double)(py[best_perm[i]] - py[best_perm[i + 1]]) * (double)(py[best_perm[i]] - py[best_perm[i + 1]]));
        cerr << px[best_perm[i]] << " " << py[best_perm[i]] << " " << px[best_perm[i + 1]] << " " << py[best_perm[i + 1]] << " check_distance: " << check_distance << endl;
    }
    cerr << "check_distance: " << check_distance << endl;
    for (auto city : best_perm)
    {
        cerr << city << " ";
    }
    cerr << endl;

    while (turn < 5000 && found < N)
    {
        // 最も近いx, yを探す
        int target_x = -1;
        int target_y = -1;
        double min_dist = 1e9;
        rep(i, N)
        {
            int city = best_perm[i];
            if (found_flag[city])
                continue;
            /*
        double dist = sqrt((ks.x(0) - px[i]) * (ks.x(0) - px[i]) + (ks.x(1) - py[i]) * (ks.x(1) - py[i]));
        if (dist < min_dist)
        {
            min_dist = dist;
            target_x = px[i];
            target_y = py[i];
        }
        */
            target_x = px[city];
            target_y = py[city];
            cerr << "city:" << city << " target_x: " << target_x << " target_y: " << target_y << endl;
            break;
        }

        // 現在地点からtarget_x, target_yに向かう

        while (turn < 5000)
        {
            cout << "#"
                 << " turn:" << turn << " (x,y):" << ks.x(0) << " " << ks.x(1) << " (vx,vy):" << ks.x(2) << " " << ks.x(3) << endl;
            cout << "#"
                 << " sigma (x, y):" << sqrt(ks.P(0, 0)) << " " << sqrt(ks.P(1, 1)) << " sigma (vx, vy):" << sqrt(ks.P(2, 2)) << " " << sqrt(ks.P(3, 3)) << endl;

            int c, h;
            // まず、加速をする
            // 現在の速度が、目的地までのベクトルを(dx, dy)として、(dx/10, dy/10)になるように調整する
            // ただし、早さが1000よりは小さくならないようにする
            double vx = ks.x(2);
            double vy = ks.x(3);
            double dx = target_x - ks.x(0);
            double dy = target_y - ks.x(1);
            double distance = sqrt(dx * dx + dy * dy);

            int accel_x, accel_y;

            // まず、現在のvx, vyについて、(dx, dy)の方向と垂直方向の成分を計算する
            double unit_dx = dx / distance;
            double unit_dy = dy / distance;

            double product = vx * unit_dx + vy * unit_dy;
            double vx_perp = vx - product * unit_dx;
            double vy_perp = vy - product * unit_dy;

            // double vx_perp = vx * unit_dy - vy * unit_dx;
            // double vy_perp = vy * unit_dx - vx * unit_dy;
            double vx_perp_size = sqrt(vx_perp * vx_perp + vy_perp * vy_perp);
            // 垂直方向の成分が0になるように加速をする
            accel_x = -vx_perp;
            accel_y = -vy_perp;
            double accel_size = sqrt(accel_x * accel_x + accel_y * accel_y);
            if (accel_size >= 400)
            {
                accel_x *= 400. / accel_size;
                accel_y *= 400. / accel_size;
            }
            // 残りの分は理想的な方向に近づくように加速をする
            // 残りの分は dx, dyの方向の理想の早さに近づくように加速をする
            int res_speed = sqrt(500 * 500 - accel_x * accel_x - accel_y * accel_y);

            int ideal_speed = max(sqrt(distance * 500. * 2. / 3.) * 0.9, 1200.);
            int current_speed = vx * unit_dx + vy * unit_dy;

            int adjusted_speed = min(res_speed, abs(ideal_speed - current_speed));
            if (ideal_speed > current_speed)
            {
                accel_x += adjusted_speed * dx / distance;
                accel_y += adjusted_speed * dy / distance;
            }
            else
            {
                accel_x -= adjusted_speed * dx / distance;
                accel_y -= adjusted_speed * dy / distance;
            }
            double tot_accel = sqrt(accel_x * accel_x + accel_y * accel_y);
            accel_x *= 498. / tot_accel;
            accel_y *= 498. / tot_accel;

            turn++;
            cout << "A"
                 << " " << accel_x << " " << accel_y << endl;
            cin >> c >> h;

            if (c == 1)
            {
                // この場合には壁に当たったので、速度を0に直してやり直し
                ks.x(2) = 0;
                ks.x(3) = 0;
                ks.P(2, 2) = 0;
                ks.P(3, 3) = 0;
                // ks.P = initial_covariance;
                // continue;
            }

            // 制御入力の用意
            Eigen::Matrix<double, 4, 1> control_input = Eigen::Matrix<double, 4, 1>::Zero();
            control_input(2) = accel_x;
            control_input(3) = accel_y;

            // 観測の用意
            Eigen::Matrix<double, 2, 1> observation = Eigen::Matrix<double, 2, 1>::Zero();
            observation(0) = ks.x(0);
            observation(1) = ks.x(1);

            // 観測ノイズの共分散行列
            Eigen::Matrix<double, 2, 2> observation_noise_cov = Eigen::Matrix<double, 2, 2>::Identity();
            observation_noise_cov(0, 0) = pow(10, 15);
            observation_noise_cov(1, 1) = pow(10, 15);

            ks = kf.step(ks, control_input, Observation<2>(observation), process_noise_cov, observation_noise_cov);

            if (h > 0)
            {
                vec_int q(h);
                rep(i, h) cin >> q[i];
                rep(i, h)
                {
                    found_flag[q[i]] = true;
                    found += 1;
                    /*
                    ks.x(0) = px[q[i]];
                    ks.x(1) = py[q[i]];
                    ks.P(0, 0) = ks.x(2) * ks.x(2);
                    ks.P(1, 1) = ks.x(3) * ks.x(3);
                    */
                }
                break;
            }

            if (delta < 0.1)
            {
                double vx = ks.x(2);
                double vy = ks.x(3);
                double dx = target_x - ks.x(0);
                double dy = target_y - ks.x(1);
                double distance = sqrt(dx * dx + dy * dy);

                int accel_x, accel_y;

                // まず、現在のvx, vyについて、(dx, dy)の方向と垂直方向の成分を計算する
                double unit_dx = dx / distance;
                double unit_dy = dy / distance;

                double product = vx * unit_dx + vy * unit_dy;
                double vx_perp = vx - product * unit_dx;
                double vy_perp = vy - product * unit_dy;

                // double vx_perp = vx * unit_dy - vy * unit_dx;
                // double vy_perp = vy * unit_dx - vx * unit_dy;
                double vx_perp_size = sqrt(vx_perp * vx_perp + vy_perp * vy_perp);
                // 垂直方向の成分が0になるように加速をする
                accel_x = -vx_perp;
                accel_y = -vy_perp;
                double accel_size = sqrt(accel_x * accel_x + accel_y * accel_y);
                if (accel_size >= 420)
                {
                    accel_x *= 420. / accel_size;
                    accel_y *= 420. / accel_size;
                }
                // 残りの分は理想的な方向に近づくように加速をする
                // 残りの分は dx, dyの方向の理想の早さに近づくように加速をする
                int res_speed = sqrt(500 * 500 - accel_x * accel_x - accel_y * accel_y);

                int ideal_speed = max(sqrt(distance * 500. * 2. / 3.) * 0.9, 800.);
                int current_speed = vx * unit_dx + vy * unit_dy;

                int adjusted_speed = min(res_speed, abs(ideal_speed - current_speed));
                if (ideal_speed > current_speed)
                {
                    accel_x += adjusted_speed * dx / distance;
                    accel_y += adjusted_speed * dy / distance;
                }
                else
                {
                    accel_x -= adjusted_speed * dx / distance;
                    accel_y -= adjusted_speed * dy / distance;
                }
                double tot_accel = sqrt(accel_x * accel_x + accel_y * accel_y);
                accel_x *= 498. / tot_accel;
                accel_y *= 498. / tot_accel;

                turn++;
                cout << "A"
                     << " " << accel_x << " " << accel_y << endl;
                int c, h;
                cin >> c >> h;

                if (c == 1)
                {
                    // この場合には壁に当たったので、速度を0に直してやり直し
                    ks.x(2) = 0;
                    ks.x(3) = 0;
                    ks.P(2, 2) = 0;
                    ks.P(3, 3) = 0;
                    // ks.P = initial_covariance;
                    // continue;
                }

                // 制御入力の用意
                Eigen::Matrix<double, 4, 1> control_input = Eigen::Matrix<double, 4, 1>::Zero();
                control_input(2) = accel_x;
                control_input(3) = accel_y;

                // 観測の用意
                Eigen::Matrix<double, 2, 1> observation = Eigen::Matrix<double, 2, 1>::Zero();
                observation(0) = ks.x(0);
                observation(1) = ks.x(1);

                // 観測ノイズの共分散行列
                Eigen::Matrix<double, 2, 2> observation_noise_cov = Eigen::Matrix<double, 2, 2>::Identity();
                observation_noise_cov(0, 0) = pow(10, 15);
                observation_noise_cov(1, 1) = pow(10, 15);

                ks = kf.step(ks, control_input, Observation<2>(observation), process_noise_cov, observation_noise_cov);

                if (h > 0)
                {
                    vec_int q(h);
                    rep(i, h) cin >> q[i];
                    rep(i, h)
                    {
                        found_flag[q[i]] = true;
                        found += 1;
                        /*
                        ks.x(0) = px[q[i]];
                        ks.x(1) = py[q[i]];
                        ks.P(0, 0) = ks.x(2) * ks.x(2);
                        ks.P(1, 1) = ks.x(3) * ks.x(3);
                        */
                    }
                    break;
                }
            }

            // 次にx方向の測定をする
            // 現在地が左右の壁のどちらかに近いかで、その壁との距離を観測する
            double distance_x;
            double predicted_x;
            bool is_left = ks.x(0) < 0;
            turn++;
            if (is_left)
            {
                // 左側の壁に近い場合
                cout << "S -1 0" << endl;
                cin >> distance_x;
                predicted_x = -100000 + distance_x;
            }
            else
            {
                cout << "S 1 0" << endl;
                cin >> distance_x;
                predicted_x = 100000 - distance_x;
            }

            cin >> c >> h;
            if (c == 1)
            {
                // この場合には壁に当たったので、速度を0に直してやり直し
                ks.x(0) += ks.x(2);
                ks.x(1) += ks.x(3);
                ks.x(2) = 0;
                ks.x(3) = 0;

                ks.P(2, 2) = 0;
                ks.P(3, 3) = 0;
                // continue;
            }

            // 制御入力の用意
            control_input = Eigen::Matrix<double, 4, 1>::Zero();

            // 観測の用意
            observation = Eigen::Matrix<double, 2, 1>::Zero();
            observation(0) = predicted_x + ks.x(2);
            observation(1) = ks.x(1);

            // 観測ノイズの共分散行列
            observation_noise_cov = Eigen::Matrix<double, 2, 2>::Identity();
            observation_noise_cov(0, 0) = distance_x * distance_x * delta * delta;
            observation_noise_cov(1, 1) = pow(10, 15);

            ks = kf.step(ks, control_input, Observation<2>(observation), process_noise_cov, observation_noise_cov);

            if (h > 0)
            {
                vec_int q(h);
                rep(i, h) cin >> q[i];
                rep(i, h)
                {
                    found_flag[q[i]] = true;
                    found += 1;

                    /*
                    ks.x(0) = px[q[i]];
                    ks.x(1) = py[q[i]];
                    ks.P(0, 0) = ks.x(2) * ks.x(2);
                    ks.P(1, 1) = ks.x(3) * ks.x(3);
                    */
                }
                break;
            }

            // 次にy方向の測定をする
            // 現在地が上下の壁のどちらかに近いかで、その壁との距離を観測する
            double distance_y;
            double predicted_y;
            bool is_bottom = ks.x(1) < 0;
            turn++;
            if (is_bottom)
            {
                cout << "S 0 -1" << endl;
                cin >> distance_y;
                predicted_y = -100000 + distance_y;
            }
            else
            {
                cout << "S 0 1" << endl;
                cin >> distance_y;
                predicted_y = 100000 - distance_y;
            }

            cin >> c >> h;

            if (c == 1)
            {
                // この場合には壁に当たったので、速度を0に直してやり直し
                ks.x(0) += ks.x(2) * 2;
                ks.x(1) += ks.x(3) * 2;
                ks.x(2) = 0;
                ks.x(3) = 0;

                ks.P(2, 2) = 0;
                ks.P(3, 3) = 0;
                // continue;
            }
            // 制御入力の用意
            control_input = Eigen::Matrix<double, 4, 1>::Zero();

            // 観測の用意
            observation = Eigen::Matrix<double, 2, 1>::Zero();
            observation(0) = ks.x(0);
            observation(1) = predicted_y + ks.x(3);

            // 観測ノイズの共分散行列
            observation_noise_cov = Eigen::Matrix<double, 2, 2>::Identity();
            observation_noise_cov(0, 0) = pow(10, 15);
            observation_noise_cov(1, 1) = distance_y * distance_y * delta * delta;

            ks = kf.step(ks, control_input, Observation<2>(observation), process_noise_cov, observation_noise_cov);

            if (h > 0)
            {
                vec_int q(h);
                rep(i, h) cin >> q[i];
                rep(i, h)
                {
                    found_flag[q[i]] = true;
                    found += 1;

                    /*
                    ks.x(0) = px[q[i]];
                    ks.x(1) = py[q[i]];

                    ks.P(0, 0) = ks.x(2) * ks.x(2);
                    ks.P(1, 1) = ks.x(3) * ks.x(3);
                    */
                }
                break;
            }
        }
    }

    return 0;
}

Submission Info

Submission Time
Task A - Windy Drone Control (A)
User yunix
Language C++ 20 (gcc 12.2)
Score 475780
Code Size 31096 Byte
Status AC
Exec Time 100 ms
Memory 4080 KiB

Compile Error

Main.cpp: In function ‘void remove_val_and_pop_from_last(vec_int&, int)’:
Main.cpp:57:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<int>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
   57 |     for (int i = 0; i < A.size(); i++)
      |                     ~~^~~~~~~~~~
Main.cpp: In function ‘int main(int, char**)’:
Main.cpp:507:16: warning: unused variable ‘dist’ [-Wunused-variable]
  507 |         double dist = sqrt((double)(px[best_perm[i]] - px[best_perm[i + 1]]) * (double)(px[best_perm[i]] - px[best_perm[i + 1]]) + (double)(py[best_perm[i]] - py[best_perm[i + 1]]) * (double)(py[best_perm[i]] - py[best_perm[i + 1]]));
      |                ^~~~
Main.cpp:678:24: warning: unused variable ‘vx_perp_size’ [-Wunused-variable]
  678 |                 double vx_perp_size = sqrt(vx_perp * vx_perp + vy_perp * vy_perp);
      |                        ^~~~~~~~~~~~
Main.cpp:575:20: warning: unused variable ‘vx_perp_size’ [-Wunused-variable]
  575 |             double vx_perp_size = sqrt(vx_perp * vx_perp + vy_perp * vy_perp);
      |                    ^~~~~~~~~~~~
Main.cpp:523:16: warning: unused variable ‘min_dist’ [-Wunused-variable]
  523 |         double min_dist = 1e9;
      |                ^~~~~~~~
Main.cpp:420:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
  420 | int main(int argc, char *argv[])
      |          ~~~~^~~~
Main.cpp:420:26: warning: unused parameter ‘argv’ [-Wunused-parameter]
  420 | int main(int argc, char *argv[])
      |                    ~~~~~~^~~~~~

Judge Result

Set Name test_ALL
Score / Max Score 475780 / 600000
Status
AC × 60
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, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt
Case Name Status Exec Time Memory
test_0000.txt AC 84 ms 3916 KiB
test_0001.txt AC 77 ms 3912 KiB
test_0002.txt AC 79 ms 4072 KiB
test_0003.txt AC 80 ms 3960 KiB
test_0004.txt AC 80 ms 4004 KiB
test_0005.txt AC 88 ms 3916 KiB
test_0006.txt AC 79 ms 3912 KiB
test_0007.txt AC 79 ms 3856 KiB
test_0008.txt AC 78 ms 3980 KiB
test_0009.txt AC 73 ms 3920 KiB
test_0010.txt AC 74 ms 3856 KiB
test_0011.txt AC 76 ms 3784 KiB
test_0012.txt AC 74 ms 3968 KiB
test_0013.txt AC 76 ms 3820 KiB
test_0014.txt AC 84 ms 3912 KiB
test_0015.txt AC 74 ms 3856 KiB
test_0016.txt AC 76 ms 3876 KiB
test_0017.txt AC 78 ms 3968 KiB
test_0018.txt AC 74 ms 3856 KiB
test_0019.txt AC 80 ms 3876 KiB
test_0020.txt AC 74 ms 3872 KiB
test_0021.txt AC 78 ms 3920 KiB
test_0022.txt AC 83 ms 3976 KiB
test_0023.txt AC 100 ms 3924 KiB
test_0024.txt AC 83 ms 4016 KiB
test_0025.txt AC 80 ms 3860 KiB
test_0026.txt AC 74 ms 3852 KiB
test_0027.txt AC 77 ms 3852 KiB
test_0028.txt AC 79 ms 4016 KiB
test_0029.txt AC 74 ms 3832 KiB
test_0030.txt AC 76 ms 4024 KiB
test_0031.txt AC 76 ms 4072 KiB
test_0032.txt AC 79 ms 3904 KiB
test_0033.txt AC 74 ms 3860 KiB
test_0034.txt AC 77 ms 4012 KiB
test_0035.txt AC 76 ms 3860 KiB
test_0036.txt AC 79 ms 3900 KiB
test_0037.txt AC 86 ms 3852 KiB
test_0038.txt AC 76 ms 4008 KiB
test_0039.txt AC 84 ms 3852 KiB
test_0040.txt AC 82 ms 4080 KiB
test_0041.txt AC 79 ms 4028 KiB
test_0042.txt AC 76 ms 3924 KiB
test_0043.txt AC 79 ms 3924 KiB
test_0044.txt AC 84 ms 4012 KiB
test_0045.txt AC 88 ms 3912 KiB
test_0046.txt AC 76 ms 4024 KiB
test_0047.txt AC 75 ms 3976 KiB
test_0048.txt AC 74 ms 3976 KiB
test_0049.txt AC 74 ms 3872 KiB
test_0050.txt AC 84 ms 3856 KiB
test_0051.txt AC 77 ms 3784 KiB
test_0052.txt AC 83 ms 4072 KiB
test_0053.txt AC 75 ms 3964 KiB
test_0054.txt AC 73 ms 3900 KiB
test_0055.txt AC 78 ms 3976 KiB
test_0056.txt AC 77 ms 4012 KiB
test_0057.txt AC 88 ms 3908 KiB
test_0058.txt AC 84 ms 3980 KiB
test_0059.txt AC 87 ms 4004 KiB