hdu 1728 逃离迷宫

/*
思路:
1)从起点开始搜索,直到找到终点。
--这个过程不允许回走,且转弯的次数不允许超过k;
--这是使用一个二维数组保存每一次走到该点的转弯次数,
--并同时判断该点是否已被访问;
--判断该点是否已被访问,可以通过前一节点的转弯次数
--加上这次移动的转弯次数来判断该点是否可行,也就是回走;
--回走的方向与原来的不同,
--那么搜索下一个是不会直接回走,
--只可能是绕弯后再一次回走,
--显然通过这种方式可以防止回走;
--所以swerve的初始化应该比k大,
--毕竟刚开始是没有转弯的。
2)找到答案后就因该直接回退,于是直接剪枝,
--也就是return,可以减掉所有的枝叶,
--方便直接返回,这里只要加个bool变量就搞定了。
*/
#include<stdio.h>

/*
使用深度优先搜索
注意:题目是从(1,1)开始,
---而程序是从(0,0)开始
m表示行数
n表示列数
x1,x2表示列
y1,y2表示行
map记录地图
swerver记录当前点已经转弯的次数,
---同时是用来判断
fourDir移动的四个方向,上下左右。
lifeAndDeath判断是否找到了出口,
也是方便最快回退。
*/
int m,n;
int k,sx1,sy1,ex2,ey2;
char map[100][100];
int swerve[100][100];
int fourDir[][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool lifeAndDeath;

int main(){
    void depthFirstSearch(int x,int y,int dir);
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&m,&n);
        for(int i=0;i<m;i++){
            scanf("%s",map[i]);
            //初始化转弯次数
            for(int j=0;j<n;j++){
                swerve[i][j]=11;
            }
        }
        scanf("%d%d%d%d%d",&k,&sx1,&sy1,&ex2,&ey2);
        /*
        题目下标与程序下标不同,x与y的的表示也不同
        深搜的起点因该是(y1,x1),
        方向是任意的
        */
        sy1--;
        sx1--;
        ey2--;
        ex2--;
        /*
        转弯次数为0,
        起始lifeAndDeath表示没有找到出口,
        从起点开始搜索。
        */
        swerve[sy1][sx1]=0;
        lifeAndDeath=false;
        depthFirstSearch(sy1,sx1,-1);
        if(lifeAndDeath){
            printf("yes\n");
        }else{
            printf("no\n");
        }
    }
    return 0;
}

/*
x表示行
y表示列
dir表示移动的方向,-1任意方向,0上,1下,2左,3右,
---这个是跟fourDir数组相对应的
*/
void depthFirstSearch(int x,int y,int dir){
    /*
    这里最好写鸿沟
    */
    // 转弯次数不合条件
    if(swerve[x][y]>k){
        return;
    }
    // 快速回退
    if(lifeAndDeath){
        return;
    }
    // 找到出口
    if(x==ey2&&y==ex2){
        lifeAndDeath=true;
        return;
    }
    for(int i=0;i<4;i++){
        /*
        四个方向选择任意一个方向,
        当然我们可以使用if加continue语句,
        来实现剪枝,其实就是不搜索而已。
        这个剪枝是把题图化,然后把图化解成树,
        这是只要把图中不相干的枝去掉(剪枝),
        就可以变成树,通过不同的方式剪枝到不同的树,
        就可以得到不同的树,也就是答案。
        */
        int a=x+fourDir[i][0];
        int b=y+fourDir[i][1];
        /*
        思路:
        从该点出发,选择i方向,
        判断该方向是否合法,
        不合法就剪枝。
        */
        // 碰壁
        if(a<0||b<0||a>=m||b>=n){
            continue;
        }
        // 遇到障碍
        if(map[a][b]=='*'){
            continue;
        }
        // 重复访问
        if(swerve[a][b]<=swerve[x][y]){
            continue;
        }
        // 直线移动,移动次数不变
        swerve[a][b]=swerve[x][y];
        // 判断方向
        if(dir!=-1&&i!=dir){
            // 转弯,值加1
            swerve[a][b]++;
        }
        // 可行方向
        depthFirstSearch(a,b,i);
    }
}

搜索题:慢慢来。


java代码:

import java.util.Scanner;

public class Main {
	/*
	 * 给定一个m × n (m行, n列)的迷宫
	 * 其中k表示gloria最多能转的弯数
	 * 其中x1,x2对应列,y1, y2对应行
	 * map地图
	 * dir表示上下左右四个方向
	 */
	static int m, n, success;
	static int k, x1, y1, x2, y2;
	static char[][] map = new char[100][100];
	static int[][] swerve = new int[100][100];
	static int dir[][] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while (t-- > 0) {
			m = sc.nextInt();
			n = sc.nextInt();
			for (int i = 0; i < m; i++) {
				String str = sc.next();
				for (int j = 0; j < n; j++) {
					map[i][j] = str.charAt(j);
					swerve[i][j] = 11;
				}
			}
			k = sc.nextInt();
			x1 = sc.nextInt() - 1;
			y1 = sc.nextInt() - 1;
			x2 = sc.nextInt() - 1;
			y2 = sc.nextInt() - 1;
			success = 0;
			swerve[y1][x1]=0;
			depthFirstSearch(y1, x1, -1);
			if (success == 1) {
				System.out.println("yes");
			} else {
				System.out.println("no");
			}
		}
	}

	/*
	 * x-x坐标
	 * y-y坐标
	 * d-direction方向0,1,2,3上下左右,
	 * -1表示起始方向。
	 * s-swerve转弯数,用来记录当前结点剩余转弯的次数。
	 */
	public static void depthFirstSearch(int x, int y, int d) {
		// 转弯超数
		if (swerve[x][y] > k) {
			return;
		}
		// 找到答案
		if (x == y2 && y == x2) {
			success = 1;
			return;
		}
		/*
		 * 2)以当前点为搜索源,进行搜索
		 */
		for (int i = 0; i < dir.length; i++) {
			int a = x + dir[i][0];
			int b = y + dir[i][1];
			// 越界
			if (a < 0 || b < 0 || a >= m || b >= n) {
				continue;
			}
			// 遇到障碍物
			if (map[a][b] == '*') {
				continue;
			}
			// 重复访问
			if (swerve[a][b] <= swerve[x][y]) {
				continue;
			}
			// 直线行走
			swerve[a][b] = swerve[x][y];
			if (d != -1 && d != i) {
				// 转弯
				swerve[a][b]++;
			}
			// 可行方向
			depthFirstSearch(a, b, i);
			if (success == 1) {
				return;
			}
		}
	}

}






逃离迷宫

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19352    Accepted Submission(s): 4694


Problem Description
  给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
 

Input
  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x 1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能转的弯数,(x 1, y 1), (x 2, y 2)表示两个位置,其中x 1,x 2对应列,y 1, y 2对应行。
 

Output
  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
 
 
Sample Input
  
  
2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3
 

Sample Output
  
  
no yes
 

Source

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值