ACM街区最短路径问题



街区最短路径问题

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 4
  • 描述

  • 一个街区有很多住户,街区的街道只能为东西、南北两种方向。

    住户只可以沿着街道行走。

    各个街道之间的间隔相等。

    用(x,y)来表示住户坐在的街区。

    例如(4,20),表示用户在东西方向第4个街道,南北方向第20个街道。

    现在要建一个邮局,使得各个住户到邮局的距离之和最少。

    求现在这个邮局应该建在那个地方使得所有住户距离之和最小;

    • 输入

    • 第一行一个整数n<20,表示有n组测试数据,下面是n组数据;
      每组第一行一个整数m<20,表示本组有m个住户,下面的m行每行有两个整数0 m行后是新一组的数据;

    • 输出

    • 每组数据输出到邮局最小的距离和,回车结束;

    • 样例输入

    • 2
      3
      1 1
      2 1
      1 2
      5
      2 9 
      5 20
      11 9
      1 1
      1 20
    • 样例输出

    • 2
      44


思路:

  1. 邮局肯定只能在其中一个点上,不然最短路径肯定多出一截

  2. 只能顺着边走(x,y)  不能斜着走  所以不是中心问题



fwrite (STDOUT, "input test collection count is : ");


$N       = trim (fgets (STDIN));

$points  = []; 

$min_map = []; 


for ($i = 0; $i < $N; $i++) {

    fwrite (STDOUT, "input point's count : ");

    $p_count     = trim (fgets (STDIN));


    for ($j = 0; $j < $p_count; $j++) {

        fwrite (STDOUT, "input this point x and y : ");


        $point_arr = explode (' ', trim(fgets (STDIN)));

        $points[]  = [ 

            'x' =>  $point_arr[0],

            'y' =>  $point_arr[1],

        ];  

    }   


    cal_minium_length_by_points ($points);

}


function cal_minium_length_by_points ($points) {

    for ($i = 0; $i < count($points); $i++) {

        $sum    = 0;

        $point1 = $points[$i];


        for ($j = 0; $j < count ($points); $j++) {

            if ($i == $j) {

                continue;

            }   


            $point2 = $points[$j];

            $length = get_two_points_length ($point1, $point2);

            $sum   += $length;

        }   


        $min_map[$sum] = $point1;

    }   


    $min_length = min (array_keys ($min_map));

    $min_point  = $min_map[$min_length];


    echo "邮局位置: ";

    print_r($min_point);

    echo "\n";

    echo "最短长度和 : $min_length";

}


function get_two_points_length ($p1, $p2) {

    return abs ($p1['x'] - $p2['x']) + abs ($p1['y'] - $p2['y']);

}


你可能感兴趣的:(ACM)