【数学】【网格】【状态压缩】782 变为棋盘

news2024/9/23 3:19:00

作者推荐

视频算法专题

本文涉及知识点

数学 网格 状态压缩

LeetCode:782 变为棋盘

一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。
返回 将这个矩阵变为 “棋盘” 所需的最小移动次数 。如果不存在可行的变换,输出 -1。
“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。
示例 1:
在这里插入图片描述

在这里插入图片描述

输入: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
输出: 2
解释:一种可行的变换方式如下,从左到右:
第一次移动交换了第一列和第二列。
第二次移动交换了第二行和第三行。
示例 2:
在这里插入图片描述

输入: board = [[0, 1], [1, 0]]
输出: 0
解释: 注意左上角的格值为0时也是合法的棋盘,也是合法的棋盘.
示例 3:
在这里插入图片描述

输入: board = [[1, 0], [1, 0]]
输出: -1
解释: 任意的变换都不能使这个输入变为合法的棋盘。

提示:
n == board.length
n == board[i].length
2 <= n <= 30
board[i][j] 将只包含 0或 1

数学

分两步:

一,调整列。
col0记录列首元素为0的列下标,col1记录列首元素为1的列下标。 col0(col1)中的各列必须完全相同,col0和col1相同行的元素必须不同。
列调整后,假定第一列是:{i1,i2,i3,i4…} 则第二列是 i 1 ⊕ 1 , i 2 ⊕ 1 , i 3 ⊕ 1 , i 4 ⊕ 1 {i1\oplus 1,i2\oplus 1,i3\oplus 1,i4\oplus 1} i11,i21,i31,i41 ,第三列,第五列 ⋯ \cdots 和第一列相同,第四列,第六列 ⋯ \cdots 和第二列相同。
c0的数量l0 = n/2,c1的数量l1 = n - l0。

