入门力扣自学笔记132 C++ 题目编号782

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

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


思路:

判断如果可以变成棋盘, 必要条件为:

有且只能有两个不同行, 两个不同列;

不同的行列必须互补。

计算变换次数: 每次变换可以改变两行的数字, 因为最终棋盘是01相间的排列, 只需要计算行列与01排列不同的数字的数量除以2, 相加即可。


代码

class Solution {
public:
    const int INF = 1e8;

    int ones(int a) {
        int res = 0;
        while(a) res++, a -= (a & -a);
        return res;
    }

    int get(int a, int b) {
        if(ones(a) != ones(b)) return INF;
        return ones(a^b) / 2;
    }

    int movestochessboard(vector<vector<int>>& board) {
        set<int> row, col;
        int n = board.size();

        for(int i=0; i<n; i++) {
            int r = 0, c = 0;
            for(int j=0; j<n; j++) {
                r = r << 1 | board[i][j];
                c = c << 1 | board[j][i];
            }
            row.insert(r), col.insert(c);
        }

        if(row.size() != 2 || col.size() != 2) return -1;
        int r1 = *row.begin(), r2 = *row.rbegin();
        int c1 = *col.begin(), c2 = *col.rbegin();
        if((r1^r2) != (1<<n)-1 || (c1^c2) != (1<<n)-1) return -1;
        int s1 = 0;
        for(int i=0; i<n; i+=2) s1 |= 1 << i;
        int s2 = ((1<<n)-1) ^ s1;
        int r_cost = min(get(r1, s1), get(r1, s2));
        int c_cost = min(get(c1, s1), get(c1, s2));
        int res = r_cost + c_cost;
        if(res >= INF) return -1;
        return res;
    }
};

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...