搜索题.
剪枝1.如果当前点的左上一个点是空,或者当前点是最右边的点并且上面一个点是空,剪掉
剪枝2.如果当前需要点亮的点数量大于等于最小值的点数量,剪掉.
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn = 6;
char pt[maxn][maxn];
char map[maxn][maxn];
int ans[maxn][maxn];
int grid[maxn][maxn];
int firstLine[maxn];
int minAns, n, m;
int di[][3] = {-1, -1, -1, 0 , 0 ,0, 1, 1, 1};
int dj[][3] = {-1, 0, 1, -1, 0, 1, -1 , 0, 1};
void backtracking(int curi, int cnt){
if(curi >= n * m){
int f = 0;
for (int i = 0; i < n; ++i){
for (int j = 0; j < m; ++j){
if(!map[i][j]){
f = 1;
break;
}
}
if(f)break;
}
if(!f && cnt < minAns){
minAns = cnt;
memcpy(ans, grid, sizeof(grid));
}
return;
}else if(cnt >= minAns)return;
int ci = curi / m, cj = curi % m;
int uli = ci - 1, ulj = cj - 1;
grid[ci][cj] = 0;
if(ci == 0 || cj == 0){//是第一行或者第一列
backtracking(curi + 1, cnt);
}else if(ci > 0 && cj > 0 && map[uli][ulj]){
if(cj != m - 1 || map[uli][cj])//是最后一列
backtracking(curi + 1, cnt);
}
for (int i = 0; i < 3; ++i){//点亮
for (int j = 0; j < 3; ++j){
int ni = ci + di[i][j], nj = cj + dj[i][j];
if(pt[i][j] &&ni >= 0 && ni < n && nj >= 0 && nj < m){
map[ni][nj] = !map[ni][nj];
}
}
}
grid[ci][cj] = 1;
if(ci == 0 || cj == 0){//是第一行或者第一列
backtracking(curi + 1, cnt + 1);
}else if(ci > 0 && cj > 0 && map[uli][ulj]){
if(cj != m - 1 || map[uli][cj])//是最后一列
backtracking(curi + 1, cnt + 1);
}
for (int i = 0; i < 3; ++i){//还原
for (int j = 0; j < 3; ++j){
int ni = ci + di[i][j], nj = cj + dj[i][j];
if(pt[i][j] &&ni >= 0 && ni < n && nj >= 0 && nj < m){
map[ni][nj] = !map[ni][nj];
}
}
}
grid[ci][cj] = 0;
}
int main(){
int cas = 1;
while (scanf("%d%d", &n, &m)){
if(!n && !m)break;
for (int i = 0; i < 3 ; ++i){
for (int j = 0; j < 3; ++j){
cin >> pt[i][j];
if(pt[i][j] == '*')pt[i][j] = 1;
else pt[i][j] = 0;
}
}
memset(ans, 0, sizeof(ans));
memset(grid, 0, sizeof(grid));
memset(map, 0, sizeof(map));
minAns = 26;
backtracking(0, 0);
printf("Case #%d\n", cas++);
memset(map, 0, sizeof(map));
if(minAns < 26){
int cnt = 0;
for (int i = 0; i < n ; ++i){
for (int j = 0; j < m; ++j){
if(ans[i][j]){
if(cnt++ > 0)printf(" ");
printf("%d", i * m + j +1);
}
}
}
printf("\n");
}else{
printf("Impossible.\n");
}
}
return 0;
}