思路:在一个n*m的地图里面,需要放置一些灯使得所有的路都能被照亮。灯照亮的方式为“L”型,即照亮(x,y),(x-1,y),(x,y+1)三个位置。但是现在有一盏特别的灯,可以旋转90°或者180°270°,当然可以用也可以不用。不过有一个要求就是,灯不能照到墙。现在问照亮所有的路需要少多少盏灯。
思路: 由于最多只有十五个"."所以枚举每一种情况,再枚举每一个的翻转情况
#include<bits/stdc++.h>
using namespace std;
int n,m;
int vis[25]; //第i个点是否点亮
int d[30][5];//每个点的坐标
int b[205][205];
char mp[205][205];
int ans1=0;//原图中.的个数
int a[30];//记录灯的位置
int ans2;//便利的i的位数
//翻转0
bool fan1(int m1){
memset(vis,0,sizeof(vis));
int ans=1;
for(int i=1;i<=ans1;i++){
if(a[i]){
if(i==m1){
if((d[i][0]>1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
else {
if((d[i][0]>1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
}
}
sort(vis+1,vis+ans1+1);
if(!vis[1]){
return 0;
}
else return 1;
}
//翻转90
bool fan2(int m1){
memset(vis,0,sizeof(vis));
int ans=1;
for(int i=1;i<=ans1;i++){
if(a[i]){
if(i==m1){
if((d[i][0]!=n&&!b[d[i][0]+1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]+1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
else {
if((d[i][0]>1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
}
}
sort(vis+1,vis+ans1+1);
if(!vis[1]){
return 0;
}
else return 1;
}
//180
bool fan3(int m1){
memset(vis,0,sizeof(vis));
int ans=1;
for(int i=1;i<=ans1;i++){
if(a[i]){
if(i==m1){
if((d[i][0]!=n&&!b[d[i][0]+1][d[i][1]])||(d[i][1]!=1&&!b[d[i][0]][d[i][1]-1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]+1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]-1]]=1;
}
else {
if((d[i][0]>1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
}
}
sort(vis+1,vis+ans1+1);
if(!vis[1]){
return 0;
}
else return 1;
}
//翻 270
bool fan4(int m1){
memset(vis,0,sizeof(vis));
int ans=1;
for(int i=1;i<=ans1;i++){
if(a[i]){
if(i==m1){
if((d[i][0]!=1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=1&&!b[d[i][0]][d[i][1]-1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]-1]]=1;
}
else {
if((d[i][0]>1&&!b[d[i][0]-1][d[i][1]])||(d[i][1]!=m&&!b[d[i][0]][d[i][1]+1])){
return 0;
}
vis[b[d[i][0]][d[i][1]]]=1;
vis[b[d[i][0]-1][d[i][1]]]=1;
vis[b[d[i][0]][d[i][1]+1]]=1;
}
}
}
sort(vis+1,vis+ans1+1);
if(!vis[1]){
return 0;
}
else return 1;
}
int main(){
while(scanf("%d%d",&n,&m)&&n+m){
ans1=0;
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
if(mp[i][j]=='.'){//存入d数组
d[ans1+1][0]=i;
d[ans1+1][1]=j;
b[i][j]=ans1+1;//按坐标排个序
ans1++;
}
}
}
//'.'只有最多15个所以用状态压缩,一个二进制数表示是否放灯
int k=20;
for(int i=0;i<(1<<ans1);i++){
//记录第i个位置是否放灯
memset(a,0,sizeof(a));
ans2=1;//共几位
int h=i;
int num1=0;//需要点亮的个数
while(h){
if(h&1){
a[ans2]=1;//标记
num1++;
}
ans2++;
h>>=1;
}
//枚举第j个灯翻转的情况
for(int j=1;j<ans2;j++){
if(a[j]){
if(fan1(j)){
k=min(k,num1);
break;
}
if(fan2(j)){
k=min(k,num1);
break;
}
if(fan3(j)){
k=min(k,num1);
break;
}
if(fan4(j)){
k=min(k,num1);
break;
}
}
}
}
if(ans1==0)cout<<0<<endl;
else if(k==20)cout<<-1<<endl;
else cout<<k<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
mp[i][j]='.';
}
}
}
return 0;
}