迷宫出口最短路径解法

寻找迷宫出口的题目好像有很多,解法好像也很多,在这里我只是说说自己发现的一种解法。至于到底有没有人也是这样做的,说不准,方正我是没看过。那么请往下看。

首先,为了模拟迷宫,需要自己设置哪里是墙壁,哪里是通道,这个我采用01表示法来做:

1110000000000000
0010000000000000
0010001111111100
0010001000000100
0010001000000100
0010001111110100
0010000000010100
0011111111110111
0010000000010011
0010000000010010
0010000000010010
0010000000010010
0010000000010010
0010000000010010
0010000000010010
0011111111101111

以上一共是16*16个数字,0代表墙壁,1代表通道。到时候只需要读取文件,就可以模拟迷宫了。

(在我的程序中,使用二维数组来表示坐标,0表示墙壁,-1表示通道而且还没有人路过,1,2,3等表示从起点到该位置的步数,起点设置为1)

原理:其实原理很简单。如图

图像 022

阴影表示墙壁,1是起点。从起点开始,周围四格“可通”的话它的数值就在原来格数的基础上+1。这里“可通”的概念是,前进的那格既不是墙壁,也不是原方向,也不是已经走过的路径(对于后两者,目标格的数字会比当前格的数字小)。就这样1找到了2(两个),其中一个2找到了前进方向3…….图中有两个7,其中绕远路的显然不是我们希望的。

通过一步一步MarkTheWay(column,row) 递归,直到无路(每个分支都没有可以前进的格)可走了,结束寻路过程。

这里有程序的输出:

图像 021

1是起点,51是出口。在初始化的时候,出口被设置为-1,当出口不是-1时,就说明有路径可以到达出口。否则说明不能(如下图)。

图像 023

以上过程只是验证能否到达出口以及找出路径数目和最短步数,还没有指出怎么走。这样吧,从上面成功的路中可以看出,这样从出口处沿着数字递减的方向往回走,就一定能够找到起点。函数FindShortWay如下:

