hdu4770Lights Against Dudely 暴力搜索

//n*m grid
//一个灯的照亮区域为(x,y),(x-1,y) ,(x,y+1)
//问最少用多少个灯等可以将'.'区照亮而不会照到‘#’区
//其中有一个灯可以的照亮区域可以旋转0,90,180,270度
//由于题目已知'.'区的个数少于15,可以直接爆搜'.'区是否放灯
//选好哪些区域放灯后枚举,是哪个灯可以旋转,旋转的角度
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 210 ;
char map[maxn][maxn] ;
int vis[maxn][maxn] ;
int x[maxn] , y[maxn] ;
int len_a ,a[maxn];
int ans ;int len ;
int dx[4][3] = {{0,-1,0},{0,0,1},{0,1,0},{0,0,-1}};
int dy[4][3] = {{0,0,1},{0,1,0},{0,0,-1},{0,-1,0}};
bool judge()
{
    int hash[20] ;
    for(int i = 1;i <= len_a ;i++)
    for(int j = 0;j < 4;j++)
    {
         memset(hash , 0 , sizeof(hash)) ;
         int flag = 0 ;
         for(int k = 0;k < 3;k++)
         {
             int u = x[a[i]] + dx[j][k] ;
             int v = y[a[i]] + dy[j][k] ;
             hash[vis[u][v]] =  1 ;
             if(map[u][v] == '#')
             {flag = 1 ; break;}
         }
         if(flag)continue ;
         for(int k = 1;k <= len_a ;k++)
         {
             if(k == i)continue ;
             flag = 0 ;
             for(int s = 0 ;s < 3;s++)
             {
                 int u = x[a[k]] + dx[0][s] ;
                 int v = y[a[k]] + dy[0][s] ;
                 hash[vis[u][v]] = 1;
                 if(map[u][v] == '#')
                 {flag = 1 ; break;}
             }
             if(flag){flag = 1 ;break;}
         }
         if(flag)continue;
         for(int k = 1;k  <= len ;k++)
         if(!hash[k]){flag = 1 ; break;}
         if(!flag)return true ;
    }
    return false ;
}
void dfs(int pos , int num)
{
    if(pos == len + 1 )
    {
        if(judge())
        ans = min(ans , num) ;
        return ;
    }
    dfs(pos + 1, num) ;
    a[++len_a] = pos ;
    dfs(pos+1 , num + 1) ;
    len_a--;
}
int main()
{
    //freopen("in.txt" ,"r" , stdin) ;
    int n , m ;
    while(~scanf("%d%d" ,&n , &m)&&(n+m))
    {
        len = 0;
        memset(vis , 0 , sizeof(vis)) ;
        memset(map , 0 ,sizeof(map)) ;
        for(int i = 1;i <= n;i++)
        {
            scanf("%s" , &map[i][1]) ;
            for(int j = 1;j <= m;j++)
            if(map[i][j] == '.')
            x[++len] = i ,y[len] = j , vis[i][j] = len ;
        }
        if(len == 0){puts("0");continue ;}
       ans = 20;len_a = 0 ;
       dfs(1 ,0);
       if(ans==20)puts("-1") ;
       else
       printf("%d\n" ,ans) ;
    }
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值