题目大意:给出一个n*m的格子,每个格子上都有一个按钮和一盏灯。
按钮按下后,它旁边的灯的状态就会变化。
灯的变化由所给的3*3的九宫格表示。
按下一个按钮后,九宫格的中心点就代表该点,然后将九宫格嵌套到该方格,九宫格的相应位置对应该n*m列表的相应格子,比如九宫格中心点的左边点对应该点的左边的第一个点。
然后*代表灯的状态变为相反状态

解题思路:
同一个点按下两次就相当于抵消了,按点的顺序是无关的,所以从小到大开始枚举。
纪录下按下每个点后这n*m格子会发生的变化,然后亦或一下就相当于按下了该点了。
暴力dfs + 剪枝,这是一个大剪枝
当你扫描的行,假设为n,上面还存在两行时,也就是n - 2 >= 0,因为当前的行只能改变到上面的行和下面的行的灯的状态,所以如果上面n - 2上面的行还有灯没亮的话,就表示永远不会亮了,return 掉

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
#define maxn 30
#define INF 0x3f3f3f3f
int r, c;
char str[5][5];
int change[30], vis[30], ans[30], MinLen;
int dir[9][2] = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,0},{0,1},{1,-1},{1,0},{1,1}};

void chan(int x,int y) {
    for(int i = 0; i < 9; i++) {
        int xx = x + dir[i][0], yy = y + dir[i][1];
        if(xx >= 0 && xx < r && yy >= 0 && yy < c && str[1 + dir[i][0]][1 + dir[i][1]] == '*') 
            change[x * c + y] |= (1 << (xx * c + yy));
    }
}

void init() {
    for(int i = 0; i < 30; i++)
        change[i] = 0;

    for(int i = 0; i < 3; i++) 
        scanf("%s", str[i]);
    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++) 
            chan(i,j);
    memset(vis,0,sizeof(vis));
    MinLen = INF;
}

void dfs(int Min, int statu, int len) {
    if(statu == (1 << (r * c)) - 1 && len < MinLen) {
        MinLen = len;
        for(int i = 0; i < r * c; i++)
            ans[i] = vis[i];
        return ;
    }
    if((Min / c) >= 2) {
        int cur = (Min / c) - 2;
        for(int i = cur * c; i < cur * c + c; i++) {
            if(! (statu & (1 << i)))
                return ;
        }
    }   
    if(Min == (r * c))
        return ;

    vis[Min] = 1;
    dfs(Min+1, statu ^ change[Min],len + 1);
    vis[Min] = 0;
    dfs(Min+1,statu,len);
}

int main() {
    int cas = 1;
    while(scanf("%d%d", &r, &c) == 2 && r + c) {  
        init();
        dfs(0,0,0);
        printf("Case #%d\n", cas++);
        if(MinLen != INF) {
            bool flag = false;
            for(int i = 0; i < r * c; i++) {
                if(ans[i]) {
                    if(flag)
                        printf(" ");

                    printf("%d", i + 1);
                    flag = true;
                }
            }
            printf("\n");
        }
        else 
            printf("Impossible.\n");
    }
    return 0;
}