东北农业大学2018春季赛

D-wyh的迷宫

链接:https://www.nowcoder.com/acm/contest/93/D
来源:牛客网

给你一个n*m的迷宫,这个迷宫中有以下几个标识:

s代表起点

t代表终点

x代表障碍物

.代表空地

现在你们涵哥想知道能不能从起点走到终点不碰到障碍物(只能上下左右进行移动,并且不能移动到已经移动过的点)。

输入描述:

输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,对于每一组测试数据,第一行输入2个数n和m(1<=n,m<=500)
接下来n行,每行m个字符代表这个迷宫,每个字符都是上面4个中的一种
数据保证只有一个起点和一个终点

输出描述:

对于每一组测试数据,如果可以的话输出YES,不可以的话输出NO

解析

首先这题很差劲啊,对Java如此的不友好,丢雷楼母的出题人。C++做这个题dfs妥妥的过了,最重要的是都不用剪纸都能过,mmmp。 而对于Java来说,会栈溢出,剪枝也不行,必须用bfs才能过。
这是一道经典的遍历的题,dfs或bfs都可过,最重要的是记住,迷宫类的题在回溯时走过的点不用恢复为未走过,因为从这个点往各个方向走,我们都已考察过了,如果回溯时恢复成未考察的状态,则下次走到这个点又要重复的判断,势必会超时

代码
Java

dfs栈溢出了(代码注释部分,感兴趣的可以尝试如何A掉)。bfs过了。

    package com.special.DongBeiLinYeSpring;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

/**
 * Create by Special on 2018/4/10 20:10
 */
public class ProD {
    static int startX, startY, endX, endY, n, m;
    static boolean[][] vis;
    static char[][] maps;
    static boolean flag;
    static int[][] steps = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

    static boolean isValid(int x, int y){
        return !(x < 0 || x >= n || y < 0 || y >= m);
    }

//    static void dfs(int x, int y){
        if(x == endX && y == endY){
            flag = true;
            return;
        }
        int tempX, tempY;
        for(int i = 0; i < 4; i++){
            tempX = x + steps[i][0];
            tempY = y + steps[i][1];
            if(isValid(tempX, tempY) && !vis[tempX][tempY] && maps[tempX][tempY] != 'x'){
                vis[tempX][tempY] = true;
                dfs(tempX, tempY);
                if(flag){
                    return;
                }
            }
        }
//        if(isValid(x, y) && !vis[x][y] && maps[x][y] != 'x'){
//            if(x == )
//            vis[x][y] = true;
//            dfs(x - 1, y);
//            dfs(x + 1, y);
//            dfs(x, y - 1);
//            dfs(x , y + 1);
//        }
//    }
    static class Node{
        int x;
        int y;

        public Node(int x, int y){
            this.x = x;
            this.y = y;
        }
    }

    static void bfs(int x, int y){
        Queue<Node> queue = new LinkedList<>();
        queue.add(new Node(x, y));
        vis[x][y] = true;
        while(!queue.isEmpty()){
            Node node = queue.poll();
            if(node.x == endX && node.y == endY){
                flag = true;
                break;
            }
            int tempX, tempY;
            for(int i = 0; i < 4; i++){
                tempX = node.x + steps[i][0];
                tempY = node.y + steps[i][1];
                if(isValid(tempX, tempY) && !vis[tempX][tempY] && maps[tempX][tempY] != 'x'){
                    vis[tempX][tempY] = true;
                    queue.offer(new Node(tempX, tempY));
                }
            }
        }
    }
    public static void main(String[] args){
        FastScanner input = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        int t = input.nextInt();
        while(t-- > 0) {
            n = input.nextInt();
            m = input.nextInt();
            maps = new char[n][m];
            vis = new boolean[n][m];
            flag = false;
            for(int i = 0; i < n; i++){
                String str = input.next();
                maps[i] = str.toCharArray();
            }
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    if(maps[i][j] == 's'){
                        startX = i;
                        startY = j;
                    }else if(maps[i][j] == 't'){
                        endX = i;
                        endY = j;
                    }
                }
            }
            bfs(startX, startY);
            out.println(flag ? "YES" : "NO");
        }
        out.close();
    }
}
C++

同样的代码,C++可过。。无奈

#include <bits/stdc++.h>

using namespace std;
const int maxn = 500 + 5;
char maps[maxn][maxn];
bool vis[maxn][maxn];
int n, m, sX, sY, eX, eY;
int steps[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool flag;

bool isValid(int x, int y){
    return !(x < 0 || x >= n || y < 0 || y >= m);
}
void dfs(int x, int y){
    if(x == eX && y == eY){
        flag = true;
        return;
    }
    int tempX = 0, tempY = 0;
    for(int i = 0; i < 4; i++){
        tempX = x + steps[i][0];
        tempY = y + steps[i][1];
        if(isValid(tempX, tempY) && !vis[tempX][tempY] && maps[tempX][tempY] != 'x'){
            vis[tempX][tempY] = true;
            dfs(tempX, tempY);
            if(flag){
                return;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d %d", &n, &m);
        memset(vis, false, sizeof(vis));
        flag = false;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                scanf("%c", &maps[i][j]);
                if(maps[i][j] == 's'){
                    sX = i;
                    sY = j;
                }else if(maps[i][j] == 't'){
                    eX = i;
                    eY = j;
                }
            }
        }
        dfs(sX, sY);
        if(flag){
            printf("YES");
        }else{
            printf("NO");
        }
    }
}
优化

我们可以利用x来表示已走过的点,所以我们把走过的点赋值为x,则不用额外的vis了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值