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}, {0, -1}, {1, 0} }

    同一个房间不可以装两栈灯,灯光不能照射坚固的房间,问说最少需要多少栈灯。

解题思路:dfs+剪枝,暴力枚举放特殊灯的位置,然后将脆弱房间按照i坐标大放前面,相等的将j坐标小的方前面,这样做是为了dfs的时候剪枝,只要碰到一个房间不能放就返回。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 200;
const int maxv = 20;
const int INF = 0x3f3f3f3f;
const int dir[4][3][2] = { { {0, 0}, {-1, 0}, {0, 1} },
                           { {0, 0}, {0, 1}, {1, 0} },
                           { {0, 0}, {-1, 0}, {0, -1} },
                           { {0, 0}, {0, -1}, {1, 0} }
                        };

int ans;
int n, N, M, x[maxv], y[maxv], c[maxv];
int v[maxn+5][maxn+5];
char g[maxn+5][maxn+5];

inline int judge (int xi, int yi, const int d[3][2]) {

    for (int i = 0; i < 3; i++) {
        int p = xi + d[i][0];
        int q = yi + d[i][1];

        if (p <= 0 || p > N)
            continue;

        if (q <= 0 || q > M)
            continue;

        if (g[p][q] == ‘#‘)
            return 0;
    }
    return 1;
}

inline void set (int xi, int yi, const int d[3][2], int type) {
    for (int i = 0; i < 3; i++) {
        int p = xi + d[i][0];
        int q = yi + d[i][1];

        if (p <= 0 || p > N)
            continue;

        if (q <= 0 || q > M)
            continue;

        v[p][q] = type;
    }
}

void init () {
    n = 0;
    for (int i = 1; i <= N; i++)
        scanf("%s", g[i] + 1);

    for (int i = N; i; i--) {
        for (int j = 1; j <= M; j++) {
            if (g[i][j] == ‘.‘) {
                x[n] = i;
                y[n] = j;
                n++;
            }
        }
    }

    memset(c, 0, sizeof(c));
    for (int i = 0; i < n; i++)
        c[i] = judge(x[i], y[i], dir[0]);
}

/*
   int solve (int spi, int id) {

   memset(v, 0, sizeof(v));
   int ans = INF;
   for (int s = 0; s < (1<<n); s++) {

   bool flag = true;
   for (int i = 0; i < n; i++) {
   if (s&(1<<i) && (c[i] == 0 || i == spi)) {
   flag = false;
   break;
   }
   }

   if (flag) {
   int light = 0;
   int tmp = set(x[spi], y[spi], dir[id], 1);

   for (int i = 0; i < n; i++) {
   if (s&(1<<i)) {
   light++;
   tmp += set(x[i], y[i], dir[0], 1);
   }
   }

   if (tmp == n)
   ans = min(ans, light);

   memset(v, 0, sizeof(v));
   }
   }
   return ans+1;
   }
   */

void dfs (int d, int f, int cnt) {

    if (cnt >= ans)
        return;

    if (d == n) {
        ans = cnt;
        return;
    }

    if (v[x[d]][y[d]])
        dfs (d + 1, f, cnt);

    if (c[d] && d != f) {
        set(x[d], y[d], dir[0], 1);
        dfs (d + 1, f, cnt+1);
        set(x[d], y[d], dir[0], 0);
    }
}

int main () {
    while (scanf("%d%d", &N, &M) == 2 && N + M) {
        init();

        ans = INF;
        if (n == 0)
            ans = 0;

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 4; j++) {
                if (judge (x[i], y[i], dir[j])) {
                    memset(v, 0, sizeof(v));

                    set(x[i], y[i], dir[j], 1);

                    dfs(0, i, 1);

                    set(x[i], y[i], dir[j], 0);
                }
            }
        }

        if (ans == INF)
            printf("-1\n");
        else
            printf("%d\n", ans);
    }
    return 0;
}

hdu 4770 Lights Against Dudely(回溯)

时间: 2024-10-11 22:49:59

hdu 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 暴力枚举+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

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

hdu 4770 Lights Against Dudely 暴力搜索

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

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

题目传送门 题意:有n*m的房间,'.'表示可以被点亮,'#'表示不能被点亮,每点亮一个房间会使旁边的房间也点亮,有意盏特别的灯可以选择周围不同方向的房间点亮.问最少需要多少灯使得所有房间点亮 分析:需要被点亮的房间最多只有15个,所以考虑状压,然后暴力枚举选择哪一个当作特殊灯和枚举选择哪个方向使旁边的房间亮,注意清空vis数组需要优化,memset超时.上交6分钟1Y,Orz... /************************************************ * Auth

hdu4770:Lights Against Dudely(回溯 + 减枝)

题目:hdu4770:Lights Against Dudely 题目大意:同样是n*m的矩阵代表room,房间同样也有脆弱和坚固之分,现在要求要保护脆弱的房间,需要将每个脆弱的房间都照亮,但是坚固的房间不允许照到灯.灯是成L形的,即在x,y上有一盏灯,那么(x - 1, y)和(x, y + 1)就可以被照亮,当然包括(x,y).题目又提供了一盏特殊的灯,它可以该改变方向,但是只有一盏,可以用也可以不用.一个房间最多一盏灯.问要将这些脆弱的房间都照亮最少需要多少盏灯. 解题思路:题目有说脆弱的

HDU 4770 状压暴力枚举

Lights Against Dudely Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1415    Accepted Submission(s): 412 Problem Description Harry: "But Hagrid. How am I going to pay for all of this? I haven't

hdu 4770 13 杭州 现场 A - Lights Against Dudely 暴力 bfs

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 Hagrid

[HDU 1016]--Prime Ring Problem(回溯)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016 Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2