1. 程式人生 > >【BFS】The New Villa

【BFS】The New Villa

ron ads long long 清空 long new term state swa

[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

Southwestern European Regional Contest 1996 題目大意:有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.\n",Que[k.to].turn);//註意on與off的區分輸出
		   	else printf("- Switch off light in room %d.\n",-Que[k.to].turn);
		}
		else{
			printf("- Move to room %d.\n",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\n",cnt);
		printf("The problem can be solved in %d steps:\n",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\n",cnt);
					printf("The problem can be solved in %d steps:\n",Que[r].st);
					print(Que[r]);
					printf("- Move to room %d.\n",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\n",cnt);
					printf("The problem can be solved in %d steps:\n",Que[r].st);
					print(Que[r]);//遞歸輸出
					if(Que[r].turn>0)
		   				printf("- Switch on light in room %d.\n",Que[r].turn);
		   			else printf("- Switch off light in room %d.\n",-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\n",cnt);
			puts("The problem cannot be solved.");
		}
		alflag=false;
		printf("\n");
		R=read(),D=read(),S=read();
	}
	return 0;
}

  

【BFS】The New Villa