【BFS】The New Villa

[poj1137] The New Villa
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 1481   Accepted: 485

Description

Mr. Black recently bought a villa in the countryside. Only one thing bothers him: although there are light switches in most rooms, the lights they control are often in other rooms than the switches themselves. While his estate agent saw this as a feature, Mr. Black has come to believe that the electricians were a bit absent-minded (to put it mildly) when they connected the switches to the outlets. 

One night, Mr. Black came home late. While standing in the hallway, he noted that the lights in all other rooms were switched off. Unfortunately, Mr. Black was afraid of the dark, so he never dared to enter a room that had its lights out and would never switch off the lights of the room he was in. 

After some thought, Mr. Black was able to use the incorrectly wired light switches to his advantage. He managed to get to his bedroom and to switch off all lights except for the one in the bedroom. 

You are to write a program that, given a description of a villa, determines how to get from the hallway to the bedroom if only the hallway light is initially switched on. You may never enter a dark room, and after the last move, all lights except for the one in the bedroom must be switched off. If there are several paths to the bedroom, you have to find the one which uses the smallest number of steps, where "move from one room to another", "switch on a light" and "switch off a light" each count as one step.

Input

The input file contains several villa descriptions. Each villa starts with a line containing three integers r, d, and s. r is the number of rooms in the villa, which will be at most 10. d is the number of doors/connections between the rooms and s is the number of light switches in the villa. The rooms are numbered from 1 to r; room number 1 is the hallway, room number r is the bedroom. 

This line is followed by d lines containing two integers i and j each, specifying that room i is connected to room j by a door. Then follow s lines containing two integers k and l each, indicating that there is a light switch in room k that controls the light in room l. 

A blank line separates the villa description from the next one. The input file ends with a villa having r = d = s = 0, which should not be processed.

Output

For each villa, first output the number of the test case ('Villa #1', 'Villa #2', etc.) in a line of its own. 

If there is a solution to Mr. Black's problem, output the shortest possible sequence of steps that leads him to his bedroom and only leaves the bedroom light switched on. (Output only one shortest sequence if you find more than one.) Adhere to the output format shown in the sample below. 