列号从0开始,记录c0在各列在偶数列的数量d0,记录c1在各列在偶数列的数量d1。
如果n是奇数。
{ 调整列次数为 d 0 , c 0 为调整后首列 l 0 = l 1 + 1 调整列次数为 d 1 , c 1 为调整后首列 l 1 = l 0 + 1 非法 o t h e r \begin{cases} 调整列次数为d0,c0为调整后首列 & l0 = l1+1 \\ 调整列次数为d1,c1为调整后首列 & l1 = l0+1 \\ 非法 & other\\ \end{cases} 调整列次数为d0,c0为调整后首列调整列次数为d1,c1为调整后首列非法l0=l1+1l1=l0+1other
如果n是偶数,调整的次数 = min(d0,d1),c0和c1为首列,不影响后续结果。

二,调整行。
各列调整后,各行一定是{0,1,0,1 ⋯ \cdots } 或 { 1,0,1,1 ⋯ \cdots },且数量相等。
调整后首列首元素的出现次数f0 ,必须等于 n - n/2。
行数从0开始。e0 为首(第0个)元素不在偶数行的数量,e1为第1个元素不在偶数行的数量。
如果n是偶数,调整行的次数:min(n/2-e0,m/2-e1)
如果n是奇数,调整行的次数:f0 - e0。

代码

125行代码,出错三次后,才搞定。强烈不推荐,细节太多。

核心代码

class Solution {
public:
	int movesToChessboard(vector<vector<int>>& board) {
		const int n = board.size();
		vector<int> col0, col1;
		for (int c = 0; c < n; c++)
		{
			if (board[0][c])
			{
				col1.emplace_back(c);
			}
			else
			{
				col0.emplace_back(c);
			}
		}
		for (int inx :col0)
		{
			if (!SameCol(board, col0.front(), inx))
			{
				return -1;
			}
		}
		for (int inx : col1)
		{
			if (!SameCol(board, col1.front(), inx))
			{
				return -1;
			}
		}
		if (abs((int)col0.size() - (int)col1.size()) > 1 )
		{
			return -1;
		}
		for (int r = 0; r < n; r++)
		{
			if (1 != board[r][col0.front()] + board[r][col1.front()])
			{
				return -1;
			}
		}
		
		int d0 = EvenCnt(col0);
		int d1 = EvenCnt(col1);
		int iRet = 0,e0=0,e1=0,f0=0;
		auto Tmp = [&](int col)
		{
			e0 = CntByValue(board, col, board[0][col], 2);
			e1 = CntByValue(board, col, board[0][col] ^ 1, 2);
			f0 = CntByValue(board, col, board[0][col], 1);
		};

		if (n & 1)
		{
			int iFirstCol = 0;
			if (col0.size() == col1.size() + 1)
			{
				iRet += (n/2+1-d0);
				iFirstCol = col0.front();				
			}
			else if (col1.size() == col0.size() + 1)
			{
				iRet += (n/2+1-d1);				
				iFirstCol = col1.front();
			}
			else
			{
				return -1;
			}	
			Tmp(iFirstCol);
			if (f0 == n / 2 + 1)
			{
				iRet += (n/2+1-e0);
			}
			else if (f0 == n / 2)
			{
				iRet += (n/2+1-e1);
			}
			else
			{
				return -1;
			}
		}
		else 
		{		
			Tmp(0);
			if (f0 != (n - n / 2))
			{
				return -1;
			}
			iRet += min(n / 2 - d0, n / 2 - d1);	
			iRet += min(n / 2 - e0, n/2 - e1);
		}
		return iRet;
	}
	int EvenCnt(const vector<int>& indexs)const
	{
		int iRet = 0;
		for (const auto& inx : indexs)
		{
			iRet += (0 == inx % 2);
		}
		return iRet;
	}
	bool SameCol(vector<vector<int>>& board, int col1, int col2)
	{
		for (int r = 0; r < board.size(); r++)
		{
			if (board[r][col1] != board[r][col2])
			{
				return false;
			}
		}
		return true;
	}
	int CntByValue(vector<vector<int>>& board, int col,int value ,int setp=2)
	{//指定值在偶数行的数量
		int iRet = 0;
		for (int r = 0; r < board.size(); r += setp)
		{
			iRet += (board[r][col] == value);
		}
		return iRet;
	}
};

测试用例


template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{
	vector<vector<int>> board;	
	{
		Solution sln;
		board = { {1,1,1,0},{1,1,1,0},{0,0,0,1},{0,0,0,1} };
		auto res = sln.movesToChessboard(board);
		Assert(-1, res);
	}
	{
		Solution sln;
		board = { {1,1,1,1},{1,1,1,1},{0,0,0,0},{0,0,0,0} };
		auto res = sln.movesToChessboard(board);
		Assert(-1, res);
	}
	{
		Solution sln;
		board = { {1, 1, 0}, { 0,0,1 }, { 0,0,1 }};
		auto res = sln.movesToChessboard(board);
		Assert(2, res);
	}
	{
		Solution sln;
		board = { {0,1,1,0},{0,1,1,0},{1,0,0,1},{1,0,0,1} };
		auto res = sln.movesToChessboard(board);
		Assert(2, res);
	}
	{
		Solution sln;
		board = { {0, 1}, {1, 0} };
		auto res = sln.movesToChessboard(board);
		Assert(0, res);
	}
	{
		Solution sln;
		board = { {1, 0}, {1, 0} };
		auto res = sln.movesToChessboard(board);
		Assert(-1, res);
	}
}

2023年4月版

用状态压缩,可以大幅降低难道。

class Solution {
public:
int movesToChessboard(vector<vector>& board) {
m_iN = board.size();
const int iRowMask = MaskRow(board[0]);
const int iColMask = MaskCol(board,0);
int iForRevrver = (1 << m_iN) - 1;
const int iRevRowMask = iRowMask ^ iForRevrver;
const int iRevColMask = iColMask ^ iForRevrver;
int iRowCnt = 0, iColCnt = 0;
for (int i = 0; i < m_iN; i++)
{
const int iCurRowMask = MaskRow(board[i]);
if ((iCurRowMask != iRowMask) && (iCurRowMask != iRevRowMask))
{
return -1;
}
iRowCnt += (iCurRowMask == iRowMask);
const int iCurColMask = MaskCol(board, i);
if ((iCurColMask != iColMask) && (iCurColMask != iRevColMask))
{
return -1;
}
iColCnt += (iCurColMask == iColMask);
}
int iMoveRow = GetMove(iRowMask, iRowCnt);
int iMoveCol = GetMove(iColMask, iColCnt);
if ((-1 == iMoveRow) || (-1 == iMoveCol))
{
return -1;
}
return iMoveRow + iMoveCol;
}
int GetMove(int iMask, int iCnt)
{
const int iOneBitNum = bitcount(iMask);
if (m_iN & 1)
{//奇数
if (1 != abs(m_iN - iCnt * 2))
{
return -1;
}
if (1 != abs(m_iN - iOneBitNum * 2))
{
return -1;
}
if (iOneBitNum == m_iN / 2)
{//奇数位0,偶数位为1
return m_iN / 2 - bitcount(iMask & 0xAAAAAAAA);
}
else
{
return m_iN / 2 + 1 - bitcount(iMask & 0x55555555);
}
}
else
{
if (iCnt != m_iN / 2)
{
return -1;
}
if (iOneBitNum != m_iN / 2)
{
return -1;
}
//最低位编号为1,次最低为编号为2… 奇数位为1,需要移动的次数
int iMove1 = m_iN / 2 - bitcount(iMask & 0x55555555);
//偶数为为1
int iMove2 = m_iN / 2 - bitcount(iMask & 0xAAAAAAAA);
return min(iMove1, iMove2);
}
}
int MaskRow(const vector& vRow)
{
int iRet = 0;
for (int i = 0; i < m_iN; i++)
{
if (vRow[i])
{
iRet |= (1 << i);
}
}
return iRet;
}
int MaskCol(const vector<vector>& board, int iCol)
{
int iRet = 0;
for (int i = 0; i < m_iN; i++)
{
if (board[i][iCol])
{
iRet |= (1 << i);
}
}
return iRet;
}
int m_iN;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 **C+

+17**
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1510761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PWARL CTF and others

title: 一些复杂点的题目 date: 2024-03-09 16:05:24 tags: CTF 2024年3月9日 今日习题完成&#xff1a; 1.BUU [网鼎杯 2020 半决赛]AliceWebsite 2.[RoarCTF 2019]Online Proxy 3.[Polar CTF]到底给不给flag呢 4.网鼎杯 2020 总决赛]Game Exp [RoarCTF 2019]Online Proxy …

微信小程序云开发教程——墨刀原型工具入门(常用组件)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

初学SpringBoot——请求响应

0 引言 我们在使用SpringBoot开发Java后端项目时候&#xff0c;需要响应前端发送过来的请求&#xff0c;那后端如何响应前端的请求呢&#xff1f;以及前端发送那么多的请求&#xff0c;后端如何根据不同的请求执行不同的代码呢&#xff1f; 1 Postman 当前&#xff0c;主流的…

电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序目录 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 1、 影院信息管理 2 、电影信息管理 2、 用户功能实现 1、 影院信息 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考…

3月12日 工作记录 DeepSeek-VL阅读笔记

昨天考完试&#xff0c;晚上把那个讨人厌的项目做了阶段结果给合作者展示去了&#xff0c;然后就看到deepseek发布了vision language的技术报告&#xff0c;于是打算今天上午看看。 DeepSeek VL 很多内容直接翻译自其 DeepSeek-VL&#xff0c;下面的我们指的的是deepseek vl的…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的障碍物检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发障碍物检测系统对于道路安全性具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个障碍物检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同模型间的性能…

卡片大小,秒传千兆,内嵌加密 | 芯点子 x 希捷联名款CS1000高速移动固态硬盘首发评测

卡片大小&#xff0c;秒传千兆&#xff0c;内嵌加密 | 芯点子 x 希捷联名款CS1000高速移动固态硬盘首发评测 哈喽小伙伴们好&#xff0c;我是Stark-C~ 写在前面 我个人作为一名常和各种数据打交道的苦逼搬砖族&#xff0c;平时使用最多的操作就是各种数据备份、文件传输和分…

Codeforces Round 933 (Div. 3)

Codeforces Round 933 (Div. 3) Codeforces Round 933 (Div. 3) A. Rudolf and the Ticket 题意&#xff1a;俩口袋各有n和m枚不同面值的硬币&#xff0c;各取一枚&#xff0c;有多少种小于k的可能。 思路&#xff1a;数据很小&#xff0c;暴力枚举。 AC code&#xff1a;…

【深度学习笔记】7_6 RMSProp算法

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 7.6 RMSProp算法 我们在7.5节&#xff08;AdaGrad算法&#xff09;中提到&#xff0c;因为调整学习率时分母上的变量 s t \boldsymbol…

得帆助力大族激光主数据平台建设,用数据为企业生产力赋能

本期客户 大族激光科技产业集团股份有限公司&#xff08;以下简称“大族激光”&#xff09;是一家从事工业激光加工设备与自动化等配套设备及其关键器件的研发、生产、销售&#xff0c;激光、机器人及自动化技术在智能制造领域的系统解决方案的优质提供商&#xff0c;是国内激光…

RPC通信原理

RPC通信原理 RPC的概念 如果现在我有一个电商项目&#xff0c;用户要查询订单&#xff0c;自然而然是通过Service接口来调用订单的实现类。 我们把用户模块和订单模块都放在一起&#xff0c;打包成一个war包&#xff0c;然后再tomcat上运行&#xff0c;tomcat占有一个进程&am…

智能革新:思通数科开源AI平台在保险合同管理中的应用与优化

思通数科开源的多模态AI能力引擎平台是一个强大的工具&#xff0c;它结合了自然语言处理&#xff08;NLP&#xff09;、图像识别和语音识别技术&#xff0c;为企业提供自动化处理和分析文本、音视频和图像数据的能力。这个平台的开源性质意味着它可以被广泛地应用于各种业务场景…

JSP中间件漏洞

jsp的注入最难挖 另外3个好挖 struts2 url有action 就代表是struts2 用漏洞利用工具 下面之这两个一般都可以用工具扫一下 、 有些网站看起来没有 action实际上我们提交了 我们的账号和密码 之后就有了 工具包是下面 这些 github上面也有 用法就是如下图 把url放进去就…

3d视觉笔记 | 神经辐射场NeRF(Neural Radiance Fields)

NeRF概念 NeRF&#xff08;Neural Radiance Fields&#xff0c;神经辐射场&#xff09;是一种用于3D场景重建和图像渲染的深度学习方法。它由Ben Mildenhall等人在2020年的论文《NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis》中首次提出。NeRF通过…

8-100V转5V 2A 12V 2A 降压芯片 外置MOS 恒压输出

SC9103 一款宽电压范围降压型 DC-DC 电源管理芯片&#xff0c;内部集成使能开关控制、基准电源、误差放大器、 过热保护、限流保护、短路保护等功能&#xff0c;非常适合宽电压输入降压使用。 SC9103 零功耗使能控制&#xff0c;可以大大节省外围器件&#xff0c;更加适合电池场…

20240309web前端_第一周作业_完成用户注册界面

作业一&#xff1a;完成用户注册界面 成果展示&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-…

c++初阶------类和对象(下)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

避抗指南:如何寻找OLED透明屏供应商

寻找OLED透明屏供应商&#xff0c;你可以按照以下步骤进行&#xff1a; 明确需求&#xff1a;首先&#xff0c;你需要明确自己的需求&#xff0c;包括所需OLED透明屏的尺寸、分辨率、亮度、色彩饱和度等具体参数&#xff0c;以及预算和采购量。这有助于你更精准地找到符合需求的…

Django入门 整体流程跑通

Django学习笔记 一、Django整体流程跑通 1.1安装 pip install django //安装 import django //在python环境中导入django django.get_version() //获取版本号&#xff0c;如果能获取到&#xff0c;说明安装成功Django目录结构 Python310-Scripts\django-admi…

滑动窗口的概念,糊涂窗口综合征,nagle算法

目录 1.流量控制 2.滑动窗口 3.思考问题 1.流量控制 一般来说,我们总是希望数据传输得更快一些,但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失.所谓流量控制(flow control)就是发送方的发送速率不要太快,要让接收方来得及接收. 2.滑动窗口 T…