Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
zmx0142857
GitHub Repository: zmx0142857/mini-games
Path: blob/master/c/lightoff/main.c
363 views
1
// 关灯问题
2
#include <stdio.h>
3
#include <stdbool.h>
4
#include <stdlib.h>
5
6
int rows;
7
int cols;
8
char press[100][100]; // 按下的开关
9
char puzzle[100][100]; // 题面
10
11
bool guess() {
12
int i, j;
13
for (i = 2; i <= rows; i++) {
14
for (j = 1; j <= cols; j++) {
15
// 根据同列的上一行灯的最后状态,来决定是否按按钮
16
press[i][j] = ( press[i-1][j]
17
+ puzzle[i-1][j]
18
+ press[i-1][j-1]
19
+ press[i-2][j]
20
+ press[i-1][j+1] ) % 2;
21
}
22
}
23
24
for (j = 1; j <= cols; j++) {
25
// 逐一判断最后一行的灯是否都熄灭
26
if (puzzle[rows][j] != (press[rows][j] + press[rows][j-1] + press[rows][j+1] + press[rows-1][j]) % 2)
27
return false;
28
}
29
30
return true;
31
}
32
33
void process() {
34
int c;
35
// 清空第一行
36
for (c = 1; c <= cols; c++)
37
press[1][c] = 0;
38
39
while (!guess()) {
40
// 采用二进制进位的算法,从000000 - 111111枚举第一行按钮的方式
41
press[1][1]++;
42
c = 1;
43
while (press[1][c] > 1) {
44
press[1][c] = 0;
45
c++;
46
press[1][c]++;
47
}
48
}
49
}
50
51
void init() {
52
// 在矩阵的第一行前加入一个空行
53
for (int i = 0; i < cols + 2; i++)
54
press[0][i] = puzzle[0][i] = 0;
55
// 在第一列前、最后一列后分别加入一个空列
56
for (int i = 1; i <= rows; i++)
57
press[i][0] = puzzle[i][0] = press[i][cols+1] = puzzle[i][cols+1] = 0;
58
// 读取输入
59
for (int i = 1; i <= rows; i++)
60
for (int j = 1; j <= cols; j++)
61
scanf("%d", (int*)&puzzle[i][j]);
62
}
63
64
void print() {
65
for (int i = 1; i <= rows; i++){
66
for (int j = 1; j <= cols; j++) {
67
printf("%d ", press[i][j]);
68
}
69
printf("\n");
70
}
71
}
72
73
int main(int argc, char **argv) {
74
if (argc < 3) {
75
puts("usage: lightoff rows cols");
76
return 1;
77
}
78
rows = atoi(argv[1]);
79
cols = atoi(argv[2]);
80
init();
81
process();
82
print();
83
return 0;
84
}
85
86