我找到了A*-Algorithm 我想用它来找到8-Puzzle的最佳解决方案。
就像图片中的拼图一样:
0 1 2
3 4 5
6 7 8
并表示为数组:0 1 2 3 4 5 6 7 8
“Neighbor-function”返回数组索引的所有邻居。 邻居是距离数组索引垂直或水平一个字段的所有数字。
示例:邻居(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等。编程语言并不重要,只要它可以移植到其中一个:C / C ++ / Delphi / C#
提前致谢!
答案 0 :(得分:2)
正如评论中所提到的,您只需要一个查找表。邻居的数量不是恒定的,因此您需要一种方法来了解每个方块有多少邻居。这可以使用sentinel value完成,如下所示
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( "%d\n", list[i] );
}
请注意,查找表可以手动编码,也可以在启动时通过您已有的代码自动生成。
答案 1 :(得分:1)
使用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;
答案 2 :(得分:1)
这些回复主要关注矩阵的静态x和y大小...如果你对algorythmics感兴趣,你可以将它们变为变量:
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;
答案 3 :(得分:0)
我有一个拼写网格的求解器,它可以通过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);
}
}
}