题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4770
题目大意:
在一个n*m的地图里面,需要放置一些灯使得所有的路都能被照亮。灯照亮的方式为“L”型,即照亮(x,y),(x-1,y),(x,y+1)三个位置。但是现在有一盏特别的灯,可以旋转90°或者180°或者270°,当然可以用也可以不用。不过有一个要求就是,灯不能照到墙。现在问照亮所有的路需要至少多少盏灯。
思路:
范围是200*200,但是路的数量最多只有15,所以我们可以想到,利用状压来表示状态,这样的话最多也只有2^15种。然后对于那盏特殊的灯,我们可以枚举它放的位置以及放置的角度,剩下的灯就按照普通的方式枚举。这样的总的复杂度就是2^15*4*15*15。
代码写的有点长= =有点丑。。。。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
char s[205][205];
int n,m,d[205][205],f[20];
struct node{
int x,y;
}p[20];
int min(int a,int b)
{
return a<b?a:b;
}
bool check(int x,int y)
{
if(s[x][y]=='#')return false;
return true;
}
int main()
{
int i,j,k,cnt,tot,ans,flag,gg;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;
ans=99999999;
k=1;
memset(d,0,sizeof(d));
memset(f,0,sizeof(f));
cnt=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>s[i][j];
if(s[i][j]=='.'){
p[cnt].x=i;
p[cnt].y=j;
d[i][j]=cnt;
cnt++;
}
}
if(cnt==0){
printf("0\n");continue;
}
tot=1<<cnt;
for(i=1;i<tot;i++) //总的状态的枚举
for(j=0;j<cnt;j++) //特殊的灯的位置的枚举
{
if(i&(1<<j))
{
for(int h=0;h<4;h++) //放置的角度
{
memset(f,0,sizeof(f));
flag=0;
gg=0;
int fx,fy;
for(int tt=0;tt<cnt;tt++) //普通的灯是否点亮进行枚举
{
gg=0;
if(tt==j)continue;
if(i&(1<<tt)){
f[d[p[tt].x][p[tt].y]]=1;
fx=p[tt].x-1;
fy=p[tt].y;
if(fx>0)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
fx=p[tt].x;
fy=p[tt].y+1;
if(fy<=m)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
}
if(gg)break;
}
if(gg)continue;
f[d[p[j].x][p[j].y]]=1;
if(h==0)
{
fx=p[j].x-1;
fy=p[j].y;
if(fx>0)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
fx=p[j].x;
fy=p[j].y+1;
if(fy<=m)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
}
if(h==1){
fx=p[j].x;
fy=p[j].y+1;
if(fy<=m)
{if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;}
fx=p[j].x+1;
fy=p[j].y;
if(fx<=n)
{if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
}
if(h==2){
fx=p[j].x+1;
fy=p[j].y;
if(fx<=n)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
fx=p[j].x;
fy=p[j].y-1;
if(fy>0)
{if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
}
if(h==3){
fx=p[j].x;
fy=p[j].y-1;
if(fy>0)
{
if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
fx=p[j].x-1;
fy=p[j].y;
if(fx>0)
{if(check(fx,fy)){
f[d[fx][fy]]=1;
}
else gg=1;
}
}
if(gg)continue;
flag=0;
for(int t=0;t<cnt;t++)
{
if(!f[t]){
flag=1;
break;
}
}
if(flag)continue;
else {
int num=0;
for(int t=0;t<cnt;t++)
if(i&(1<<t))num++;
ans=min(ans,num);
}
}
}
}
if(ans==99999999)printf("-1\n");
else
printf("%d\n",ans);
}
}