uva 321(隐式图搜索)

题意:一个人买了一栋别墅,有r个房间,d条房间通道,l个灯的开关,告诉了哪两个房间是连通的,又有哪些灯的开关在哪个屋子里,这个人要从房间1到房间r,但是他怕黑,如果要进的屋子是黑的就不进去,问给出的条件是否能让他顺利从1到 r并且除r之外所有灯都是灭的(好节约。。),如果可以输出开灯,关灯的移动的步骤。

题解:bfs + hash,每进行一个步骤之后需要记录灯的状态改变,用二进制存贮这个状态,1为灯亮,0为灯灭,刚开始忘记考虑灯的状态是可以重复的,如果在不同的屋子里,所以死循环,然后用了哈希把房间不同的因素也加进去,就成功了。。另外,用了三种不同的标记表示是哪个步骤。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <map>
using namespace std;
const int N = 15;
const int MAX = 800;

struct ST {
	int room, step, lst, step1[MAX], step2[MAX];
}st, st1, ans;
int r, d, s, g[N][N], l[N][N], flag, tar;
queue<ST> q;
map<int, int> m;

void init() {
	memset(g, 0, sizeof(g));
	memset(l, 0, sizeof(l));
	flag = 0;
	tar = 1 << (r - 1);
	while (!q.empty())
		q.pop();
	m.clear();
}

int hash(ST temp) {
	int cnt = temp.lst * 10 + temp.room;//加入房间不同的影响
	if (!m[cnt]) {
		m[cnt] = 1;
		return 1;
	}
	return 0;
}

void bfs() {
	st.room = 1;
	st.step = 0;
	st.lst = 1 << 0;
	m[st.lst] = 1;
	q.push(st);
	while (!q.empty()) {
		st = q.front();
		if (st.lst == tar) {
			flag = 1;
			ans = st;
			return;
		}
		q.pop();
		for (int i = 1; i <= r; i++) {
			if (l[st.room][i] && i != st.room) {
				st1 = st;
				if (st1.lst & (1 << (i - 1))) {
					st1.lst -= 1 << (i - 1);
					st1.step++;
					st1.step1[st1.step] = 2;//关灯
					st1.step2[st1.step] = i;
				}
				else {
					st1.lst += 1 << (i - 1);
					st1.step++;
					st1.step1[st1.step] = 3;//开灯
					st1.step2[st1.step] = i;
				}
	 			if (hash(st1))
					q.push(st1);
			}
			if (g[st.room][i] && (st.lst & (1 << (i - 1)))) {
				st1 = st;
				st1.room = i;
				st1.step++;
				st1.step1[st1.step] = 1;//移动
				st1.step2[st1.step] = i;
				if (hash(st1))
					q.push(st1);
			}
		}
	}
}

int main() {
	int a, b, t = 1;
	while (scanf("%d%d%d", &r, &d, &s) && (r + d + s)) {
		init();
		for (int i = 0; i < d; i++) {
			scanf("%d%d", &a, &b);
			g[a][b] = g[b][a] = 1;
		}
		for (int i = 0; i < s; i++) {
			scanf("%d%d", &a, &b);
			l[a][b] = 1;
		}
		bfs();
		printf("Villa #%d\n", t++);
		if (flag) {
			printf("The problem can be solved in %d steps:\n", ans.step);
			for (int i = 1; i <= ans.step; i++) {
				if (ans.step1[i] == 1)
					printf("- Move to room %d.\n", ans.step2[i]);
				else if (ans.step1[i] == 2)
					printf("- Switch off light in room %d.\n", ans.step2[i]);
				else if (ans.step1[i] == 3)
					printf("- Switch on light in room %d.\n", ans.step2[i]);
			}
		}
		else
			printf("The problem cannot be solved.\n");
		printf("\n");
	}
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值