【夏老师讲模拟卷系列149】详解四省联考(数学·全部题目)

#include <iostream>
using namespace std;
//按动开关,注意二维数组在内存中的分布方式
void turn(bool *arr, int n, int x, int y) {
arr[y + x * n] ^= 1;
//对左侧开关改变状态
if (y - 1 >= 0) {
arr[y - 1 + x * n] ^= 1;
}
//对右侧开关改变状态
if (y + 1 <= 2) {
arr[y + 1 + x * n] ^= 1;
}
//对上侧开关改变状态
if (x - 1 >= 0) {
arr[y + x * n - n] ^= 1;
}
//对下侧开关改变状态
if (x + 1 <= 2) {
arr[y + x * n + n] ^= 1;
}
}
int main() {
bool end[9] = {1, 0, 0, 0, 0, 0, 0, 0, 0}; //结束状态
int ans[8];//存储结果,如果最终结果不符合要求,就存-1
for (int i = 0; i < 8; i++) {
int cnt = 0; //翻转次数
bool start[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; //起始状态
//先对第一行状态进行枚举(内存中是第0行)
if (i & 1 == 1) {
turn(start, 3, 0, 0);
cnt ++;
}
if ((i >> 1) & 1 == 1) {
turn(start, 3, 0, 1);
cnt ++;
}
if ((i >> 2) & 1 == 1) {
turn(start, 3, 0, 2);
cnt ++;
}
/*
开始从第二行第一列开始,逐行遍历。
若上一行结果与答案不符,就按动开关,使上一行结果符合要求,
最终检测最后一行结果是否与结果相同。
一个开关不能按两次,否则次数不是最小,
因为逐行遍历,只有按下一行才能改变上一行的结果
*/
for (int j = 1; j < 3; j++) {
for (int k = 0; k < 3; k++) {
if (start[j * 3 - 3 + k] != end[j * 3 - 3 + k]) {
turn(start, 3, j, k);
cnt++;
}
}
}
for (int k = 0; k < 3; k++) {
//最后一行不符合结果,结果数组内存上-1
if (start[6 + k] != end[6 + k]) {
ans[i] = -1;
goto l1;
}
}
ans[i] = cnt;
l1:
continue;
}
//选出最小结果
int min = 9;
for (int i = 0; i < 8; i++) {
if (ans[i] < min && ans[i] > 0) {
min = ans[i];
}
}
cout << min << endl;
}