Submission #67638408


Source Code Expand

<?php

declare(strict_types=1);

/**
 * 距離行列を計算する
 *
 * @param array<int, array{int, int}> $coords 各都市の座標 [(x1, y1), ..., (xN, yN)]
 * @return array<int, array<int, float>> 距離行列 dist[i][j] = 都市iからjへの距離
 */
function computeDistances(array $coords): array {
    $N = count($coords);
    $dist = array_fill(0, $N, array_fill(0, $N, 0.0));
    for ($i = 0; $i < $N; $i++) {
        for ($j = 0; $j < $N; $j++) {
            $dx = $coords[$i][0] - $coords[$j][0];
            $dy = $coords[$i][1] - $coords[$j][1];
            $dist[$i][$j] = hypot($dx, $dy);
        }
    }
    return $dist;
}

/**
 * 巡回セールスマン問題を解く
 *
 * @param int $N 都市の数 (2 <= N <= 15)
 * @param array<int, array{int, int}> $coords 各都市の座標
 * @return float 最短距離(誤差1e-3以内)
 */
function solveTSP(int $N, array $coords): float {
    $dist = computeDistances($coords);
    $INF = INF;

    // dp[s][u] := 訪問済み集合s, 現在地u のときの最短距離
    $dp = array_fill(0, 1 << $N, array_fill(0, $N, $INF));
    $dp[1][0] = 0.0;

    for ($s = 1; $s < (1 << $N); $s++) {
        for ($u = 0; $u < $N; $u++) {
            if (!(($s >> $u) & 1)) continue;
            for ($v = 0; $v < $N; $v++) {
                if (($s >> $v) & 1) continue;
                $ns = $s | (1 << $v);
                $dp[$ns][$v] = min($dp[$ns][$v], $dp[$s][$u] + $dist[$u][$v]);
            }
        }
    }

    $res = $INF;
    for ($u = 1; $u < $N; $u++) {
        $res = min($res, $dp[(1 << $N) - 1][$u] + $dist[$u][0]);
    }

    return $res;
}

/**
 * 標準入力から座標情報を読み取り、solveTSP を呼び出すメイン関数
 */
function main(): void {
    [$N] = sscanf(trim(fgets(STDIN)), "%d");
    $coords = [];

    for ($i = 0; $i < $N; $i++) {
        [$x, $y] = sscanf(trim(fgets(STDIN)), "%d %d");
        $coords[] = [$x, $y];
    }

    $result = solveTSP($N, $coords);

    // 小数点以下12桁で出力(誤差1e-3対策)
    printf("%.12f\n", $result);
}

main();

Submission Info

Submission Time
Task B23 - Traveling Salesman Problem
User myoshizumi
Language PHP (php 8.2.8)
Score 1000
Code Size 2158 Byte
Status AC
Exec Time 101 ms
Memory 34160 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 1000 / 1000
Status
AC × 2
AC × 16
Set Name Test Cases
Sample sample_01.txt, sample_02.txt
All in01.txt, in02.txt, in03.txt, in04.txt, in05.txt, in06.txt, in07.txt, in08.txt, in09.txt, in10.txt, in11.txt, in12.txt, in13.txt, in14.txt, sample_01.txt, sample_02.txt
Case Name Status Exec Time Memory
in01.txt AC 13 ms 21208 KiB
in02.txt AC 12 ms 20724 KiB
in03.txt AC 12 ms 21200 KiB
in04.txt AC 13 ms 21132 KiB
in05.txt AC 13 ms 20732 KiB
in06.txt AC 12 ms 20812 KiB
in07.txt AC 13 ms 21136 KiB
in08.txt AC 14 ms 20948 KiB
in09.txt AC 14 ms 21104 KiB
in10.txt AC 19 ms 21648 KiB
in11.txt AC 26 ms 22688 KiB
in12.txt AC 45 ms 24380 KiB
in13.txt AC 84 ms 27200 KiB
in14.txt AC 101 ms 34160 KiB
sample_01.txt AC 13 ms 21508 KiB
sample_02.txt AC 14 ms 21524 KiB