hdu 4770 Lights Against Dudely(回溯)

时间:2023-03-08 16:28:22

pid=4770" target="_blank" style="">题目链接: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;
}