419.甲板上的战舰(dfs, 沉没战舰)

给定一个二维的甲板, 请计算其中有多少艘战舰。 战舰用 'X'表示,空位用 '.'表示。 你需要遵守以下规则:

给你一个有效的甲板,仅由战舰或者空位组成。
战舰只能水平或者垂直放置。换句话说,战舰只能由 1xN (1 行, N 列)组成,或者 Nx1 (N 行, 1 列)组成,其中N可以是任意大小。
两艘战舰之间至少有一个水平或垂直的空位分隔 - 即没有相邻的战舰。
示例 :

X..X
...X
...X
在上面的甲板中有2艘战舰。

无效样例 :

...X
XXXX
...X
你不会收到这样的无效甲板 - 因为战舰之间至少会有一个空位将它们分开。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/battleships-in-a-board
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思考

我们打算遍历这个二维数组,然后遇到X就开始就记个数。但这样有个问题,比如又变那一列,3个X其实是一艘战舰,如果遇上了都数一遍,就会重复数。

所以数过的战舰需要“沉没”掉,把"X"变为"."

怎样探索一艘战舰包含哪些X呢,注意到战舰只能横向或者纵向成一竖。

首先检查点有没有越界,是不是在甲板上(X),不是的话直接返回。

符合条件的话:

我们就先将这个点变成".",然后对这个点进行深度优先搜索,向四周探索。

探索到下一个X点,就继续dfs.

下图注释

遍历二维数组,到(0,0),发现是X。船数+1

就dfs(0,0)

    将board[0][0] = "."

    然后dfs四周的点。发现左边和上边的点越界了,右边和下边的点不是X,所以直接返回。

 

然后遍历(0,1),  (0,2), 都不是X,没事

 

到(0,3)了,它是X,船数+1. dfs(0,3)

 首先将board[0][3]置为"."

dfs四周的点。

左边不是X,上和右边越界了,直接返回。

dfs(1,3)

没有越界,且是X

board[1][3] 置为"."

dfs四周

这个时候,左边上边都不是X,右边越界,直接返回。

 

dfs(2,3)

没有越界,且是X

board[2][3] 置为"."

左边,上边都不是X,下边和右边越界,直接返回。

 

回到主遍历线,遍历(1,0), (1,1)......     (2,3),都没找到X,所以返回战舰数2


代码实现 

/**
 * @param {character[][]} board
 * @return {number}
 */
var countBattleships = function(board) {
    let result = 0
    for (let row = 0; row < board.length; row++) {
        for (let col = 0; col < board[0].length; col++) {
            if (board[row][col] === 'X') {
                result++
                dfs(row, col)
            }
        }
    }

    function dfs(row, col) {
        //当前点条件判断
        //越界或不在甲板上直接返回
        if (row < 0 || row >= board.length || col < 0 || col >= board[0].length ||
        board[row][col] !== 'X') {
            return
        }

        //沉默当前点
        board[row][col] = '.'
        //对四个方向进行深度优先搜索
        dfs(row-1, col)
        dfs(row+1, col)
        dfs(row, col-1)
        dfs(row, col+1)
    }

    return result

}; 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!要在C++中使用OpenCV进行装甲板图像识别,您可以按照以下步骤进行操作: 1. 安装OpenCV:首先,您需要在您的计算机上安装OpenCV库。您可以从OpenCV官方网站下载适合您操作系统的版本,并按照安装说明进行安装。 2. 读取图像:使用OpenCV的`imread`函数读取您的装甲板图像。例如: ```cpp cv::Mat image = cv::imread("path_to_image.jpg"); if (image.empty()) { // 处理图像读取失败的情况 } ``` 3. 图像预处理:根据您的需求对图像进行预处理,以便更好地进行装甲板识别。这可能包括调整图像大小、改变颜色空间或应用滤波器等操作。 4. 目标检测:使用OpenCV中的目标检测算法来检测装甲板。这可能涉及使用特征提取方法(如Haar特征或HOG特征)或深度学习方法(如卷积神经网络)。 5. 轮廓提取:如果您已经检测到了装甲板的候选区域,您可以使用OpenCV的`findContours`函数来提取这些区域的轮廓。 ```cpp std::vector<std::vector<cv::Point>> contours; cv::findContours(image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); ``` 6. 轮廓过滤和匹配:根据装甲板的形状和特征,您可以使用一些过滤器(如面积、周长等)来筛选轮廓,并使用匹配算法来确定最终的装甲板。 7. 结果显示:最后,您可以使用OpenCV的函数在图像上绘制装甲板的边界框或其他可视化结果。 这只是一个简单的指导,具体的实现可能因您的需求而有所不同。希望对您有所帮助!如有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值