当你第一次看到"布尔矩阵奇偶性"这个题目时,是不是感觉有点懵?别担心,这篇文章将带你从零开始,一步步理解题意、设计算法,最终用C语言实现这个功能。我们会用最通俗易懂的方式,让你彻底掌握这道题的解法。
布尔矩阵是由0和1组成的方阵(即行数和列数相同的矩阵)。题目中提到的"奇偶均势特性"指的是:
举个例子:
code复制1 0 1 0
0 0 0 0
1 1 1 1
0 1 0 1
这个4×4矩阵中:
题目要求我们做三件事:
要解决这个问题,我们需要:
具体来说:
我们需要以下变量:
row_errors:记录不符合条件的行数col_errors:记录不符合条件的列数error_row:记录不符合条件的行号error_col:记录不符合条件的列号plaintext复制开始
↓
输入矩阵
↓
检查每行1的个数是否为偶数
↓
记录不符合的行数和位置
↓
检查每列1的个数是否为偶数
↓
记录不符合的列数和位置
↓
判断:
- 如果行列错误数都为0 → "OK"
- 如果行列错误数都为1 → "Change bit(i,j)"
- 其他情况 → "Corrupt"
↓
输出结果
结束
首先,我们建立基本的程序框架:
c复制#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main() {
int matrix[MAX_SIZE][MAX_SIZE];
int n;
// 读取输入
scanf("%d", &n);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
scanf("%d", &matrix[i][j]);
}
}
// 检查行和列的奇偶性
// ...
// 输出结果
// ...
return 0;
}
接下来,我们实现检查行奇偶性的部分:
c复制int row_errors = 0, error_row = -1;
for(int i = 0; i < n; i++) {
int row_sum = 0;
for(int j = 0; j < n; j++) {
row_sum += matrix[i][j];
}
if(row_sum % 2 != 0) {
row_errors++;
error_row = i;
}
}
同样地,我们检查列的奇偶性:
c复制int col_errors = 0, error_col = -1;
for(int j = 0; j < n; j++) {
int col_sum = 0;
for(int i = 0; i < n; i++) {
col_sum += matrix[i][j];
}
if(col_sum % 2 != 0) {
col_errors++;
error_col = j;
}
}
最后,根据检查结果输出相应信息:
c复制if(row_errors == 0 && col_errors == 0) {
printf("OK");
} else if(row_errors == 1 && col_errors == 1) {
printf("Change bit(%d,%d)", error_row, error_col);
} else {
printf("Corrupt");
}
将上述部分组合起来,我们得到完整代码:
c复制#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main() {
int matrix[MAX_SIZE][MAX_SIZE];
int n;
// 读取输入
scanf("%d", &n);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
scanf("%d", &matrix[i][j]);
}
}
// 检查行奇偶性
int row_errors = 0, error_row = -1;
for(int i = 0; i < n; i++) {
int row_sum = 0;
for(int j = 0; j < n; j++) {
row_sum += matrix[i][j];
}
if(row_sum % 2 != 0) {
row_errors++;
error_row = i;
}
}
// 检查列奇偶性
int col_errors = 0, error_col = -1;
for(int j = 0; j < n; j++) {
int col_sum = 0;
for(int i = 0; i < n; i++) {
col_sum += matrix[i][j];
}
if(col_sum % 2 != 0) {
col_errors++;
error_col = j;
}
}
// 输出结果
if(row_errors == 0 && col_errors == 0) {
printf("OK");
} else if(row_errors == 1 && col_errors == 1) {
printf("Change bit(%d,%d)", error_row, error_col);
} else {
printf("Corrupt");
}
return 0;
}
rowErrorCount代替row_errors优化后的代码结构:
c复制#include <stdio.h>
#include <stdbool.h>
#define MAX_SIZE 100
bool checkRowParity(int matrix[MAX_SIZE][MAX_SIZE], int n, int* errorRow) {
// 实现行检查
}
bool checkColumnParity(int matrix[MAX_SIZE][MAX_SIZE], int n, int* errorCol) {
// 实现列检查
}
int main() {
// 主函数更简洁
}
| 输入 | 预期输出 | 说明 |
|---|---|---|
| 4 1 0 1 0 0 0 0 0 1 1 1 1 0 1 0 1 |
OK | 已满足条件 |
| 3 1 1 1 1 1 1 0 0 0 |
Change bit(0,0) | 修改(0,0)可满足 |
| 2 1 0 0 1 |
Corrupt | 需要修改多个位 |
让我们分析一下这个算法的时间复杂度:
总时间复杂度为O(n²),这是最优的,因为我们必须检查矩阵中的每个元素。
空间复杂度是O(n²),用于存储矩阵。如果题目允许逐行处理,可以优化到O(n)空间,但需要多次读取输入。
对于布尔矩阵,可以使用位运算来优化:
c复制// 用整数表示一行,每位代表一个元素
unsigned int rows[MAX_SIZE];
for(int i = 0; i < n; i++) {
rows[i] = 0;
for(int j = 0; j < n; j++) {
if(matrix[i][j]) {
rows[i] ^= (1 << j);
}
}
}
在实际刷题过程中,我遇到过几个容易忽略的细节:一是忘记初始化计数器,二是行列编号从0开始但输出时误用1-based索引,三是没有考虑n=1的特殊情况。这些问题在测试时都需要特别注意。