迷宫老鼠游戏

迷宫老鼠游戏
【题目】

       以一个m×n的长方阵表示迷宫,01分别表示迷宫中的通路和障碍。请设计一个算法,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论;如果有通道,请输出最短路径的通道。例如:

【分析】

       首先用一个二维数组存储该迷宫,从起点位置(0,0开始分支遍历,将起点位置作为当前扩展结点,扩展出所有出未被访问过的有效结点,即该位置不是路障,而是通路,将所有这些有效结点依次加入到队列中,同时记录该有效结点的前驱结点,可用二维数组进行记录,此时从起始位置到达该有效结点的位置的路长为到达前驱结点的路长加1。再从队列中取出一个结点作为当前的扩展结点,重复上述操作,直到队列为空或者达到终点位置。

       当没有通路时,输出“No”;

       当存在通路时,输出“Yes”,并输出最短路径,同时输出最短路径的路长。

【伪代码】

void sovle(int n, int m, int[][] g) {
	int[] dx 定义x方向上的移动方式;
	int[] dy 定义y方向上的移动方式;

	定义活结点队列 q;
	定义用于存储位置是否被访问的二维数组;

	将起始位置加入到队列q中;
	标记起始位置已被访问;
	
	定义用于记录前驱结点的二维数组;
	
	while(队列q不为空) {
		从队列q中取出队头作为当前的扩展结点;
		
		if(该扩展结点为终点位置)
			break;

		for(int i = 0; i < 4; i++) {
			通过移动,得出新的子结点;
			if(该子结点没有越界,并且该结点未被访问,为通路) {
				将该子结点加入到队列中;
				标记该子结点位置已被访问;
				记录该子结点的前驱结点为当前扩展结点;
				记录起始位置到达该结点的路长 = 前驱结点的路长 + 1;
			}
		}
	}

	if(终点位置的结点没有被访问过)
		输出No;
	else {
		创建一个栈,并将终点结点加入栈中;
		while(true) {
			找到当前结点的前驱结点,加入到栈中;
			if(前驱结点的位置为起始位置)
				break;
			修改当前结点为前驱结点;
		}
		
		从栈中依次取出结点,输出结点位置,即为所求最短通道路径;
		输出最短路径长度;
	}
}
【程序】

用java语言编写程序,代码如下:

import java.io.BufferedInputStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class MazeGame {
	public static void main(String[] args) {
		Scanner input = new Scanner(new BufferedInputStream(System.in));
		int n = 0, m = 0;
		
		while(input.hasNext()) {
			n = input.nextInt();
			m = input.nextInt();

			if(n == 0 && m == 0)
				break;
			
			int[][] g = new int[n][m];
			
			for(int i = 0; i < n; i++)
				for(int j = 0; j < m; j++)
					g[i][j] = input.nextInt();
			
			solve(n, m, g);
		}
	}
	
	public static void solve(int n, int m, int[][] g) {
		int[] dx = {1, 0, -1, 0};
		int[] dy = {0, 1, 0, -1};
		
		Queue<Pos> q = new LinkedList<Pos>();
		boolean[][] isVisited = new boolean[n][m];
		
		Pos p0 = new Pos(0, 0);
		p0.dist = 0;
		isVisited[0][0] = true;
		
		q.add(p0);
		Pos[][] prev = new Pos[n][m];
		
		int x = 0, y = 0, tx = 0, ty = 0;
		Pos p = new Pos();
		while(!q.isEmpty()) {
			p = q.poll();
			x = p.x; y = p.y;
			if(x == n - 1 && y == m - 1) break;
			
			for(int i = 0; i < 4; i++) {
				tx = dx[i] + x; ty = dy[i] + y;
				if(tx >= 0 && ty >= 0 && tx < n && ty < m) {
					if(!isVisited[tx][ty] && g[tx][ty] == 0) {
						Pos p1 = new Pos(tx, ty);
						prev[tx][ty] = p;
						p1.dist = p.dist + 1;
						isVisited[tx][ty] = true;
						q.add(p1);
					}
				}
			}
		}
		
		if(!isVisited[n - 1][m - 1])
			System.out.println("No");
		else {
			System.out.println("Yes");
			
			Stack<Pos> sp = new Stack<Pos>();
			sp.add(p);
			int ex = n - 1, ey = m - 1;
			while(true) {
				Pos p2 = prev[ex][ey];
				sp.add(p2);
				if(p2.x == 0 && p2.y == 0)
					break;
				
				ex = p2.x;
				ey = p2.y;
			}

			Pos p3 = sp.pop();
			System.out.print("(" + p3.x + "," + p3.y + ")");
			int i = 2;
			while(!sp.isEmpty()) {
				p3 = sp.pop();
				if(i % 10 == 1) {
					System.out.print("\n(" + p3.x + "," + p3.y + ")");
				}
				else
					System.out.print(" (" + p3.x + "," + p3.y + ")");
				i++;
			}
			System.out.println("\n" + p.dist);
		}
	}
	
	static class Pos {
		int x, y;
		int dist;
		public Pos(int x, int y) {
			this.x = x;
			this.y = y;
		}
		public Pos() {
		}
	}
}
【结果】

       运行程序,输入10 10和迷宫的布局,输出结果:

【体会】

     分支限界法以广度优先或以最小耗费优先的方式搜索解空间。分支限界法的搜索策略是,在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。为了有效地选择下一扩展结点,加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
程序在VC++ 6下顺利编译通过。 一、 实验目的: (1) 熟练掌握链栈的基本操作及应用。 (2) 利用链表作为栈的存储结构,设计实现一个求解迷宫的非递归程序。 二、实验内容: 【问题描述】 以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对信任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。 【基本要求】 首先实现一个链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),……。 【测试数据】 迷宫的测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口。 1 2 3 4 5 6 7 8 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 以方阵形式输出迷宫及其通路。 输出: 请输入迷宫的长和宽:5 5 请输入迷宫内容: 0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 0 0 0 迷宫的路径为 括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向) (1,1,1,↓) (2,1,2,→) (2,2,1,↓) (3,2,1,↓) (4,2,2,→) (4,3,1,↓) (5,3,2,→) (5,4,2,→) (5,5,0,) 迷宫路径探索成功!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值