If there is no solution, output a line containing the statement `The problem cannot be solved.' 

Output a blank line after each test case.

Sample Input

3 3 4
1 2
1 3
3 2
1 2
1 3
2 1
3 2

2 1 2
2 1
1 1
1 2

0 0 0

Sample Output

Villa #1
The problem can be solved in 6 steps:
- Switch on light in room 2.
- Switch on light in room 3.
- Move to room 2.
- Switch off light in room 1.
- Move to room 3.
- Switch off light in room 2.

Villa #2
The problem cannot be solved.

Source

 
题目大意:有R个房间,D道门,S个开关。Mr.Black不愿意去黑的屋里,一开始只有走廊(1号)灯亮着,请问走到卧室(R号)需要多少步(步数=操作数量),输出方案
试题分析:这题需要注意的地方非常的多,我调了1个小时:
               ①注意格式!输出完方案后还有一个换行!
               ②位运算不要写错
               ③注意输出里的"on/off"
               ④如果走廊就是他的卧室 ……
 
               这道题标成就是BFS+位运算+STL(不用也可以),我们发现N<=10,那么我们就可以用二进制数来表示第i号房间的灯亮没亮。而且需要一个vis数组来标记走过的状态(vis[灯开关状态][现在到达的房间数]),以链表的形式输出就好了(这道题没有SPJ,坑了很多人,在输入后一定要排序!)
               
附上一组数据(discuss里的):

输入:

10 31 31
9 7
6 8
8 5
6 10
2 9
7 3
9 1
2 10
1 8
10 9
4 1
7 10
2 6
5 4
10 5
7 5
2 3
6 7
2 8
9 4
4 7
5 1
1 3
9 8
10 8
4 8
3 6
8 7
1 2
5 6
3 9
4 9
7 6
3 6
8 2
2 6
7 3
2 8
3 1
3 7
1 2
2 10
9 10
7 8
5 7
6 10
9 7
4 5
9 3
8 6
5 3
6 7
9 8
6 8
3 2
10 5
1 10
2 7
7 1
6 9
10 7
3 8

0 0 0

输出:

Villa #1
The problem can be solved in 12 steps:
- Switch on light in room 2.
- Move to room 2.
- Switch on light in room 7.
- Switch on light in room 8.
- Switch on light in room 10.
- Move to room 8.
- Switch off light in room 2.
- Move to room 7.
- Switch off light in room 1.
- Switch off light in room 8.
- Move to room 10.
- Switch off light in room 7.

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
//#include<cmath>

using namespace std;
const int INF = 9999999;
#define LL long long

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
int R,D,S;//room door switch
bool vis[10024][13]; 
int a,b;
struct data{
	int seq,st,ro;//状态,步数,现在所在的房间
	bool flag;//0为走路,1为开关灯
	int to;//链表的上一个,前驱
	int turn;//记录当前开关了几号
}Que[100001];
int l=1,r=1;
bool alflag=false;

bool print(data k){
	if(k.to!=-1){//如果不是末尾
		if(!print(Que[k.to])) return 1;//这是防止输出move to 1的
		if(Que[k.to].flag==1){
		   if(Que[k.to].turn>0) printf("- Switch on light in room %d.
",Que[k.to].turn);//注意on与off的区分输出
		   	else printf("- Switch off light in room %d.
",-Que[k.to].turn);
		}
		else{
			printf("- Move to room %d.
",Que[k.to].ro);
		}
		return 1;
	}
	else return 0;
}
vector<int> pat[13];
vector<int> swa[13]; 
int cnt;

void BFS(){
	Que[l].ro=1,Que[l].seq=2,Que[l].st=0;
	Que[l].turn=0;
	Que[l].to=-1;
	if(Que[r].seq==(1<<R)&&Que[r].ro==R){//处理卧室就是走廊的
		alflag=true;
		printf("Villa #%d
",cnt);
		printf("The problem can be solved in %d steps:
",Que[r].st);
	    return ;
	}
	int room,Seq,step;
	while(l<=r){
		step=Que[l].st,Seq=Que[l].seq,room=Que[l].ro;
		for(int i=0;i<pat[room].size();i++){//走到另一个房间
			if(((Seq>>pat[room][i])&1)==1&&!vis[Seq][pat[room][i]]){//如果此房间的灯是亮着的且此状态没有出现过
				vis[Seq][pat[room][i]]=true;//标记此状态出现过
				Que[++r].ro=pat[room][i];
				Que[r].st=step+1;
				Que[r].seq=Seq;
				Que[r].to=l;
				Que[r].flag=0;//flag=0表示走路
				if(Que[r].seq==(1<<R)&&Que[r].ro==R){ 
				    alflag=true;
			    	printf("Villa #%d
",cnt);
					printf("The problem can be solved in %d steps:
",Que[r].st);
					print(Que[r]);
					printf("- Move to room %d.
",Que[r].ro);
					return ;
			    }
			}
		}
		for(int i=0;i<swa[room].size();i++){//开/关灯
			if(!vis[Seq^(1<<swa[room][i])][room]&&swa[room][i]!=room){//如果不是此房间的灯且此状态没有出现过的
				vis[Seq^(1<<swa[room][i])][room]=true;
				Que[++r].ro=room;
				Que[r].st=step+1;
				Que[r].seq=Seq^(1<<swa[room][i]);//更改灯亮的状态
				Que[r].to=l;
				Que[r].flag=1; //flag=1表示开关灯
				if(!((Seq>>swa[room][i])&1)) Que[r].turn=swa[room][i];
				else Que[r].turn=-swa[room][i];//负的代表turn off
				if(Que[r].seq==(1<<R)&&Que[r].ro==R){
					alflag=true;
					printf("Villa #%d
",cnt);
					printf("The problem can be solved in %d steps:
",Que[r].st);
					print(Que[r]);//递归输出
					if(Que[r].turn>0)
		   				printf("- Switch on light in room %d.
",Que[r].turn);
		   			else printf("- Switch off light in room %d.
",-Que[r].turn);
		   			return ;
				}
			}
		}
		l++;//不要忘了这个
	}
}

int main(){
	R=read(),D=read(),S=read();
	while(R!=0||D!=0||S!=0){
		cnt++;
        l=1,r=1;
        for(int i=1;i<=11;i++) pat[i].clear(),swa[i].clear();//注意清空
        memset(vis,0,sizeof(vis));
		for(int i=1;i<=D;i++){
			a=read(),b=read();
			pat[a].push_back(b);//路是双向的,可能走到下一个房间调了一下状态又回来了
			pat[b].push_back(a);
		}
		for(int i=1;i<=R;i++) sort(pat[i].begin(),pat[i].end(),less<int>());//vector排序,因为没有spj
		for(int i=1;i<=S;i++){
			a=read(),b=read();
			swa[a].push_back(b);
		}
		for(int i=1;i<=R;i++) sort(swa[i].begin(),swa[i].end(),less<int>());
		BFS();
		if(!alflag){
			printf("Villa #%d
",cnt);
			puts("The problem cannot be solved.");
		}
		alflag=false;
		printf("
");
		R=read(),D=read(),S=read();
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/wxjor/p/6962079.html