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

作者推荐

视频算法专题

本文涉及知识点

数学 网格 状态压缩

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.mzph.cn/news/739382.shtml

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

相关文章

day08_Mybatis

文章目录 前言一、快速入门1.1 入门程序分析1.2 入门程序实现1.2.1 准备工作1.2.1.1 创建springboot工程1.2.1.2 数据准备 1.2.2 配置Mybatis1.2.3 编写SQL语句1.2.4 单元测试1.3 解决SQL警告与提示 二、JDBC介绍2.1 介绍2.2 代码2.3 问题分析2.4 技术对比 三、数据库连接池3.1…

c语言经典测试题12

1.题1 float f[10]; // 假设这里有对f进行初始化的代码 for(int i 0; i < 10;) { if(f[i] 0) break; } 上述代码有那些缺陷&#xff08;&#xff09; A: for(int i 0; i < 10;)这一行写错了 B: f是float型数据直接做相等判断有风险 C: f[i]应该是f[i] D: 没有缺…

【YOLOv8模型网络结构图理解】

YOLOv8模型网络结构图理解 1 YOLOv8的yaml配置文件2 YOLOv8网络结构2.1 Conv2.2 C3与C2f2.3 SPPF2.4 Upsample2.5 Detect层 1 YOLOv8的yaml配置文件 YOLOv8的配置文件定义了模型的关键参数和结构&#xff0c;包括类别数、模型尺寸、骨干&#xff08;backbone&#xff09;和头部…

谷歌seo外链重要还是内容重要?

想做网站&#xff0c;内容跟外链缺一不可&#xff0c;如果真的要说哪个更重要&#xff0c;那内容依旧是网站的核心&#xff0c;而外链则是额外的加分项 内容永远是王道&#xff0c;不管谷歌seo的算法怎么变&#xff0c;只要你的内容没问题&#xff0c;那就肯定不会牵扯到你的网…

Oracle 配置多个缓冲池(Keep pool Recycle Pool)

默认情况下&#xff0c;Oracle只有一个缓冲池 - Buffer Cache&#xff0c;其可以满足基本数据缓存需求。但某些数据的访问模式可能与普通数据不同&#xff0c;对于访问非常频繁的数据和很少访问的数据&#xff08;两种极端&#xff09;&#xff0c;Oracle可以支持配置两个独立的…

“312血洗四周年”!比特币冲破7.2万创新高!手持华尔街资金与减半叙事,跃升为全球第8大资产!

在过去一周时间里&#xff0c;比特币三次突破了2021年11月的历史高点。周一&#xff0c;加密市场延续涨势&#xff0c;比特币涨至72000美元以上&#xff0c;盘中一度触及72800美元&#xff0c;以太坊攀升至4000美元以上。 随着比特币再次创下新纪录&#xff0c;其市值已突破1.4…

python基础及网络爬虫

网络爬虫(Web crawler)&#xff0c;有时候也叫网络蜘蛛(Web spider)&#xff0c;是指这样一类程序——它们可以自动连接到互联网站点&#xff0c;并读取网页中的内容或者存放在网络上的各种信息&#xff0c;并按照某种策略对目标信息进行采集&#xff08;如对某个网站的全部页面…

记录一下C++的学习之旅吧--C++基础

文章目录 前言using namespace std; 使用标准命名空间一、helloworld-输出表示1.1代码1.2 运行结果 二、变量2.1.1 普通变量代码2.1.2 运行结果2.2.1 常量和变量代码2.2.2 运行结果 三、sizeof---统计数据类型所占的内存大小3.1 代码3.2 运行结果 四、小数表示4.2 运行结果 五、…

基于React低代码平台开发:直击最新高效应用构建

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录…

【JavaWeb】Tomacat部署Web项目

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍【JavaWeb】Tomacat部署Web项目的详细使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题…

《为什么学生不喜欢上学?》读书笔记

书简介 美国弗吉尼亚大学心理学教授威林厄姆的教育心理学著作。 作者在文末揭示了撰写此书的目的&#xff1a; 【 教育是将世代积累的智慧传递给孩子&#xff0c;我们强烈地相信它的重要性&#xff0c;因为我们知道&#xff0c;它为每个孩子以及其他所有人都带来了更好生活的希…

./ 相对路径与node程序的启动目录有关

node:internal/fs/sync:78 return binding.openSync( ^ Error: ENOENT: no such file or directory, open D:\前端的学习之路\项目\codeHub\keys\private_key.pem at Object.open (node:internal/fs/sync:78:18) at Object.openSync (node:fs:565:…

【网站项目】014乡镇自来水收费系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

JavaScript---lazyload图片懒加载处理_IntersectionObserver

IntersectionObserver API兼容性&#xff1a; 部分代码展示&#xff1a; // 懒加载处理const imgsElem document.querySelectorAll(img);const topElem document.querySelector(#top);// IntersectionObserverconst Observer new IntersectionObserver((entries, observer) …

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 …

【软件工程导论】——软工学绪论及传统软件工程(学习笔记)

&#x1f4d6; 前言&#xff1a;随着软件产业的发展&#xff0c;计算机应用逐步渗透到社会生活的各个角落&#xff0c;使各行各业都发生了很大的变化。这同时也促使人们对软件的品种、数量、功能和质量等提出了越来越高的要求。然而&#xff0c;软件的规模越大、越复杂&#xf…

X64 页表结构

PML4&#xff08;Page Map Level 4&#xff09;是x86-64架构中用于管理虚拟内存地址翻译的四级页表结构之一。它是一种树形结构&#xff0c;由多个页目录表&#xff08;Page Directory Pointer Table&#xff0c;PDPT&#xff09;组成&#xff0c;每个PDPT有512个指向下一级页表…

Hololens 2应用开发系列(3)——MRTK基础知识及配置文件配置(中)

Hololens 2应用开发系列&#xff08;3&#xff09;——MRTK基础知识及配置文件配置&#xff08;中&#xff09; 一、前言二、输入系统2.1 MRTK输入系统介绍2.2 输入数据提供者&#xff08;Input Data Providers&#xff09;2.3 输入动作&#xff08;Input Actions&#xff09;2…

Date类型及dayjs的使用总结

一、Date() Date数据类型用于处理日期和时间&#xff0c;它可以表示自1970年1月1日00:00:00 UTC&#xff08;Coordinated Universal Time&#xff0c;国际协调时间&#xff09;以来的毫秒数。 1.创建Date对象 例如&#xff1a;Tue Oct 31 2023 14:01:33 GMT0800 (中国标准时…

算法刷题day28

目录 引言一、截断数组二、双端队列三、日期统计 引言 这几道题是周赛里的几道题目&#xff0c;第一道题目我没用这种方法&#xff0c;但还是做出来了&#xff0c;用的一种比较特殊的思考方法&#xff0c;就是把每一个点都判断出来&#xff0c;不满足要求的就舍弃&#xff0c;…