题意:N*M的地图,需要照亮所有的'.'(最多15个),但是'#'不能被照亮,问最多需要多少灯。每盏灯能照亮当前格子,右边格子和上方格子。有一盏特别的灯,能够转向。
http://acm.hdu.edu.cn/showproblem.php?pid=4770
#include <stdio.h>
#include <queue>
#include <memory.h>
#include <iostream>
using namespace std;
#define INF 1000000000
char x[210][210];
int cnt;
bool vis[16];
struct node{
int a,b;
}y[210];
int dx[8]={-1,0,0,1,1,0,0,-1};
int dy[8]={0,1,1,0,0,-1,-1,0};
int n,m;
bool judge(int a,int b,int k){
memset(vis,0,sizeof(vis));
int w=1;
int aa=a;
while(a>0){
if(a%2==1){
if(w!=b){ //下标为w的灯是普通灯
vis[w]=1;
for(int i=0;i<2;++i){
int g=x[y[w].a+dx[i]][y[w].b+dy[i]]; //这个位置是#还是下标
if(g=='#')
return 0;
vis[g]=1;
}
}
else{
vis[w]=1;
for(int i=k*2;i<=k*2+1;++i){
int g=x[y[w].a+dx[i]][y[w].b+dy[i]]; //这个位置是#还是下标
if(g=='#')
return 0;
vis[g]=1;
}
}
}
w++;
a/=2;
}
for(int i=1;i<=cnt;i++)
if(!vis[i])
return 0;
return 1;
}
int main(){
while(~scanf("%d%d",&n,&m)){
if(n==0&&m==0)break;
memset(x,0,sizeof(x));
cnt=0;
for(int i=1;i<=n;i++){
scanf("%s",x[i]+1);
for(int j=1;j<=m;j++){
if(x[i][j]=='.'){
x[i][j]=++cnt;
y[cnt].a=i;y[cnt].b=j;
}
}
}
if(!cnt){
printf("0\n");
continue;
}
int end=(1<<cnt);
int ans=INF;
for(int i=1;i<end;i++){ //二进制枚举灯的状态
for(int j=0;j<=cnt;j++){ //挑出要把哪一个作为特殊灯或不选(取0)
int tmp=i;
int ss=0;
while(tmp){
if(tmp%2==1)
ss++; //求出这种状态要点几盏灯
tmp/=2;
}
for(int k=1;k<=3;k++){ //枚举这盏特殊灯的方向
if(judge(i,j,k)){
ans=min(ans,ss); //这种状态符合条件,更新最少灯数
break;
}
}
}
}
if(ans!=INF)
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}