当前位置: 首页 > article >正文

开心消消乐

题目描述

给定一个N行M列的二维矩阵,矩阵中每个位置的数字取值为0或1。矩阵示例如:
1100
0001
0011
1111
现需要将矩阵中所有的1进行反转为0,规则如下:
1) 当点击一个1时,该1便被反转为0,同时相邻的上、下、左、右,以及左上、左下、右上、右下8 个方向的1(如果存在1)均会自动反转为0;
2)进一步地,一个位置上的1被反转为0时,与其相邻的8个方向的1(如果存在1)均会自动反转为0;

按照上述规则示例中的矩阵只最少需要点击2次后,所有值均为0。请问,给定一个矩阵,最少需要点击几次后,所有数字均为0?

输入描述

第一行输入两个数字N,M,分别表示二维矩阵的行数、列数,并用空格隔开

之后输入N行,每行M个数字,并用空格隔开

输出描述

最少需要点击几次后,矩阵中所有数字均为0

用例

输入
4 4
1 1 0 0
0 0 0 1
0 0 1 1
1 1 1 1

输出 2
说明 无

如下图所示:
在这里插入图片描述
即,含有1的块数总共2块,需要点击2次才能把所有1变为0。

解题思路

本题可以用并查集求解。步骤如下:

  1. 根据输入矩阵的行数和列数,初始化并查集。实现并查集中初始化、查找根节点、添加节点关系等方法;
  2. 遍历输入矩阵;
  3. 如果当前位置数值为0,该位置不是1,1的总块数需要减1,即并查集的size减1;
  4. 如果当前位置为1,向上下左右四个方向搜索临近点。如果搜索位置不越界,且数值为1,则添加点关系;
  5. 遍历结束,得到并查集的Size,即1的总块数;
  6. 释放并查集对象,返回总块数。

代码实现

用文章开头算例为输入条件,根据上面的思路编写代码。

class UnionFindCol//并查集类
{
public:
	int Size;
	vector<int> ParentList;
	UnionFindCol(int size)//初始化并查集
	{
		Size = size;
		for (int i = 0; i < size; ++i)
		{
			ParentList.push_back(i);
		}
	}

	int GetRoot(int index)//获取根节点
	{
		if (ParentList[index] == index) return index;
		ParentList[index] = GetRoot(ParentList[index]);//路径压缩
		return ParentList[index];
	}

	void Join(int index1,int index2)//添加节点间关系
	{
		int parent1 = GetRoot(index1);//点1根节点
		int parent2 = GetRoot(index2);//点2根节点
		if (parent1 == parent2) return;//根节点一致,不处理
		ParentList[parent2] = parent1;//根节点不一致,节点2根节点的根节点重置
		Size--;//块数-1
	}
};

int GetCount(std::vector<std::vector<int>> matrix)
{
	int rowCount = matrix.size();
	int colCount = matrix[0].size();
	vector<int> dirs = { 0,1,0,-1,0 };
	UnionFindCol* ufc = new UnionFindCol(rowCount * colCount);
	for (int i = 0; i < rowCount; ++i)
	{
		for (int j = 0; j < colCount; ++j)
		{
			if (matrix[i][j] == 0) { ufc->Size--; continue; }
			int index = i * colCount + j;
			for (int k = 0; k < 4; ++k)
			{
				int nextRow = i + dirs[k];
				int nextCol=j+ dirs[k+1];
				if (nextRow >= 0 && nextRow < rowCount && nextCol >= 0 && nextCol < colCount && matrix[nextRow][nextCol] != 0)
				{
					int nextIndex= nextRow * colCount + nextCol;
					ufc->Join(index, nextIndex);
				}
			}
		}
	}
	int result = ufc->Size;;
	delete ufc;
	return result;
}

int main()
{
	std::vector<std::vector<int>> matrix =
	{
		{1,1,0,0},
		{0,0,0,1},
		{0,0,1,1},
		{1,1,1,1},
	};
	int result = GetCount(matrix);
	std::cout << result;
}

运行结果

算例的示意图如下:
在这里插入图片描述
由图可知,含1的数字总块数是2;

代码运行结果如下:
在这里插入图片描述
对比可知,代码运行结果符合预期。


http://www.kler.cn/a/571510.html

相关文章:

  • 准确--k8s离线导入镜像
  • 【商城实战(2)】商城架构设计:从底层逻辑到技术实现
  • Docker 深度解析:适合零基础用户的详解
  • 【机器学习】应用梯度下降法训练线性回归算法模型
  • vue2(笔记)5.0 vuex
  • 【全栈开发】从0开始搭建一个图书管理系统【二】前端搭建
  • ‘QDesktopWidget::availableGeometry‘: Use QGuiApplication::screens()
  • Vue3项目如何使用TailWind CSS保姆级教程
  • Linux基础开发工具—软件安装器yum。人类世界软件安装器一夜消失,而我却会用yum
  • 笔记:代码随想录算法训练营day36:LeetCode1049. 最后一块石头的重量 II、494. 目标和、474.一和零
  • Python 入门总结与实践:构建你的第一个程序
  • 深度集成DeepSeek,智问BI@GPT引领商业智能“深度思考“革命
  • 复试准备日常
  • tidb vs starrocks 资源估算pk
  • 【Redis】常用命令汇总
  • 拆一拆吉利普及高阶智驾的盲盒
  • Vue 3 新特性:对比 Vue 2 的重大升级
  • 坐标变换介绍与机器人九点标定的原理
  • 解交互题时如何规划交互流程
  • 源码编译安装httpd