結果

問題 No.5007 Steiner Space Travel
ユーザー ainem-mainem-m
提出日時 2023-04-27 12:26:36
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
MLE  
実行時間 -
コード長 5,137 bytes
コンパイル時間 4,175 ms
実行使用メモリ 819,200 KB
スコア 0
最終ジャッジ日時 2023-04-27 12:26:44
合計ジャッジ時間 5,193 ms
ジャッジサーバーID
(参考情報)
judge11 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 MLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: 関数 ‘std::vector<int> dijkstra(int, int)’ 内:
main.cpp:71:24: 警告: ‘next’ may be used uninitialized [-Wmaybe-uninitialized]
   71 |         for (int next; next < points.size(); next++)
      |                        ^~~~
main.cpp:71:18: 備考: ‘next’ はここで宣言されています
   71 |         for (int next; next < points.size(); next++)
      |                  ^~~~

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;

template <typename T>
bool chmin(T &a, const T &b)
{
    if (a > b)
    {
        a = b;
        return true;
    }
    return false;
}

const int INF = 1000000000;

int N,
    M;
vector<pair<int, int>>
    points;

/**
 * 2点間の消費エネルギーを計算する関数
 */
int calc_energy(int i, int j)
{
    int dx, dy;
    int energy;
    auto [x1, y1] = points[i];
    auto [x2, y2] = points[j];
    dx = x1 - x2;
    dy = y1 - y2;
    energy = dx * dx + dy * dy;

    // 惑星かどうかは i < Nで判定可能
    if (i < N)
    {
        energy *= 5;
    }
    if (j < N)
    {
        energy *= 5;
    }
    return energy;
}

/**
 *  ダイクストラを行い、経由点iから経由点jへの最短経路を復元する関数
 */
vector<int> dijkstra(int i, int j)
{
    vector<int> dijkstra_dist(points.size(), INF);

    // 1つ前にいた頂点を保存する配列(経路復元用)
    vector<int> prev_points(points.size(), -1);

    // (距離, 頂点)のペアをpush
    priority_queue<pair<int, int>> queue;
    queue.emplace(0, i);
    dijkstra_dist[i] = 0;

    while (!queue.empty())
    {
        auto [d, v] = queue.top();
        queue.pop();
        if (d > dijkstra_dist[v])
        {
            continue;
        }

        for (int next; next < points.size(); next++)
        {
            int next_d = d + calc_energy(v, next);
            if (next_d < dijkstra_dist[next])
            {
                // 1つ前の頂点を保存しておく
                prev_points[next] = v;
                dijkstra_dist[next] = next_d;
                queue.emplace(next_d, next);
            }
        }
    }

    // ここから経路復元
    // ゴールから1つずつ原点を辿っていく
    // パンくずみたいな感じ
    int v = j;
    vector<int> path;

    while (v != i)
    {
        path.push_back(v);
        v = prev_points[v];
    }

    // pathには経路が逆順で入っているのでひっくり返す
    reverse(path.begin(), path.end());

    return path;
}

int main()
{
    // 入力読み込み
    cin >> N >> M;
    for (int i = 0; i < N; i++)
    {
        int a, b;
        cin >> a >> b;
        points.emplace_back(a, b);
    }

    // 宇宙ステーションの座標は適当に決め打ち
    //
    // x x x
    // x   x
    // x x x
    //
    // みたいにする

    points.emplace_back(300, 300);
    points.emplace_back(300, 500);
    points.emplace_back(300, 700);
    points.emplace_back(500, 300);
    points.emplace_back(500, 700);
    points.emplace_back(700, 300);
    points.emplace_back(700, 500);
    points.emplace_back(700, 700);

    // ワーシャルフロイド
    vector<vector<int>> distances(points.size(), vector<int>(points.size(), 0));

    // 全点間エネルギーを計算
    for (int i = 0; i < points.size(); i++)
    {
        for (int j = 0; j < points.size(); j++)
        {
            distances[i][j] = calc_energy(i, j);
        }
    }

    // ワーシャルフロイド
    for (int k = 0; k < points.size(); k++)
    {
        for (int i = 0; i < points.size(); i++)
        {
            for (int j = 0; j < points.size(); j++)
            {
                int d = distances[i][k] + distances[k][j];
                chmin(distances[i][j], d);
            }
        }
    }

    // 経路の作成(貪欲法)

    // 惑星1から出発し、一番近い惑星を貪欲に選び続ける(Nearest Neighbour法)
    int v = 0;
    vector<bool> visited(N, false);
    visited[0] = true;
    vector<int> route{0};

    // 惑星1以外のN-1個の惑星を訪問していく
    for (int i = 0; i < N - 1; i++)
    {
        int nearest_dist = INF;
        int nearest_v = -1;

        // 一番近い惑星を探す
        for (int next = 0; next < N; next++)
        {
            if (visited[next])
            {
                continue;
            }
            if (distances[v][next] < nearest_dist)
            {
                nearest_dist = distances[v][next];
                nearest_v = next;
            }

            // パスを復元
            vector<int> path = dijkstra(v, nearest_v);
            // pythonでいうextend, rustでいうappendの挙動をする関数がわからなくて…
            for (auto p : path)
            {
                route.push_back(p);
            }
            // 次の頂点に移動
            v = nearest_v;
            visited[v] = true;
        }
    }
    // 最後に惑星1に戻る必要がある
    vector<int> path = dijkstra(v, 0);
    for (auto p : path)
    {
        route.push_back(p);
    }

    // 解の出力
    // 宇宙ステーションの座標を出力
    for (int i = N; i < N + M; i++)
    {
        cout << points[i].first << " " << points[i].second << endl;
    }
    // 経路の長さを出力
    cout << route.size() << endl;

    // 経路を出力
    for (auto v : route)
    {
        if (v < N)
        {
            cout << "1 " << v + 1 << endl;
        }
        else
        {
            cout << "2 " << v - N + 1 << endl;
        }
    }
}
0