# LightOJ 1092 Lighted Panels 状压DP

179人阅读 评论(0)

Description

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

4

5 5

*****

*...*

*...*

*...*

*****

1 2

.*

3 3

**.

**.

...

4 4

*...

**..

..**

...*

Sample Output

Case 1: 1

Case 2: impossible

Case 3: 2

Case 4: 10

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int dp[10][260][260],ret[300][300],sta[10],opt[300];
char str[20];
int cal(int opt,int sat){
int res=sat,tmp=opt;
int ii=0;
while(tmp){
if(tmp&1){
if(ii>0) res^=(1<<(ii-1));
res^=(1<<ii);
if(ii<m-1) res^=(1<<(ii+1));
}
tmp=tmp>>1;
ii++;
}
//cout<<sat<<' '<<opt<<' '<<res<<endl;
return res;
}
int cnt_opt(int op){
int tmp=op;
int res=0;
while(tmp){
if(tmp&1) res++;
tmp=tmp>>1;
}
return res;
}
void init(){
for(int i=0;i<n;++i)
for(int j=0;j<(1<<m);++j)
for(int k=0;k<(1<<m);++k)
dp[i][j][k]=INF;
memset(sta,0,sizeof(sta));
for(int i=0;i<(1<<m);++i){
opt[i]=cnt_opt(i);
for(int j=0;j<(1<<m);++j){
ret[j][i]=cal(i,j);
}
}
}
int main()
{

int T,cas=1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<n;++i){
scanf("%s",str);
for(int j=m-1;j>=0;--j)
if(str[j]=='.') sta[i]+=(1<<(m-1-j));
//cout<<sta[i]<<endl;
}
int ans=INF;
if(n==1){
for(int i=0;i<(1<<m);++i){
if(ret[sta[0]][i]==0) ans=min(ans,opt[i]);
}
if(ans==INF) printf("Case %d: impossible\n",cas++);
else printf("Case %d: %d\n",cas++,ans);
continue;
}
dp[0][sta[0]][sta[1]]=0;
for(int i=0;i<(1<<m);++i){
dp[0][ret[sta[0]][i]][ret[sta[1]][i]]=min(dp[0][ret[sta[0]][i]][ret[sta[1]][i]],opt[i]);
}
for(int i=0;i<n-2;++i)
for(int j=0;j<(1<<m);++j)
for(int k=0;k<(1<<m);++k)
if(dp[i][j][k]!=INF){
for(int op=0;op<(1<<m);++op){
if(ret[j][op]==0){
//cout<<j<<' '<<k<<' '<<op<<endl;
dp[i+1][ret[k][op]][ret[sta[i+2]][op]]=min(dp[i+1][ret[k][op]][ret[sta[i+2]][op]],dp[i][j][k]+opt[op]);
}
}
//cout<<dp[1][sta[1]][sta[2]]<<endl;
}
for(int i=0;i<(1<<m);++i)
for(int j=0;j<(1<<m);++j)
for(int k=0;k<(1<<m);++k){
if(ret[i][k]==0&&ret[j][k]==0){
ans=min(ans,dp[n-2][i][j]+opt[k]);
}
}
if(ans==INF) printf("Case %d: impossible\n",cas++);
else printf("Case %d: %d\n",cas++,ans);
}
return 0;
}


0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：3536次
• 积分：158
• 等级：
• 排名：千里之外
• 原创：12篇
• 转载：3篇
• 译文：0篇
• 评论：0条
阅读排行
评论排行