代码改变世界

矩阵转换

2010-10-02 22:46  wansishuang  阅读(217)  评论(0编辑  收藏  举报

You are given a rectangular matrix with odd numbers of rows and columns. Each cell of the matrix contains either 0 or 1. In one move, you can select any one row or column of the matrix and replace all 0's with 1's and all 1's with 0's in that row/column. Your aim is to have an even number of 1's in each row and each column.

The elements of the String[] matrix correspond to the rows of the matrix. Return the minimal number of moves needed to achieve your aim, or -1 if it's impossible.

 

Examples

0)
    
{
"111",
"011",
"001"
}
Returns: 2
We can first apply the operation to the middle row of the matrix, and then to the middle column.
1)
    
{
"111",
"111",
"111",
"111",
"111"
}
Returns: 3
We must apply the operations either to all rows or to all columns. As the number of columns is less than the number of rows, we choose the second variant.
2)
    
{
"00000",
"00000",
"00000"
}
Returns: 0
The matrix initially contains an even number of ones in each row and column, so we don't apply any operations.
3)
    
{
"10101",
"01010",
"10101",
"01010",
"10101"
}
Returns: 5

This problem involved very little coding, as the main challenge to overcome was figuring out the mathematical logic behind it. The first thing we may wonder is why the input always consists of an odd number of rows and columns.One important property that this restriction gives us is that if we, say, perform a move on a particular row, then the parity of the ones and zeros in that row is always changed, and the same holds for performing a move on a particular column.When we talk about the parity of ones or zeros, we mean the property that the number of ones or zeros in a row or column is even or odd. From this property, we have two important observations:

  • If we perform a move on row i, the parity of ones in row i is changed, and the parity of ones and zeros in every column is changed.
  • If we perform a move on column j, the parity of ones in column j is changed, and the parity of ones and zeros in every row is changed.
  • If we perform an even number of moves on the set of rows, then the parity of ones and zeros in every column remains unchanged, otherwise it is changed.
  • If we perform an even number of moves on the set of columns, then the parity of ones and zeros in every row remains unchanged, otherwise it is changed.

Now, let's define the number of rows with an even number of ones as Gr (good rows), the number of rows with an odd number of ones as Br (bad rows), the number of columns with an even number of ones as Gc (good columns), and the number of columns with an odd number of ones as Bc (bad columns). Also assume that there are N rows and M columns in our grid. We have two possible ways of making the partity of ones in the rows and columns to be even:

 

First, we can perform moves on every bad row. If Br is even, then after performing our moves on the bad rows, the parity of ones in all the columns remains constant. Now we complete our task by performing moves on every bad column, and the total number of moves required is Br + Bc.However, if Br is odd, then the partity of ones in all the columns will change after performing the moves on the bad rows. Thus, all the good columns become bad columns, and vice-versa.Therefore we must perform moves on all the originally good columns, and the total number of moves required is Br + Gc.

The other possible solution is to perform moves on every good row. If Gr is even, then after performing our moves on the good rows, the parity of ones in all the columns remains constant similar to the above.We again complete the task by performing moves on every bad column, and the total number of moves required is Gr + Bc. However, if Gr is odd, then the partity of ones in all the columns will change after performing the moves on the good rows,so all the good columns become bad columns, and vice-versa. Therefore we must perform moves on all the good columns, and the total number of moves required is Gr + Gc.

Of course, there may be situations where after performing the required operations on the chosen rows and columns, that the resulting grid could still have some row or column with an odd number of ones. However, it can be shown thatthis situation can never happen, so we will never return -1. The proof of this fact is left as an exercise to the reader (hint: consider a case-by-case analysis and a proof by contradiction). A sample C++ solution to this problem follows:

 

int EvenOnes::minOperations(vector <string> mat) {
    int badrow = 0, badcol = 0;
    int n = mat.size(); int m = mat[0].size();
    
    //get number of bad rows
    for (int i = 0; i < n; i++) {
        int ones = 0;
        for (int j = 0; j < m; j++) if (mat[i][j]=='1') ones++;
        if (ones % 2 == 1) badrow++;
    }
    
    //get number of bad cols
    for (int i = 0; i < m; i++) {
        int ones = 0;
        for (int j = 0; j < n; j++) if (mat[j][i] == '1') ones++;
        if (ones % 2 == 1) badcol++;
    }
    int a = 0, b = 0;
    //choose bad rows
    a = badrow;
    if (badrow % 2 == 1) a += m - badcol;
    else a += badcol;
    
    //choose good rows
    b = n - badrow;
    if ((n - badrow) % 2 == 1) b += m - badcol;
    else b += badcol;
    
    return min(a, b);
}