您的位置:首页 > 其它

uva 10318 - Security Panel(dfs+剪枝)

2013-12-21 22:04 302 查看
题目链接:uva 10318 - Security Panel 

题目大意:给出r和l,表示r*l个房间,然后给出开关的关联,3*3,每次按了某个房间的开关,以该房间为中心的周围几个房间会受到影响,‘*’表示被影响到。问说最少按几次开关使得所欲房间灯全部亮起。每个房间的开关只能按一次。

解题思路:dfs,枚举2^25,每次最优考虑不按的,这样只要有一种结果可以满足,即为最少按的次数。另外因为每个房间最多影响周围8个房间,所以一旦x-2层有灯未亮,则说明该方案不可行。

#include <stdio.h>
#include <string.h>

const int N = 10;

int r, c, n, d
[2], cnt
, vis

, rec

;
char g

;

void init() {
n = 0;
memset(cnt, 0, sizeof(cnt));
memset(vis, 0, sizeof(vis));
memset(rec, 0, sizeof(rec));

for (int i = 0; i < 3; i++) {
scanf("%s", g[i]);
for (int j = 0; j < 3; j++) if (g[i][j] == '*') {
d
[0] = i - 1; d
[1] = j - 1;
n++;
}
}
}

void put() {
int p = 0, path[50];
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++) if (rec[i][j]) {
path[p++] = i * c + j + 1;
}
for (int i = 0; i < p - 1; i++) printf("%d ", path[i]);
printf("%d\n" , path[p-1]);
}

void clear(int x, int y) {
for (int i = 0; i < n; i++) {
int p = x + d[i][0], q = y + d[i][1];
if (p < 0 || p >= r || q < 0 || q >= c) continue;
if (vis[p][q]) cnt[p]--;
else cnt[p]++;
vis[p][q] = vis[p][q] ? 0 : 1;
}
}

bool dfs(int x, int y) {
if (y == c) {
x += 1; y = 0;
if (x >= 2 && cnt[x - 2] != c) return false;
}

if (x == r) {
if (cnt[x - 1] != c) return false;
put();
return true;
}

if (dfs(x, y + 1)) return true;

rec[x][y] = 1; clear(x, y);
if (dfs(x, y + 1)) return true;
rec[x][y] = 0; clear(x, y);

return false;
}

int main () {
int cas = 1;
while (scanf("%d%d", &r, &c) == 2 && r + c) {
init();
printf("Case #%d\n", cas++);
if (!dfs(0, 0)) printf("Impossible.\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: