HDU 4770 Lights Against Dudely(枚举子集,简单模拟)

来源:互联网 发布:python cgi 编辑:程序博客网 时间:2024/06/07 11:59

题目链接:

由题中最多只有15个需要点亮的灯可知,暴力法可行。。。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=205, maxr=20 ,INF=(int)1e9 ,EPS = 100;char mp[maxn][maxn];int N,M;int light[maxr] , d[maxr] ;int dx[4][2] = {{-1,0}, {0,1}, {1,0},  {0,-1}};int dy[4][2] = {{0,1} , {1,0}, {0,-1}, {-1,0}};struct ROOM{    int x[maxr],y[maxr];    int RN;    void Init() { RN = 0 ;}    void add_room(int a,int b) {        x[RN] = a , y[RN] = b , RN++;    }    int room_num(int a,int b){        for(int i=0;i<RN;i++)            if(x[i]==a && y[i]==b) return i;        return -1;    }}R;int bitcount(int x){    int cnt=0;    while(x) cnt+=x&1 , x>>=1;    return cnt;}bool InMap(int x,int y){    return x>=0 && x<N && y>=0 && y<=M ;}bool Dangrous(int t){    for(int i=0 ; i<2 ; i++){        int x = R.x[t] + dx[d[t]][i] , y = R.y[t] + dy[d[t]][i];        if(!InMap(x,y)) continue;        if(mp[x][y] == '#') return true;    }    return false;}bool AllLighted(){    for(int t=0 ; t<R.RN ; t++){        if(light[t]==0) return false;        if(light[t]>=EPS && Dangrous(t)) return false;    }    return true;}void TurnOn(int u){    for(int i=0; i<2; i++){        int x = R.x[u] + dx[d[u]][i] , y = R.y[u] + dy[d[u]][i];        int tmp = R.room_num(x,y);        if(tmp != -1) light[tmp]++;    }}void TurnOff(int u){    for(int i=0; i<2; i++){        int x = R.x[u] + dx[d[u]][i] , y = R.y[u] + dy[d[u]][i];        int tmp = R.room_num(x,y);        if(tmp != -1) light[tmp]--;    }}bool check(int S){    memset(d,0,sizeof(d));    memset(light,0,sizeof(light));    for(int t=0; t<R.RN; t++) if(S&(1<<t)) {        light[t] += 100;        TurnOn(t);    }    if(AllLighted()) return true;    for(int t=0; t<R.RN; t++) if(S&(1<<t)) {        for(int i=0; i<4; i++){            TurnOff(t) , d[t] = i ,TurnOn(t);            if(AllLighted()) return true;            TurnOff(t) , d[t]=0 , TurnOn(t);        }    }    return false;}int main(){    while(scanf("%d%d",&N,&M)!=EOF && N+M){        R.Init();        for(int i=0 ; i<N; i++){            scanf("%s",mp[i]);            for(int j=0; j<M; j++) if(mp[i][j]=='.') {                R.add_room(i,j) ;            }        }        int ans=  INF;        if(R.RN==0) {puts("0"); continue; }        int tt;        for(int S=0 ; S<(1<<R.RN) ; S++){            if((tt=bitcount(S)) >= ans || !check(S)) continue;            ans = tt;        }        if(ans>=INF) ans=-1;        printf("%d\n",ans);    }    return 0;}