zoukankan      html  css  js  c++  java
  • 红与黑[DFS]

    红与黑[DFS]

    题目描述

    有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。

    你站在其中一块黑色的瓷砖上,只能向相邻(上下左右四个方向)的黑色瓷砖移动。

    请写一个程序,计算你总共能够到达多少块黑色的瓷砖。

    输入格式

    输入包括多个数据集合。

    每个数据集合的第一行是两个整数 WW 和 HH,分别表示 xx 方向和 yy 方向瓷砖的数量。

    在接下来的 HH 行中,每行包括 WW 个字符。每个字符表示一块瓷砖的颜色,规则如下

    1)‘.’:黑色的瓷砖;
    2)‘#’:红色的瓷砖;
    3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。

    当在一行中读入的是两个零时,表示输入结束。

    输出格式

    对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。

    数据范围

    1≤W,H≤201≤W,H≤20


    6 9 
    ....#. 
    .....# 
    ...... 
    ...... 
    ...... 
    ...... 
    ...... 
    #@...# 
    .#..#. 
    0 0
    

    输出样例:

    45
    

    思路分析

    • 应题目要求,我们只能找到,‘@’与其他黑砖相连的区域,并记录黑砖的个数就是答案。

    • 首先分析,每次坐标变换的偏移量, 以下图为例分析。

      • 在这里插入图片描述

      • 由题可知,每次移动只能向上下左右移动一个瓷砖,所以和以得到,x轴和y轴的偏移量,**注意:**这里说的 x轴 指的是——以左上交为原点,向下为 x正半轴,向右为 y轴负半轴。

      • 得到 x和y轴的偏移量,可以存在数组中(方便计算相邻的点)。

    • 算法

      • 本题用到了深度优先搜索,简称DFS。
        • 深度优先搜索就是,先选中一条路径一直走,走到底,然后没路了,返回上一个交叉口(选择的地方),走其他的路径,也就是尝试求出每种结果找出正确答案。
        • 本题,就是一个简单的dfs求连通区域。首先,由题可知每个瓷砖只能计算一次,所以需要用一个 标记 数组, 来记录当前瓷砖是否已经计算过了。最后得到的就是答案。

    AC代码

    java代码

    import java.util.Scanner;
    
    public class Main {
        public static int[] dx = {-1, 1, 0, 0}; // x轴偏移量
        public static int[] dy = {0, 0, -1, 1}; // y轴偏移量
        public static int ans = 0;
        public static int n = 0;
        public static int m = 0;
        public static void main(String[] args) {
            Scanner cin = new Scanner(System.in);
    
                while (true) {
                    m = cin.nextInt();
                    n = cin.nextInt();
                    if (n == 0 && m == 0) break;
                    ans = 0;
                    cin.nextLine();
                    boolean[][] v = new boolean[n][m]; // 定义标记数组
                    StringBuilder[] mp = new StringBuilder[n]; // 存储输入的地图
    
                    int x = 0, y = 0, f = -1;
                    for (int i = 0; i < n; ++ i) {
                        mp[i] = new StringBuilder(cin.nextLine());
                        f = mp[i].indexOf("@"); 
                        if (f != -1) { // 找到开始位置
                            x = i;
                            y = f;
                        }
                    }
                    dfs(x, y, v, mp); // 进行深度优先搜索
    
                    System.out.println(ans);
                }
        }
        public static void dfs(int x, int y, boolean[][] v, StringBuilder[] mp) {
            v[x][y] = true; // 标记当前,x,y坐标的函数已经计算过了
            ans ++;// 加入答案
            for (int i = 0; i < 4; ++ i) { // 判断当前黑瓷砖周围的其他砖
                int nx = x + dx[i];
                int ny = y + dy[i];
                // 判断 坐标是否超过数组大小,判断当前瓷砖是否记录过,判断当前周边瓷砖是否为黑瓷砖
                if (nx < 0 || nx >= n || ny < 0 || ny >= m || v[nx][ny] == true || mp[nx].charAt(ny) == '#') continue;
                dfs(nx, ny, v, mp);// 是黑瓷砖,且没越界,没计算过,则继续以当前瓷砖为点,选中它周围的瓷砖,进行搜索
    
            }
        }
    }
    

    C++代码

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 25;
    int dx[] = {0, 0, -1, 1};
    int dy[] = {1, -1, 0, 0};
    int n, m, ans = 0;
    bool v[N][N];
    char mp[N][N];
    
    void dfs(int x, int y) {
        v[x][y] = true;
        ans ++;
        for (int i = 0; i < 4; ++ i) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m || v[nx][ny] == true || mp[nx][ny] == '#') continue;
            dfs(nx, ny);
        }
    }
    
    int main () {
        
        while (true) {
            cin >> m >> n;
            if (n == 0 && m == 0) break;
            ans = 0;
            memset(v, 0, sizeof v);
            int x, y;
            for (int i = 0; i < n; ++ i) {
                for (int j = 0; j < m; ++ j) {
                    cin >> mp[i][j];
                    if (mp[i][j] == '@') x = i, y = j;
                }
            }
            
            dfs(x, y);
            cout << ans << endl;
        }
        
        return 0;
    }
    
    
    
    追求吾之所爱
  • 相关阅读:
    vue2 生命周期
    javascript http库axios
    vue2自定义事件之$emit
    php配置rewrite模块
    php 正则匹配中文(转)
    php常用自定义函数
    Mysql----MySQL的mysql_insert_id和LAST_INSERT_ID(转)
    Mysql----mysql启动服务时提示"服务名无效"
    div+css布局
    php常见问题以及解决方法
  • 原文地址:https://www.cnblogs.com/rstz/p/14390970.html
Copyright © 2011-2022 走看看