状态压缩 + 暴力 HDOJ 4770 Lights Against Dudely

题目传送门

题意:有n*m的房间,‘.‘表示可以被点亮,‘#‘表示不能被点亮,每点亮一个房间会使旁边的房间也点亮,有意盏特别的灯可以选择周围不同方向的房间点亮。问最少需要多少灯使得所有房间点亮

分析:需要被点亮的房间最多只有15个,所以考虑状压,然后暴力枚举选择哪一个当作特殊灯和枚举选择哪个方向使旁边的房间亮,注意清空vis数组需要优化,memset超时。上交6分钟1Y,Orz。。。

/************************************************
 * Author        :Running_Time
 * Created Time  :2015/10/22 星期四 18:25:25
 * File Name     :A.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
char room[N][N];
struct Point    {
    int x, y;
    Point (int x, int y) : x (x), y (y) {}
};
int n, m;
bool vis[N][N];

void back_nomal(int x, int y)   {
    vis[x][y] = false;
    if (x - 1 >= 1) vis[x-1][y] = false;
    if (y + 1 <= m) vis[x][y+1] = false;
}

void back_special(int x, int y, int type) {
    if (type == 1)  {
        back_nomal (x, y);  return ;
    }
    else if (type == 2)  {
        if (x + 1 <= n) {
            vis[x+1][y] = false;
        }
        if (y + 1 <= m) {
            vis[x][y+1] = false;
        }
    }
    else if (type == 3) {
        if (x + 1 <= n) {
            vis[x+1][y] = false;
        }
        if (y - 1 >= 1) {
            vis[x][y-1] = false;
        }
    }
    else if (type == 4) {
        if (x - 1 >= 1) {
            vis[x-1][y] = false;
        }
        if (y - 1 >= 1) {
            vis[x][y-1] = false;
        }
    }
    vis[x][y] = false;
}

bool light_nomal(int x, int y)  {
    if (x - 1 >= 1 && room[x-1][y] != ‘.‘)  return false;
    if (y + 1 <= m && room[x][y+1] != ‘.‘)  return false;
    if (x - 1 >= 1) {
        vis[x-1][y] = true;
    }
    if (y + 1 <= m) {
        vis[x][y+1] = true;
    }
    vis[x][y] = true;
    return true;
}

bool light_special(int x, int y, int type)    {
    if (type == 1)  {
        return light_nomal (x, y);
    }
    else if (type == 2)  {
        if (x + 1 <= n && room[x+1][y] != ‘.‘)  return false;
        if (y + 1 <= m && room[x][y+1] != ‘.‘)  return false;
        if (x + 1 <= n) {
            vis[x+1][y] = true;
        }
        if (y + 1 <= m) {
            vis[x][y+1] = true;
        }
    }
    else if (type == 3) {
        if (x + 1 <= n && room[x+1][y] != ‘.‘)  return false;
        if (y - 1 >= 1 && room[x][y-1] != ‘.‘)  return false;
        if (x + 1 <= n) {
            vis[x+1][y] = true;
        }
        if (y - 1 >= 1) {
            vis[x][y-1] = true;
        }
    }
    else if (type == 4) {
        if (x - 1 >= 1 && room[x-1][y] != ‘.‘)  return false;
        if (y - 1 >= 1 && room[x][y-1] != ‘.‘)  return false;
        if (x - 1 >= 1) {
            vis[x-1][y] = true;
        }
        if (y - 1 >= 1) {
            vis[x][y-1] = true;
        }
    }
    vis[x][y] = true;
    return true;
}

int main(void)    {
    while (scanf ("%d%d", &n, &m) == 2) {
        if (!n && !m)   break;
        for (int i=1; i<=n; ++i)    {
            scanf ("%s", room[i] + 1);
        }
        int cnt = 0;
        memset (vis, false, sizeof (vis));
        vector<Point> V;
        for (int i=1; i<=n; ++i)    {
            for (int j=1; j<=m; ++j)    {
                if (room[i][j] == ‘.‘)  {
                    cnt++;
                    V.push_back (Point (i, j));
                }
            }
        }
        if (cnt == 0)   {
            puts ("0"); continue;
        }
        int tot = 1 << cnt;
        int ans = INF;
        for (int i=0; i<tot; ++i) {
            for (int k=0; k<cnt; ++k)   {
                for (int l=1; l<=4; ++l)    {
                    bool ok = true;
                    for (int j=0; j<cnt; ++j)   {
                        if (i & (1 << j))   {
                            if (j == k) {
                                if (!light_special (V[j].x, V[j].y, l))    {
                                    ok = false; break;
                                }
                            }
                            else    {
                                if (!light_nomal (V[j].x, V[j].y))  {
                                    ok = false; break;
                                }
                            }
                        }
                    }
                    if (!ok)    {
                        for (int j=0; j<cnt; ++j)   {
                            if (j == k) back_special (V[j].x, V[j].y, l);
                            else    back_nomal (V[j].x, V[j].y);
                        }
                        continue;
                    }
                    bool flag = true;
                    for (int j=0; j<cnt; ++j)   {
                        int x = V[j].x, y = V[j].y;
                        if (!vis[x][y]) {
                            flag = false;   break;
                        }
                    }
                    if (flag)   {
                        ans = min (ans, __builtin_popcount (i));
                    }
                    for (int j=0; j<cnt; ++j)   {
                        if (j == k) back_special (V[j].x, V[j].y, l);
                        else    back_nomal (V[j].x, V[j].y);
                    }
                }
            }
        }
        printf ("%d\n", ans == INF ? -1 : ans);
    }

    return 0;
}

  

时间: 2024-11-06 18:28:46

状态压缩 + 暴力 HDOJ 4770 Lights Against Dudely的相关文章

HDU 4770 Lights Against Dudely(暴力)

HDU 4770 Lights Against Dudely 题目链接 题意:给定灯,有一盏灯可以旋转,问最少几个灯可以照亮.的位置,并且不能照到# 思路:暴力求解,先枚举特殊的灯,再枚举正常的灯,要加剪枝,不然会TLE 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N =

hdu 4770 Lights Against Dudely(回溯)

题目链接:hdu 4770 Lights Against Dudely 题目大意:在一个N*M的银行里,有N*M个房间,'#'代表坚固的房间,'.'代表的是脆弱的房间,脆弱的房间个数不会超过15个,现在为了确保安全,要在若干个脆弱的房间上装灯,普通的灯是照亮{0, 0}, {-1, 0}, {0, 1}(和题目中坐标有点出入),然后可以装一个特殊的,可以照射 { {0, 0}, {0, 1}, {1, 0} }, { {0, 0}, {-1, 0}, {0, -1} }, { {0, 0}, {

HDU 1557 权利指数 状态压缩 暴力

HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意: 中文题,不解释. 分析: 枚举所有集合,计算集合中的和,判断集合里面的团体是否为关键团队. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: 1557.cpp * Create Date: 2014-06-28 14:47:58 * Descripton: brute force/ set */ #include <cstdio&g

