1092

1092 - Lighted Panels
Time Limit: 3 second(s) Memory Limit: 32 MB

You are given an R x C 2D grid consisting of several light panels. Each cell contains either a '*' or a '.''*' means the panel is on, and '.' means it's off. If you touch a panel, its state will be toggled. That means, if you touch a panel that's on, it will turn off, and if you touch a panel that's off, it will turn on. But if we touch a panel, all its horizontal, vertical, and diagonal adjacent panels will also toggle their states.

Now you are given the configuration of the grid. Your goal is to turn on all the lights. Print the minimum number of touches required to achieve this goal.

Input

Input starts with an integer T (≤ 125), denoting the number of test cases.

Each test case starts with two integers R (1 ≤ R ≤ 8) and C (1 ≤ C ≤ 8). Then there will be R lines each containing C characters ('*' or '.').

Output

For each test case, print the case number and the minimum number of touches required to have all the light panels in the board on at the same time. If it is not possible then print "impossible".

Sample Input

Output for Sample Input

4

5 5

*****

*...*

*...*

*...*

*****

1 2

.*

3 3

**.

**.

...

4 4

*...

**..

..**

...*

Case 1: 1

Case 2: impossible

Case 3: 2

Case 4: 10

思路:状压枚举;

由于是8个方向的所以不能像以前那样只枚举第一行,但是我们可以将第一行和第一列一起枚举,这样就可以通过dp[x-1][y-1]来断定dp[x][y]是否要翻过来。

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<stdlib.h>
  5 #include<string.h>
  6 #include<queue>
  7 #include<math.h>
  8 using namespace std;
  9 char  str[20][20];
 10 int ak[20][20];
 11 int ap[20][20];
 12 int minn=1e9;
 13 int slove(int n,int m);
 14 void Init(int n,int m);
 15 int main(void)
 16 {
 17     int i,j,k;
 18     scanf("%d",&k);
 19     int s;
 20     int n,m;
 21     for(s=1; s<=k; s++)
 22     {
 23         scanf("%d %d",&n,&m);
 24         for(i=0; i<n; i++)
 25         {
 26             scanf("%s",str[i]);
 27         }
 28         for(i=0; i<n; i++)
 29         {
 30             for(j=0; j<m; j++)
 31             {
 32                 if(str[i][j]=='*')
 33                 {
 34                     ak[i][j]=1;
 35                 }
 36                 else ak[i][j]=0;
 37             }
 38         }
 39         int ac=slove(n,m);
 40         if(ac!=1e9)
 41             printf("Case %d: %d
",s,ac);
 42         else printf("Case %d: impossible
",s);
 43     }
 44     return 0;
 45 }
 46 void Init(int n,int m)
 47 {
 48     int i,j;
 49     for(i=0; i<n; i++)
 50     {
 51         for(j=0; j<m; j++)
 52         {
 53             ap[i][j]=ak[i][j];
 54         }
 55     }
 56 }
 57 int slove(int n,int m)
 58 {
 59     int i,j,k;
 60     int ask=0;
 61     int minn=1e9;
 62     for(i=0; i<(1<<(n+m-1)); i++)
 63     {
 64         ask=0;
 65         Init(n,m);
 66         int xx,yy;
 67         for(j=0; j<n; j++)
 68         {
 69             if(i&(1<<j))
 70             {
 71                 ask++;
 72                 ap[j][0]=ap[j][0]+1;
 73                 ap[j][0]%=2;
 74                 if(j>=1)
 75                 {
 76                     ap[j-1][0]=(ap[j-1][0]+1)%2;
 77                     ap[j-1][1]=(ap[j-1][1]+1)%2;
 78                 }
 79                 ap[j+1][0]=(ap[j+1][0]+1)%2;
 80                 ap[j+1][1]=(ap[j+1][1]+1)%2;
 81                 ap[j][1]=(ap[j][1]+1)%2;
 82             }
 83         }
 84         for(j=n; j<(n+m-1); j++)
 85         {
 86             int s=j-n+1;
 87             if(i&(1<<j))
 88             {
 89                 ask++;
 90                 ap[0][s]=(ap[0][s]+1)%2;
 91 
 92                 if(s>=1)
 93                 {
 94                     ap[0][s-1]=(ap[0][s-1]+1)%2;
 95                     ap[1][s-1]=(ap[1][s-1]+1)%2;
 96                 }
 97                 ap[1][s]=(ap[1][s]+1)%2;
 98                 ap[1][s+1]=(ap[1][s+1]+1)%2;
 99                 ap[0][s+1]=(ap[0][s+1]+1)%2;
100             }
101         }
102         int x,y;
103         for(x=1; x<n; x++)
104         {
105             for(y=1; y<m; y++)
106             {
107                 if(ap[x-1][y-1]==0)
108                 {
109                     ap[x-1][y-1]=1;
110                     ask++;
111                     ap[x][y]=(ap[x][y]+1)%2;
112                     ap[x-1][y]=(ap[x-1][y]+1)%2;
113                     ap[x][y-1]=(ap[x][y-1]+1)%2;
114                     ap[x-1][y+1]=(ap[x-1][y+1]+1)%2;
115                     ap[x+1][y+1]=(ap[x+1][y+1]+1)%2;
116                     ap[x][y+1]=(ap[x][y+1]+1)%2;
117                     ap[x+1][y]=(ap[x+1][y]+1)%2;
118                     ap[x+1][y-1]=(ap[x+1][y-1]+1)%2;
119                 }
120             }
121         }
122         int flag=0;
123         for(x=0;x<n;x++)
124         {
125             for(y=0;y<m;y++)
126             {
127                 if(!ap[x][y])
128                 {flag=1;break;}
129             }
130             if(flag)break;
131         }
132         if(!flag)
133         {
134             minn=min(minn,ask);
135         }
136     }
137     return minn;
138 }
油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5685594.html