private void FindShortWay()
{
int column = x2;
int row = y2;
int current = migong[column, row];
while ((current = migong[column, row])!=1)
{
Console.Write(FormatPoint(column, row)+" -> ");
if (CanBack(column + 1, row,current))
{
column+=1;
continue;
}
if (CanBack(column - 1, row, current))
{
column -= 1;
continue;
}
if (CanBack(column, row + 1, current))
{
row += 1;
continue;
}
if (CanBack(column, row - 1, current))
{
row -= 1;
continue;
}
}

虽说最短路可能是多条,但是只要找到一条就足够了(我偷懒)。

 

//源代码附上。献丑了。

namespace Test

{
class FindMiGong
{
static void Main(string[] args)
{
FindWay findway = new FindWay();
findway.GetTheWay();//执行
Console.ReadLine();
}

}

class FindWay
{
private const int COUNT = 16;
private int x1 = 0;    //起点x坐标
private int y1 = 0;    //起点y坐标
private int x2 = 15;    //出口x坐标
private int y2 = 15;    //出口y坐标
public int WayCount { get; set; }    //通道数
public int ShortestWay = -1;//最短步数

private int[,] migong=new int[COUNT,COUNT];

private void InitMigong(string datafile)    //初始化
{
try
{
using (FileStream afile = new FileStream(datafile, FileMode.Open))
{
using (StreamReader reader = new StreamReader(afile))
{
string line = string.Empty;

for (int column = 0; column < COUNT; column++)
{
line = reader.ReadLine();
char[] chars = line.ToArray();
for (int row = 0; row < COUNT; row++)
{
migong[column, row] = int.Parse(chars[row].ToString());
}

}
}
for (int column = 0; column < COUNT; column++)
{
for (int row = 0; row < COUNT; row++)
{
if (migong[column,row] == 1)
migong[column, row] = -1;  //0表示墙壁,-1表示还无人路过。
}
}
migong[x1, y1] = 1;    //初始化起点
}
}
catch{throw;}
}

public void GetTheWay()
{
//0 is blocked,-1 is the init data;
string datafile = @"C:\Users\Administrator\Desktop\data.txt";
InitMigong(datafile);
MarkTheWay(x1,y1);  //最主要的步骤,详细内容往下看
if (IsArrived())  //是否可以达到出口
{
Console.WriteLine("shortest way is:"+ShortestWay);
Console.WriteLine("way count:" + WayCount);
FindShortWay();
}
else
{
Console.WriteLine("can't exit the migong ");
}

OutPut();

}

private bool IsArrived()
{
return !(migong[x2, y2] == -1);
}

private void MarkTheWay(int column,int row)  
{
int current = migong[column, row];
int next = current + 1;
if (CanGo(column+1, row,current))
{
migong[column + 1, row] = next;
MarkTheWay(column + 1, row);
}
if (CanGo(column-1, row,current))
{
migong[column - 1, row] = next;
MarkTheWay(column - 1, row);
}
if (CanGo(column, row+1,current))
{
migong[column, row + 1] = next;
MarkTheWay(column, row + 1);
}
if (CanGo(column, row-1,current))
{
migong[column, row - 1] = next;
MarkTheWay(column, row - 1);
}
}
private bool CanGo(int column, int row,int lastNumber)
{
if (column < 0 || column > COUNT - 1 || row < 0 || row > COUNT - 1)
return false;
int current = migong[column, row];
if (current == 0)
return false;
if (current != -1 && current < lastNumber)
return false;
HaveArrived(column, row,lastNumber);  //到达出口路径数+1,统计最短的情况
return true;
}
private void HaveArrived(int column, int row,int lastNumber)
{
if (column == x2 && row == y2)
{
WayCount++;
if (ShortestWay < 0)
{
ShortestWay = lastNumber;
}
else
{
ShortestWay = lastNumber < ShortestWay ? lastNumber : ShortestWay;
}
}
return;
}

public void OutPut()
{
for (int column = 0; column < COUNT; column++)
{
for (int row = 0; row < COUNT; row++)
{
Console.Write(migong[column, row].ToString().PadRight(3));
}
Console.Write('\n');
}
}

private bool CanBack(int column, int row, int lastNumber)  
{
if (column < 0 || column > COUNT - 1 || row < 0 || row > COUNT - 1)
return false;
int current = migong[column, row];
if (current != lastNumber - 1)
return false;

return true;
}

private string FormatPoint(int column, int row)
{
return "(" + column + "," + row + ")";
}

private void FindShortWay()
{
int column = x2;
int row = y2;
int current = migong[column, row];
while ((current = migong[column, row])!=1)
{
Console.Write(FormatPoint(column, row)+" -> ");
if (CanBack(column + 1, row,current))
{
column+=1;
continue;
}
if (CanBack(column - 1, row, current))
{
column -= 1;
continue;
}
if (CanBack(column, row + 1, current))
{
row += 1;
continue;
}
if (CanBack(column, row - 1, current))
{
row -= 1;
continue;
}
}
Console.Write(FormatPoint(column, row));
Console.WriteLine();
}

}
}

转载于:https://www.cnblogs.com/hongxucai/archive/2011/12/12/2284333.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里给出一种基于深度优先搜索的解法,可以求出所有路径数量和最路径。 首先,我们需要定义迷宫的结构体,包括迷宫大小、起点、终点以及迷宫本身。代码如下: ```c #define MAX_SIZE 100 struct maze { int n, m; // 迷宫大小 int sx, sy; // 起点坐标 int ex, ey; // 终点坐标 int maze[MAX_SIZE][MAX_SIZE]; // 迷宫本身 }; ``` 接下来,我们需要实现深度优先搜索算法,用于求解路径数量和最路径。具体实现如下: ```c struct path_node { int x, y; // 该点坐标 int prev; // 该点的上一个点在路径中的下标 }; int dfs(struct maze *mz, int x, int y, int prev, int *min_dis, struct path_node path[], int *path_cnt) { // 如果到达终点,更新最路径 if (x == mz->ex && y == mz->ey) { int dis = 0; path[*path_cnt].x = x; path[*path_cnt].y = y; path[*path_cnt].prev = prev; (*path_cnt)++; while (prev != -1) { // 从终点往回走,更新路径 int nx = path[prev].x, ny = path[prev].y; prev = path[prev].prev; dis++; if (nx == mz->sx && ny == mz->sy) break; } if (*min_dis == -1 || dis < *min_dis) *min_dis = dis; return 1; // 返回 1 表示找到了一条路径 } // 如果该点不可通,返回 0 if (mz->maze[x][y] == 1) return 0; // 标记该点已经走过 mz->maze[x][y] = 1; path[*path_cnt].x = x; path[*path_cnt].y = y; path[*path_cnt].prev = prev; (*path_cnt)++; // 沿四个方向搜索 int dx[4] = {0, -1, 0, 1}, dy[4] = {-1, 0, 1, 0}; int found = 0; for (int i = 0; i < 4; i++) { int nx = x + dx[i], ny = y + dy[i]; if (nx >= 0 && nx < mz->n && ny >= 0 && ny < mz->m) { found += dfs(mz, nx, ny, *path_cnt - 1, min_dis, path, path_cnt); } } // 取消标记该点 mz->maze[x][y] = 0; (*path_cnt)--; return found; } ``` 最后,我们需要在主函数中读入迷宫数据,调用深度优先搜索算法求解,输出结果。具体代码如下: ```c int main() { struct maze mz; printf("输入迷宫大小(n m):"); scanf("%d%d", &mz.n, &mz.m); printf("输入迷宫(0 表示可以通行,1 表示不可通行):\n"); for (int i = 0; i < mz.n; i++) { for (int j = 0; j < mz.m; j++) { scanf("%d", &mz.maze[i][j]); } } printf("输入起点坐标(x y):"); scanf("%d%d", &mz.sx, &mz.sy); printf("输入终点坐标(x y):"); scanf("%d%d", &mz.ex, &mz.ey); int min_dis = -1; struct path_node path[MAX_SIZE * MAX_SIZE]; int path_cnt = 0; int found = dfs(&mz, mz.sx, mz.sy, -1, &min_dis, path, &path_cnt); if (found) { printf("路径数量:%d\n", found); printf("最路径长度:%d\n", min_dis); printf("最路径为:"); int cur = path_cnt - 1; while (cur >= 0) { printf("(%d,%d)", path[cur].x, path[cur].y); cur = path[cur].prev; } printf("\n"); } else { printf("找不到路径!\n"); } return 0; } ``` 完整代码如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值