HDU 4770 Lights Against Dudely 暴力枚举+dfs

又一发吐血ac,,,再次明白了用函数(代码重用)和思路清晰的重要性. 11779687 2014-10-02 20:57:53 Accepted 4770 0MS 496K 2976 B G++ czy Lights Against Dudely Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1360    Accepted Subm

hdu 4770 Lights Against Dudely 暴力搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4770 题目大意是让你放一些灯照亮一些房间 灯不可以照到某些特殊房间 但可以照出边界 灯光必须覆盖所有可以放灯的房间 求至少需要多少灯 搜索题 应该注意到冗长而无聊的题面中有告诉你最多只有15个可以放灯的房间 所以2^15来枚举 还应该注意到冗长而无聊的题面中有告诉你最多只有1个灯可以转向 所以还应该枚举哪个灯来转向 转向再枚举4个方向 然后判断是否成立 为了简化问题 单独把那些可放灯空间拿出来 最多

HDU 4770 Lights Against Dudely

Problem Description Harry: "But Hagrid. How am I going to pay for all of this? I haven't any money." Hagrid: "Well there's your money, Harry! Gringotts, the wizard bank! Ain't no safer place. Not one. Except perhaps Hogwarts." - Rubeus

CSU1611: Concatenation(状态压缩)

Description Zuosige always has bad luck. Recently, he is in hospital because of pneumonia. While he is taking his injection, he feels extremely bored. However, clever Zuosige comes up with a new game. Zuosige writes some of his favorite strings on pa

POJ1753 状态压缩(+BFS) + 棋盘问题

0 棋盘问题,改变一个子的颜色,这个子以及这个子周围的四个位置(左右上下)的子分别变色,求最少的改变次数. 此类题大部分应该可以用状态压缩+暴力搜索解决.纯粹找规律不太合理. 1)第一种方法,状态压缩后BFS暴力搜索.因为棋盘很小,只有16个格子,枚举所有的状态共有2^16=65536种.所以有可以用int数组存储65535个状态用以确认哪一个出现了哪一个没出现,然后暴力枚举+BFS的搜索方式. 2)第二种,或者不进行状态压缩,直接按顺序,确定改变次数为1.改变次数为2...改变次数为16,在每

hdoj 5125 Little Zu Chongzhi&#39;s Triangles【状态压缩dp】

题目:hdoj 5125 Little Zu Chongzhi's Triangles 题意:给出n个木棍的长度,然后问这些木棍所能组成三角形的最大面积. 分析:这个题目用状态压缩解,因为木棍的最大个数为12 我们枚举所有状态,用状态对应位的 0 和 1 表示这个木棍是否选择,然后如果某个状态选择的木棍是3的话,判断是否可以组成,可以的话dp[st] = 三角形面积 然后大于三的,分解之后得出转移方程dp[st] = max(dp[st],dp[i] + dp[st - i]) (i | (st