n*m的空间中最多有15个.,其他的全是#,现在可以在 . 的位置放置一盏灯,x,y位置的灯可以照亮x,y ; x-1,y; x,y+1三个位置,并且允许有一盏灯可以旋转90,180或270度。问最少用多少盏灯可以照亮所有 . 的区域,并且不照射到#区域(边界可以被照射)。
这题的关键是题干里的There are at most fifteen vulnerable rooms in the bank 和 Dumbledore has only one special light whose lighting direction can be turned by 0 degree,90 degrees, 180 degrees or 270 degrees. 看到这两句话就是个简单的枚举了。最多15个空白位置的话,可以直接状压枚举2^15种状态,然后再枚举一盏可以旋转的灯,最后判断一下时候所有的空白都被找到就可以了......现场赛的时候第一遍只读到最多15盏灯,居然没看到只有一个特殊灯...结果就傻呵呵的去写了个装压搜索,然后就WA到死啊....所以比赛的时候细心读题是很重要的。。题干再长也要耐心读啊...
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <cmath> #include <stack> #include <queue> #include <string> #include <cstring> using namespace std; typedef long long ll; int n,m; int g[210][210]; int gg[210][210]; int fx[5][2]={{-1,0},{1,0},{1,0},{-1,0}}; int fy[5][2]={{0,1},{0,1},{0,-1},{0,-1}}; struct node { int x,y; }light[20]; bool ok[20]; bool on[20]; bool check[20]; char c,c1; int tol; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m) && n&& m) { getchar(); tol=0; for (int i=1; i<=n; i++) { for (int j=1; j<=m; j++) { scanf("%c",&c); if (c=='.') g[i][j]=++tol,light[tol].x=i,light[tol].y=j; else g[i][j]=0; } getchar(); } if (!tol) { cout<<0<<endl; continue; } memset(ok,false,sizeof ok); for (int i=1; i<=tol; i++) { int tx=light[i].x,ty=light[i].y; if ((tx-1<=0 || g[tx-1][ty]) && (ty+1>m || g[tx][ty+1])) ok[i]=true; } int ans=100; int sum; bool flag; for (int sta=0; sta<(1<<tol); sta++) { if (sta==50) { flag=true; } flag=true; sum=0; int tx1,ty1,tx2,ty2; memset(on,0,sizeof on); int num=0; int tp=0; int st=sta; while(st) { on[++num]=st&1; sum+=(st&1); if (on[num]) { if (!ok[num]) tp++; } st>>=1; } if (tp>1) continue; for (int i=1; i<=tol; i++) if (on[i]) { for (int j=0; j<=3; j++) { memset(check,false,sizeof check); flag=true; check[g[light[i].x][light[i].y]]=true; tx1=light[i].x+fx[j][0]; ty1=light[i].y+fy[j][0]; if (tx1<=n && ty1<=m && tx1>0 && ty1>0) { if (!g[tx1][ty1]) continue; check[g[tx1][ty1]]=true; } tx2=light[i].x+fx[j][1]; ty2=light[i].y+fy[j][1]; if (tx2<=n && ty2<=m && tx2>0 && ty2>0) { if (!g[tx2][ty2]) continue; check[g[tx2][ty2]]=true; } for (int k=1; k<=tol; k++) if (k!=i && on[k]) { check[g[light[k].x][light[k].y]]=true; tx1=light[k].x+fx[0][0]; ty1=light[k].y+fy[0][0]; tx2=light[k].x+fx[0][1]; ty2=light[k].y+fy[0][1]; if (tx1<=n && ty1<=m && tx1>0 && ty1>0) { if (!g[tx1][ty1]) { flag=false; break; } check[g[tx1][ty1]]=true; } if (tx2<=n && ty2<=m && tx2>0 && ty2>0) { if (!g[tx2][ty2]) { flag=false; break; } check[g[tx2][ty2]]=true; } } if (!flag) continue; for (int ii=1; ii<=tol; ii++) if (!check[ii]) { flag=false; break; } if (flag) ans=min(ans,sum); } } } if (ans==100) cout<<"-1\n"; else cout<<ans<<endl; } return 0; }