大尺寸迷宫求解器的 OutOfMemoryException
OutOfMemoryException For Maze Solver of Large Dimensions
该程序适用于最大 20x20 的数组,但对于更大的数组,它会抛出 OutOfMemoryException。
代码如下:
public static Point GetFinalPath(int x, int y) {
queue.Enqueue(new Point(x,y, null));
while(queue.Count>0) {
Point p = queue.Dequeue();
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Found Destination");
return p;
}
if(IsOpen(p.x+1,p.y)) {
arr[p.x,p.y] = 1;
queue.Enqueue(new Point(p.x+1,p.y, p));
}
//similarly for the other directions
}
return null;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(0, 0);
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
好的,这里是代码的其余部分
public static Queue<Point> queue=new Queue<Point>();
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}
假设开始为 0,0,最终目的地在构造函数中设置为 9。
帮我实现一个大小为 500x500 的数组
嗯,看了你的代码我发现了一个问题。您执行了错误的检查。您应该检查您的点是否已添加到队列中。你现在做什么?我们会的,您只是将已处理的单元格标记为未打开。很容易看出您可以将同一节点添加到队列两次。
让我们以我的例子为例:
1 | . .
0 | ! .
--+----
yx| 0 1
Queue: point (0,0)
我们从点 (0,0) 开始。此时,我们将点 (0, 1) 和 (1,0) 添加到我们的队列中并将点 (0,0) 标记为已处理
1 | . .
0 | X !
--+----
yx| 0 1
Queue: point (0,1), point (1,0)
现在我们将点 (0,1) 出列,将其标记为已处理并将点 (1,1) 添加到队列中。
1 | ! .
0 | X X
--+----
yx| 0 1
Queue: point (1,0), point(1,1)
现在我们将点 (1,0) 出列,将其标记为已处理并将点 (1,1) 添加到队列中:
1 | X !
0 | X X
--+----
yx| 0 1
Queue: point (1,1), point (1,1)
现在我们在队列中有两次相同的点。那不是你的最后一个问题。您的点数引用了它的所有父项,因此您之前的点数(也加倍)无法使用垃圾收集器处理。
好的,我找到了 OutOfMemory 的答案。现在代码甚至适用于 500x500 矩阵
事实证明,我刚刚实现了一个节点列表,它使用 y*MAX_X_LENGTH + x 公式
跟踪队列中添加的节点
public static Queue<Point> queue=new Queue<Point>();
public SolveMaze(int[,] array,int staX,int staY,int finX,int finY)
{
//sets Destination as 9
arr = array;
XMAX = array.GetLength(0);
YMAX = array.GetLength(1);
finishY = finX; finishX = finY; startY = staX; startX = staY;
solvedarray = new int[XMAX, YMAX];
}
public static List<int> nodelist=new List<int>();
public void AddPointToQueueIfOpenAndNotAlreadyPresent(Point p,int direction)
{
if (nodelist.Contains(XMAX * p.y + p.x))
return;
else
{
switch(direction){
case 1:
//north
if (IsOpen(p.x, p.y - 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y - 1, p));
nodelist.Add(XMAX * (p.y - 1) + p.x);
}
break;
case 0:
//east
if (IsOpen(p.x + 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x + 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x + 1);
}
break;
case 3:
//south
if (IsOpen(p.x, p.y + 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y +1, p));
nodelist.Add(XMAX * (p.y + 1) + p.x);
}
break;
case 2:
//west
if (IsOpen(p.x - 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x - 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x-1);
}
break; }
}
}
public Point GetFinalPath(int x, int y) {
if (arr[finishX, finishY] == 0)
arr[finishX, finishY] = 9;
else
return null;
queue.Enqueue(new Point(x, y, null));
nodelist.Add(XMAX * y + x);
while(queue.Count>0) {
Point p = queue.Dequeue();
nodelist.Remove(p.y * XMAX + p.x);
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Exit is reached!");
return p;
}
for (int i = 0; i < 4; i++)
{
AddPointToQueueIfOpenAndNotAlreadyPresent(p, i);
}
}
return null;
}
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(startX, startY);
if(p!=null)
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}
该程序适用于最大 20x20 的数组,但对于更大的数组,它会抛出 OutOfMemoryException。
代码如下:
public static Point GetFinalPath(int x, int y) {
queue.Enqueue(new Point(x,y, null));
while(queue.Count>0) {
Point p = queue.Dequeue();
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Found Destination");
return p;
}
if(IsOpen(p.x+1,p.y)) {
arr[p.x,p.y] = 1;
queue.Enqueue(new Point(p.x+1,p.y, p));
}
//similarly for the other directions
}
return null;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(0, 0);
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
好的,这里是代码的其余部分
public static Queue<Point> queue=new Queue<Point>();
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}
假设开始为 0,0,最终目的地在构造函数中设置为 9。
帮我实现一个大小为 500x500 的数组
嗯,看了你的代码我发现了一个问题。您执行了错误的检查。您应该检查您的点是否已添加到队列中。你现在做什么?我们会的,您只是将已处理的单元格标记为未打开。很容易看出您可以将同一节点添加到队列两次。
让我们以我的例子为例:
1 | . .
0 | ! .
--+----
yx| 0 1
Queue: point (0,0)
我们从点 (0,0) 开始。此时,我们将点 (0, 1) 和 (1,0) 添加到我们的队列中并将点 (0,0) 标记为已处理
1 | . .
0 | X !
--+----
yx| 0 1
Queue: point (0,1), point (1,0)
现在我们将点 (0,1) 出列,将其标记为已处理并将点 (1,1) 添加到队列中。
1 | ! .
0 | X X
--+----
yx| 0 1
Queue: point (1,0), point(1,1)
现在我们将点 (1,0) 出列,将其标记为已处理并将点 (1,1) 添加到队列中:
1 | X !
0 | X X
--+----
yx| 0 1
Queue: point (1,1), point (1,1)
现在我们在队列中有两次相同的点。那不是你的最后一个问题。您的点数引用了它的所有父项,因此您之前的点数(也加倍)无法使用垃圾收集器处理。
好的,我找到了 OutOfMemory 的答案。现在代码甚至适用于 500x500 矩阵 事实证明,我刚刚实现了一个节点列表,它使用 y*MAX_X_LENGTH + x 公式
跟踪队列中添加的节点public static Queue<Point> queue=new Queue<Point>();
public SolveMaze(int[,] array,int staX,int staY,int finX,int finY)
{
//sets Destination as 9
arr = array;
XMAX = array.GetLength(0);
YMAX = array.GetLength(1);
finishY = finX; finishX = finY; startY = staX; startX = staY;
solvedarray = new int[XMAX, YMAX];
}
public static List<int> nodelist=new List<int>();
public void AddPointToQueueIfOpenAndNotAlreadyPresent(Point p,int direction)
{
if (nodelist.Contains(XMAX * p.y + p.x))
return;
else
{
switch(direction){
case 1:
//north
if (IsOpen(p.x, p.y - 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y - 1, p));
nodelist.Add(XMAX * (p.y - 1) + p.x);
}
break;
case 0:
//east
if (IsOpen(p.x + 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x + 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x + 1);
}
break;
case 3:
//south
if (IsOpen(p.x, p.y + 1))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x, p.y +1, p));
nodelist.Add(XMAX * (p.y + 1) + p.x);
}
break;
case 2:
//west
if (IsOpen(p.x - 1, p.y))
{
arr[p.x, p.y] = 1;
queue.Enqueue(new Point(p.x - 1, p.y, p));
nodelist.Add(XMAX * (p.y) + p.x-1);
}
break; }
}
}
public Point GetFinalPath(int x, int y) {
if (arr[finishX, finishY] == 0)
arr[finishX, finishY] = 9;
else
return null;
queue.Enqueue(new Point(x, y, null));
nodelist.Add(XMAX * y + x);
while(queue.Count>0) {
Point p = queue.Dequeue();
nodelist.Remove(p.y * XMAX + p.x);
if (arr[p.x,p.y] == 9) {
Console.WriteLine("Exit is reached!");
return p;
}
for (int i = 0; i < 4; i++)
{
AddPointToQueueIfOpenAndNotAlreadyPresent(p, i);
}
}
return null;
}
public static bool IsOpen(int x, int y)
{
//BOUND CHECKING
if ((x >= 0 && x < XMAX) && (y >= 0 && y < YMAX) && (arr[x,y] == 0 || arr[x,y] == 9))
{
return true;
}
return false;
}
public int[,] SolutionMaze()
{
Point p = GetFinalPath(startX, startY);
if(p!=null)
while (p.getParent() != null)
{
solvedarray[p.x, p.y] = 9;
p = p.getParent();
}
return solvedarray;
}
}
public class Point
{
public int x;
public int y;
Point parent;
public Point(int x, int y, Point parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public Point getParent()
{
return this.parent;
}
}