PHP:确定2个网格之间的网格数

时间:2014-05-08 05:13:41

标签: php math path-finding

编辑:允许对角线移动

我有一个5x5网格(只是为了让自己更容易,虽然会增长到30x30甚至更大)并且我试图确定2个网格之间的网格数,但是,它正在做我的头,我希望也许有人可以指出我正确的方向。我试图实现的基本上是用户选择2个网格,即30043017,然后它应该找到最短路径并计算网格。例如,30043017之间的网格数应为430013005之间的网格数应为530013017之间的网格数应为430013002之间的网格数应为2等。

网格:

------------------------------------
| 3001 | 3002 | 3003 | 3004 | 3005 |
------------------------------------
| 3006 | 3007 | 3008 | 3009 | 3010 |
------------------------------------
| 3011 | 3012 | 3013 | 3014 | 3015 |
------------------------------------
| 3016 | 3017 | 3018 | 3019 | 3020 |
------------------------------------
| 3021 | 3022 | 3023 | 3024 | 3025 |
------------------------------------

我的数组按以下方式构建:

$grids = array(
    1 => array(
        1 => 3001,
        2 => 3002,
        3 => 3003,
        4 => 3004,
        5 => 3005
    ),
    2 => array(
        1 => 3006,
        2 => 3007,
        3 => 3008,
        4 => 3009,
        5 => 3010
    ),
    3 => array(
        1 => 3011,
        2 => 3012,
        3 => 3013,
        4 => 3014,
        5 => 3015
    ),
    4 => array(
        1 => 3016,
        2 => 3017,
        3 => 3018,
        4 => 3019,
        5 => 3020
    ),
    5 => array(
        1 => 3021,
        2 => 3022,
        3 => 3023,
        4 => 3024,
        5 => 3025
    ),
);

我尝试了什么:

我意识到我可以使用好的旧斜视 a 2 + b 2 = c 2

这对于一些例子来说非常有用,但不是每次都有。例如,如果我插入30043017,则网格计数应为4,但是,它会吐出5或者插入3001并且3025网格数将为7,它位于网格本身之外。我明白为什么这些结果会出现,所以我想检查是否有办法改进公式以使其以某种方式工作?

这个问题让我很伤心,因为我非常接近我能尝到的解决方案。

非常感谢您提前获得所有帮助!

我目前的代码:(请原谅杂乱)

<style>
.grid {
    display: inline-block;
    line-height: 50px; padding-left: 10px; padding-right: 10px;
    border:1px solid black;
}
.grid.active {
    background: red;
}
</style>
<?php

/*
3001  3002  3003  3004  3005
3006  3007  3008  3009  3010
3011  3012  3013  3014  3015
3016  3017  3018  3019  3020
3021  3022  3023  3024  3025
*/

$from = 3001;
$to   = 3025;

$grids = array(
    1 => array(
        1 => 3001,
        2 => 3002,
        3 => 3003,
        4 => 3004,
        5 => 3005
    ),
    2 => array(
        1 => 3006,
        2 => 3007,
        3 => 3008,
        4 => 3009,
        5 => 3010
    ),
    3 => array(
        1 => 3011,
        2 => 3012,
        3 => 3013,
        4 => 3014,
        5 => 3015
    ),
    4 => array(
        1 => 3016,
        2 => 3017,
        3 => 3018,
        4 => 3019,
        5 => 3020
    ),
    5 => array(
        1 => 3021,
        2 => 3022,
        3 => 3023,
        4 => 3024,
        5 => 3025
    ),
);

$from_cells = 1;
$from_rows  = 1;

foreach ( $grids as $y => $xs )
{
    $from_cells = 1;

    foreach ( $xs as $x => $postcode )
    {
        if ( $postcode == $from )
        {
            break 2;
        }
        else
        {
            $from_cells++;
        }
    }

    $from_rows++;
}

$to_cells = 1;
$to_rows  = 1;

foreach ( $grids as $y => $xs )
{
    $to_cells = 1;

    foreach ( $xs as $x => $postcode )
    {
        if ( $postcode == $to )
        {
            break 2;
        }
        else
        {
            $to_cells++;
        }
    }

    $to_rows++;
}

echo "From<hr/>X: $from_cells | Y: $from_rows<br/><hr/>To<hr/>X: $to_cells | Y: $to_rows";

$leg1 = 0;
$leg2 = 0;

$cell_short = ($from_cells < $to_cells) ? $from_cells : $to_cells;
$cell_long  = ($from_cells > $to_cells) ? $from_cells : $to_cells;

for ( $i=$cell_short; $i <= $cell_long; $i++ )
{
    $leg1 = $i;
}

$row_short = ($from_rows < $to_rows) ? $from_rows : $to_rows;
$row_long  = ($from_rows > $to_rows) ? $from_rows : $to_rows;

for ( $i=$row_short; $i <= $row_long; $i++ )
{
    $leg2 = $i;
}

echo "<hr/>Length: $leg1<br/>Height: $leg2";

$grid_count = pow($leg1,2) + pow($leg2,2);
$grid_count = floor(sqrt($grid_count));

echo "<hr/>Grids: $grid_count<hr/>";

foreach ( $grids as $y => $xs )
{
    foreach ( $xs as $x => $postcode )
    {
        if ( $postcode == $from or $postcode == $to )
        {
            echo '<div class="grid active">'.$postcode.'</div>';
        }
        else
        {
            echo '<div class="grid">'.$postcode.'</div>';
        }
    }

    echo '<br/>';
}

如果需要任何其他信息,请告诉我,我会把它丢进去。

2 个答案:

答案 0 :(得分:2)

您可以进行的对角线移动次数限制为您必须遍历以到达目的地的行数或列数。所有其他移动可以是左/右或上/下,并保持最短距离。

那就是说,假设你知道你的细胞的行数和col数,我相信这会给你最短的距离:

$startCol = [column of starting cell];
$startRow = [row of starting cell];

$endCol = [column of end cell];
$endRow = [row of end cell];

$numMoves = 0;

$moveCol = 0;
$moveRow = 0;

/*
 * figure out which direction the end cell is, in relation to the
 * start cell.
 */

// end is to the right, so we need to add columns to the start
if( $startCol < $endCol ) {
    $moveCol = 1;
}
// end is to the left (or in the same column), so we need to subtract
// column from the start
else {
    $moveCol = -1;
}

// end is below the start, so we need to add rows
if( $startRow < $endRow ) {
    $moveRow = 1;
}
// end is above (or in the same row), so we need to subtract rows to the start
else {
    $moveRow = -1;
}

/*
 * now go diagnoal until you hit either the row or the column
 * that the end cell is in
 */

while( $startCol != $endCol && $startRow != $endRow ) {
    $startCol += $moveCol;
    $startRow += $moveRow;
    $numMoves++;
}

/* at this point, we're either in the same row or the same column
 * as our destination, so just move down that row or col until we
 * reach the destination
 */

// already at the destination, don't do anything
if( $startCol == $endCol && $startRow == $endRow ) {
}
// in the same column, so move up/down rows
else if( $startCol == $endCol ) {
    while( $startRow != $endRow ) {
        $startRow += $moveRow;
        $numMoves++;
    }
}
// in the same row, so move left/right cols
else {
    while( $startCol != $endCol ) {
        $startCol += $moveCol;
        $numMoves++;
    }
}

echo "min moves: $numMoves";

在此示例中,您不需要任何网格知识,只要您假设开始和结束坐标实际上在网格内。

答案 1 :(得分:1)

也许不是最优雅的,也可以简化。但它的确有效:

假设:

$from = 3001;
$to   = 3025;

$grids = array(
    1 => array(
        1 => 3001,
        2 => 3002,
        3 => 3003,
        4 => 3004,
        5 => 3005
    ),
    2 => array(
        1 => 3006,
        2 => 3007,
        3 => 3008,
        4 => 3009,
        5 => 3010
    ),
    3 => array(
        1 => 3011,
        2 => 3012,
        3 => 3013,
        4 => 3014,
        5 => 3015
    ),
    4 => array(
        1 => 3016,
        2 => 3017,
        3 => 3018,
        4 => 3019,
        5 => 3020
    ),
    5 => array(
        1 => 3021,
        2 => 3022,
        3 => 3023,
        4 => 3024,
        5 => 3025
    ),
);

算法:

// Determine the (x,y) coordinates of $from and $to
foreach($grids as $row=>$g) {

    if (in_array($from, $g)) {
        $from_row = $row;
        foreach ($g as $col=>$val) {
            if ($val==$from)
                $from_col = $col;
        }
    }
    if (in_array($to, $g)) {
        $to_row = $row;
        foreach ($g as $col=>$val) {
            if ($val==$to)
                $to_col = $col;
        }
    }
}

// Difference between $from cols, $to cols and $from rows, $to rows
$col_diff = abs($from_col-$to_col);
$row_diff = abs($from_row-$to_row);

if ($col_diff==4) {
    $d = 5;
}
elseif ($col_diff==3) {
    if ($row_diff==4) 
        $d = 5;
    else
        $d = 4;
}
elseif ($col_diff==2) {
    if ($row_diff==4)
        $d = 5;
    elseif ($row_diff==3)
        $d = 4;
    else
        $d = 3;
}
elseif ($col_diff==1) {
    if ($row_diff==4)
        $d = 5;
    elseif ($row_diff==3)
        $d = 4;
    elseif ($row_diff==2)
        $d = 3;
    else
        $d = 2;
}
elseif ($col_diff==0) {
    if ($row_diff==4)
        $d = 5;
    elseif ($row_diff==3)
        $d = 4;
    elseif ($row_diff==2)
        $d = 3;
    elseif ($row_diff==1)
        $d = 2;
    else
        $d = 1;
}

echo $from . ' -> ' . $to . ' = ' . $d;