题意:一个人买了一栋别墅,有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;
}