uva 10318 - Security Panel(dfs+剪枝)

737 篇文章 0 订阅
232 篇文章 0 订阅
该博客介绍了如何解决 UVA 10318 - Security Panel 问题,这是一个涉及开关关联的逻辑难题。通过深度优先搜索(DFS)策略,结合剪枝技巧,寻找最小操作次数来点亮所有房间的灯。题目中每个开关会影响以它为中心的3*3区域,每个房间只能被操作一次。解题策略是枚举2^25种可能,并判断如果在某一层的上方有未亮灯的房间,那么这个方案就无效。
摘要由CSDN通过智能技术生成

题目链接: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[N][2], cnt[N], vis[N][N], rec[N][N];
char g[N][N];

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[n][0] = i - 1; d[n][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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值