"Neighbor function"优化以使用A*算法解决8难题

"Neighbor function" optimization to solve 8-Puzzle using A*-Algorithm

本文关键字:算法 解决 难题 Neighbor function 优化      更新时间:2023-10-16

我找到了a*-algorithm我想使用它来找到8个puzzle的最佳解决方案。

图片中的拼图看起来像:

0 1 2
3 4 5
6 7 8

并表示为一个数组:0 1 2 3 4 5 6 7 8

"邻居权力"返回数组索引的所有邻居。邻居都是一个数字,它们是一个字段垂直或远离数组索引的水平。

示例:邻居(4)将返回1,5,7,3,邻居(6)将返回3,7

我当前的解决方案(由Uwe Raabe 编码):

function Neighbours(zahl: Integer): TArray<Integer>;
var
  lst: TList<Integer>;
  c: Integer;
  r: Integer;
begin
  lst := TList<Integer>.Create;
  try
    c := zahl mod 3;
    r := zahl div 3;
    if r > 0 then
      lst.Add(zahl-3);
    if c > 0 then
      lst.Add(zahl-1);
    if c < 2 then
      lst.Add(zahl+1);
    if r < 2 then
      lst.Add(zahl+3);
    result := lst.ToArray;
  finally
    lst.Free;
  end;
end;

我正在寻找一个紧凑,更好的解决方案。我很想看到一些算法。我不喜欢IF的ECT。只要它可以便携到其中之一:c/c /delphi/c#

,该编程语言就不会真正重要。

预先感谢!

如评论中所述,您需要的只是一个查找表。邻居的数量不是恒定的,因此您需要一种方法来知道每个正方形有多少邻居。这可以用哨兵值进行,如下所示

int neighbors[9][5] = {
    {  1, 3,-1,-1,-1 },
    {  0, 2, 4,-1,-1 },
    // etc
};
int main( void )
{
    // get the list of neighbors for square 1
    int *list = neighbors[1];
    // print the list of neighbors
    for ( int i = 0; list[i] >= 0; i++ )
        printf( "%dn", list[i] );
}

请注意,查找表可以手工编码,也可以在启动时通过您已经拥有的代码自动生成。

使用delphi xe7或较新的查找表解决方案紧凑:

function Neighbours( number: Integer): TArray<Integer>;
const
  resCount: array[0..8] of Integer = (2,3,2,3,4,3,2,3,2);
  resValue: TArray<TArray<Integer>> = [
    [1,3,-1,-1],
    [0,2,4,-1],
    [1,5,-1,-1],
    [0,4,6,-1],
    [1,3,5,7],
    [2,4,8,-1],
    [3,7,-1,-1],
    [4,6,8,-1],
    [5,7,-1,-1]];
begin
  SetLength(Result,4);  // Set default length
  Result := resValue[number];  // Assign a solution vector
  SetLength(Result,resCount[number]); // Correct result length
end;

您不太可能找到一种比问题中给出的算法更紧凑的算法。即使您考虑if语句丑陋,它们也是有效的,并且是每种(几乎)编程语言的中心部分。


或使用OP提出的集合:

Type
  TMySet = set of 0..8;
function Neighbours( number: Integer): TMySet;
const 
  NeighboursA: array[0..8] of TMySet = 
    ([1,3], [0,2,4], [1,5], [0,4,6],[1,3,5,7], [2,4,8], [3,7], [4,6,8], [5,7]);
begin
  Result := NeighboursA[number];
end;

这些答案重点关注矩阵的静态X和y尺寸...如果您对算法感兴趣,则可以使它们变量:

function Neighbours(zahl: Integer; xSize,Ysize:integer): TArray<Integer>;
var
  lst: TList<Integer>;
  x: Integer;
  y: Integer;
begin
  lst := TList<Integer>.Create;
  try
    x := zahl mod xSize;
    y := zahl div ySize;
    if x > 0 then
      lst.Add(zahl-1);
    if x < (xSize - 1) then
      lst.Add(zahl+1);
    if y > 0 then
      lst.Add(zahl-xSize);
    if y < (ySize - 1) then
      lst.Add(zahl+xSize);
    result := lst.ToArray;
  finally
    lst.Free;
  end;
end;

我有一个求解器,用于拼写网格,该网格在C#中通过Algorythm在C#中进行此操作,该算法适用于任何尺寸矩阵

private void InitPaths()
{
    PathDictionary.Clear();
    for (var rowstart = 0; rowstart < GridRowSize; rowstart++)
    {
        for (var colstart = 0; colstart < GridColSize; colstart++)
        {
            var tuples = new List<Tuple<int, int>>();
            for (var r = rowstart - 1; r <= rowstart + 1; r++)
            {
                if (r < 0 || r >= GridRowSize) continue;
                for (var c = colstart - 1; c <= colstart + 1; c++)
                {
                    if (c < 0 || c >= GridColSize || (r == rowstart && c == colstart)) continue;
                    tuples.Add(new Tuple<int, int>(r, c));
                }
            }
            PathDictionary.Add(new Tuple<int, int>(rowstart, colstart), tuples);
        }
    }
}