PDF (English) | Statistics | Forum |
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\n",s,ac); 42 else printf("Case %d: impossible\n",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 }