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

题目链接:

由题中最多只有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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值