题目大意:别墅里面有r间房间,d扇门,s个开关,最初的状态是:房间1的灯是开着的,其他的灯都是关着的。现在有一个人在房间1,这个人怕黑,所以要待在一个房间或者要去另一个房间的条件是,这个房间的灯必须是开的,现在给出最终状态,最终状态是:这个人到了房间r,除了房间r的灯是亮的外,其他房间的灯都是灭的,求最少的操作数。(每到另一个房间,或者开关一个房间的灯都是一个操作)

解题思路:因为房间最多只有十个,且每个房间的灯只有两种状态,不是开就是关,所以可以用二进制表示形式将所有房间的状态记录下来,接着进行BFS即可

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 15
#define maxm 60000
struct Status{
	int pos, s, time, pre;
	int beha;
	int des;
};

Status Sta[maxm];
int R, D, S;
int door[maxn][maxn],key[maxn][maxn];
int vis[maxm][maxn],last, end;
bool flag;

int try_insert(int cur) {

	int s = Sta[cur].s;
	int p = Sta[cur].pos;
	if(vis[s][p])
		return false;
	vis[s][p] = 1;
	return true;
}

void BFS() {

	Sta[0].pos = 1;
	Sta[0].s = 2;
	Sta[0].time = 0;
	Sta[0].pre = 0;
	int front = 0, rear = 1;
	while(front < rear) {
		Status &t = Sta[front];
		int p = t.pos;
		int s = t.s;
		int tim = t.time;

		if( p == R && s == last ) {
			end = front;
			flag = true;
			break;	
		}
		
		for(int i = 1; i <= R; i++)
			if(key[p][i] && i != p) {
				int st = s ^ (1 << i);
				Sta[rear].pos = p;
				Sta[rear].s = st;	
				Sta[rear].time = tim + 1; 
				Sta[rear].pre = front; 
				if( (s >> i) % 2 == 0)
					Sta[rear].beha = 1;
				else
					Sta[rear].beha = 3;
				Sta[rear].des = i;
				if(try_insert(rear)) 
					rear++;
			}

		for(int i = 1; i <= R; i++) 
			if( door[p][i] && (s & (1 << i)) ) {
				Sta[rear].pos = i;
				Sta[rear].s = s;
				Sta[rear].time = tim + 1;
				Sta[rear].pre = front;
				Sta[rear].beha = 2;
				Sta[rear].des = i;
				if(try_insert(rear)) 
					rear++;	
			}		
		front++;
	}
}

void print_path(int cur) {
	if(cur == 0)
		return ;
	print_path(Sta[cur].pre);
	if(Sta[cur].beha == 1)
		printf("- Switch on light in room %d.\n",Sta[cur].des);
	if(Sta[cur].beha == 2)
		printf("- Move to room %d.\n",Sta[cur].des);
	if(Sta[cur].beha == 3)
		printf("- Switch off light in room %d.\n",Sta[cur].des);
}

int main() {
	int mark = 1;
	while(scanf("%d%d%d",&R, &D ,&S) != EOF && R + D + S) {
		int t1, t2;
		memset(door,0,sizeof(door));
		memset(key,0,sizeof(key));
		memset(vis,0,sizeof(vis));
		for(int i = 0; i < D; i++) {
			scanf("%d%d",&t1,&t2);
			door[t1][t2] = door[t2][t1] = 1;
		}

		for(int i = 0; i < S; i++) {
			scanf("%d%d",&t1,&t2);
			key[t1][t2] = 1;	
		}
		last = 1 << R;
		flag = false;
		BFS();
		printf("Villa #%d\n",mark++);
		if(flag){
			printf("The problem can be solved in %d steps:\n",Sta[end].time);
			print_path(end);
		}
		else
			printf("The problem cannot be solved.\n");
		printf("\n");
	}
	return 0;
}