1 // Solve a Light Up puzzle.
14 uint32_t rcount
, ccount
;
15 if (!scanf("%d %d\n", &rcount
, &ccount
)) die("input error");
16 int board
[rcount
][ccount
];
17 uint32_t getv(uint32_t i
, uint32_t j
) { return ccount
* i
+ j
+ 1; }
18 zdd_set_vmax(getv(rcount
- 1, ccount
- 1));
22 for (int i
= 0; i
< rcount
; i
++) {
24 for (int j
= 0; j
< ccount
; j
++) {
26 if (c
== EOF
|| c
== '\n') die("input error");
34 inta_append(a
, getv(i
, j
));
38 inta_append(a
, getv(i
, j
));
44 board
[i
][j
] = encode(c
);
47 if (c
!= '\n') die("input error");
49 // Instead of constructing a ZDD excluding particular elements, we could
50 // reduce the number of variables, but then we need to record which variable
51 // represents which square.
52 zdd_contains_0(inta_raw(a
), inta_count(a
));
55 for (uint32_t i
= 0; i
< rcount
; i
++) {
57 zdd_contains_at_most_1(inta_raw(a
), inta_count(a
));
58 for (uint32_t j
= 0; j
< ccount
; j
++) {
61 // There must be at least one light bulb in this square or a
62 // square reachable in one rook move.
65 for(r0
= i
; r0
> 0 && board
[r0
- 1][j
] == -1; r0
--);
66 for(int k
= r0
; k
!= i
; k
++) {
67 inta_append(a
, getv(k
, j
));
69 for(c0
= j
; c0
> 0 && board
[i
][c0
- 1] == -1; c0
--);
70 for(int k
= c0
; k
!= j
; k
++) {
71 inta_append(a
, getv(i
, k
));
73 inta_append(a
, getv(i
, j
));
74 for(int k
= j
+ 1; k
< ccount
&& board
[i
][k
] == -1; k
++) {
75 inta_append(a
, getv(i
, k
));
77 for(int k
= i
+ 1; k
< rcount
&& board
[k
][j
] == -1; k
++) {
78 inta_append(a
, getv(k
, j
));
80 zdd_contains_at_least_1(inta_raw(a
), inta_count(a
));
81 // There is at most one light bulb in this row. We record this when
82 // we first enter the row.
85 for(int k
= i
; k
< rcount
&& board
[k
][j
] == -1; k
++) {
86 inta_append(a
, getv(k
, j
));
88 zdd_contains_at_most_1(inta_raw(a
), inta_count(a
));
91 // Similarly for columns.
94 for(int k
= j
; k
< ccount
&& board
[i
][k
] == -1; k
++) {
95 inta_append(a
, getv(i
, k
));
97 zdd_contains_at_most_1(inta_raw(a
), inta_count(a
));
98 // Defer the intersection.
105 void check(int r
, int c
) {
106 if (r
>= 0 && r
< rcount
&& c
>= 0 && c
< ccount
107 && board
[r
][c
] == -1) {
108 inta_append(a
, getv(r
, c
));
115 zdd_contains_exactly_n(board
[i
][j
], inta_raw(a
), inta_count(a
));
127 void printsol(int *v
, int vcount
) {
128 char pic
[rcount
][ccount
];
129 memset(pic
, '.', rcount
* ccount
);
130 for(int i
= 0; i
< vcount
; i
++) {
137 for (int i
= 0; i
< rcount
; i
++) {
138 for (int j
= 0; j
< ccount
; j
++) {
139 switch(board
[i
][j
]) {
144 putchar('0' + board
[i
][j
]);
155 zdd_forall(printsol
);