一个n*m的房间有的房间是可破坏的,其他不可破坏,现在给你一些L型的灯,其中只有一个可以旋转,其他不能,让你用最少的灯覆盖所有的可破坏区域,且不能覆盖不可破坏的区域。
枚举旋转的灯,对剩下的DFS即可,状压存储已经被点亮的灯
#include "stdio.h" #include "string.h" struct P { int x,y; }p[21]; int ans,n,m,cnt,aim,b[21]; char str[210][210]; int judge(int x,int y) { if (x>=0 && x<n && y>=0 && y<m && str[x][y]=='#') return 0; return 1; } void dfs(int k,int sum,int mark,int light) { int i,j,ll; if (sum>=ans) return ; if (light==aim) {ans=sum; return ;} if (k>=cnt) return ; dfs(k+1,sum,mark,light); for (i=k;k<cnt;k++) if (i!=mark) { ll=light|b[i]; if (judge(p[i].x-1,p[i].y)==0 || judge(p[i].x,p[i].y+1)==0) continue; for (j=0;j<cnt;j++) { if (p[i].x-1==p[j].x && p[i].y==p[j].y) ll|=b[j]; if (p[i].x==p[j].x && p[i].y+1==p[j].y) ll|=b[j]; } dfs(k+1,sum+1,mark,ll); } } int main() { int i,j,mark,light; b[0]=1; for (i=1;i<=16;i++) b[i]=b[i-1]*2; while (scanf("%d%d",&n,&m)!=EOF) { if (n+m==0) break; for (i=0;i<n;i++) scanf("%s",str[i]); cnt=0; for (i=0;i<n;i++) for (j=0;j<m;j++) if (str[i][j]=='.') { p[cnt].x=i; p[cnt].y=j; cnt++; } if (cnt==0) { printf("0\n"); continue; } ans=100000; aim=b[cnt]-1; dfs(0,0,-1,0); for (i=0;i<cnt;i++) { if (judge(p[i].x-1,p[i].y) && judge(p[i].x,p[i].y-1)) { mark=i; light=b[i]; for (j=0;j<cnt;j++) { if (p[j].x==p[i].x && p[j].y==p[i].y-1) light|=b[j]; if (p[j].x==p[i].x-1 && p[j].y==p[i].y) light|=b[j]; } dfs(0,1,mark,light); } if (judge(p[i].x,p[i].y-1) && judge(p[i].x+1,p[i].y)) { mark=i; light=b[i]; for (j=0;j<cnt;j++) { if(p[j].x==p[i].x && p[j].y==p[i].y-1) light|=b[j]; if(p[j].x==p[i].x+1 && p[j].y==p[i].y) light|=b[j]; } dfs(0,1,mark,light); } if (judge(p[i].x,p[i].y+1) && judge(p[i].x+1,p[i].y)) { mark=i; light=b[i]; for (j=0;j<cnt;j++) { if (p[j].x==p[i].x && p[j].y==p[i].y+1) light|=b[j]; if (p[j].x==p[i].x+1 && p[j].y==p[i].y) light|=b[j]; } dfs(0,1,mark,light); } } if (ans==100000) printf("-1\n"); else printf("%d\n",ans); } return 0; }
时间: 2024-11-05 12:34:35