UVa 321 The New Villa ( BFS + 状态压缩判重)

来源:互联网 发布:足球数据分析大师app 编辑:程序博客网 时间:2024/05/16 10:35

题意:有几个房间,从一个房间开始走,进入另一个房间的要求是灯要亮着,而且两个房间之间是连通的。题目会给出房间的控制开关,也就是哪个房间的开关可以控制哪一个房间的开关。输入有房间数,房间的连接数,和开关控制数,要求从走廊开始,走到卧室,而且最后只有卧室的灯是开着的,别的房间的灯都是关着的

那么这道题要注意的是,一个操作是一步,要求输出走到卧室的最少操作,以及操作的顺序

关键在于建图和判重,其他的就是BFS的模板即可

由于要记录操作顺序,所以节点的结构设置也比较重要


 The New Villa 

Mr. Black recently bought a villa in the countryside. Only one thingbothers him: although there are light switches in most rooms, the lightsthey control are often in other rooms than the switches themselves.While his estate agent saw this as a feature, Mr. Black has come tobelieve that the electricians were a bit absent-minded (to putit 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 entera room that had its lights out and would never switch off the lightsof the room he was in.

After some thought, Mr. Black was able to use the incorrectly wiredlight switches to his advantage. He managed to get to his bedroom and toswitch 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 hallwaylight is initially switched on. You may never enter a dark room, and afterthe last move, all lights except for the one in the bedroom mustbe switched off. If there are several paths to the bedroom, you haveto 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 startswith a line containing three integersr,d, and s. r is the number ofrooms in the villa, which will be at most 10.d is the number ofdoors/connections between the rooms ands is the number of light switchesin the villa. The rooms are numbered from 1 tor; room number 1 isthe hallway, room numberr is the bedroom.

This line is followed by d lines containing two integers i andj each,specifying that roomi is connected to room j by a door.Then follows lines containing two integersk and l each,indicating that there is a light switch in roomk that controls thelight in rooml.

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

Output

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

If there is a solution to Mr. Black's problem, output the shortestpossible sequence of steps that leads him to his bedroom and only leavesthe bedroom light switched on. (Output only one shortest sequence if you findmore 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 41 21 33 21 21 32 13 22 1 22 11 11 20 0 0ample Output
Villa #1The 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 #2The problem cannot be solved.
题目如上

那么对于我来说,第一比较困难的是怎么建图,想了很久,也借鉴了一些思路,才想明白,应该是用操作来作为节点,然后开始BFS,那么BFS入队怎么判重呢?朋友给我了一些提示,可以说是很详细的提示了,那就是对每个节点来说,什么是不同的,第一每个节点都有一个状态,就是记录从根节点走到当前节点,每个房间的灯的一系列的变化以及状态,第二每个节点代表在不同的房间,那么也就是说变量就是房间和状态,只要判定queue里面没有这样的节点就可以把它插入队列了

然后,就是这个状态应该怎么表示,要知道,对于每个房间来说,当前房间的灯的状态有两个,关和开,那就就可以用位串来表示一系列的灯的状态,但是就要求每个节点都要带有一个数组,其实这样也可以,但是对于后面的判重来讲,就比较麻烦了。更好的办法就是把表示位串的数组变成一个数,不一样的二进制数表示成十进制数,也是不一样的,所以只是用一个十进制整数来表示每个节点的状态,后面的查看灯的状态的操作可以用位运算来实现

接下来要说的是,我一开始的时候错了,是因为,我用高位来表示序号小的房间,而后面我就忘记了二进制的制约,用低位表示序号小的房间了,这一点要注意,你的房间号和二进制的表示要一致

最后所以下位运算,想判断某一位是1还是0,用&,和谁&呢,就是除了要被判断的那一位,其余的位都是0的这个数来计算,如果计算之后的值为0,那么该位是0,反之是1;如果要改变某一位的值,那么用异或^,和谁^,就是除了要改变的值的那一位是1,剩下的都是0

代码:

#include <cstdio>#include <cstring>#include <queue>#include <string>#include <cmath>#include <iostream>using namespace std;const int Max = 2000;const int N = 15;const int INF = 100000000;struct Node {    int state;    int room;    int fa;    int dist;    int id;    int todo;    string op;}sta[Max*N];bool used[Max][N];int mp[N][N], lin[N][N];int d1, d2, r, d, s, x;string move = "- Move to room ", On = "- Switch on light in room ", off = "- Switch off light in room ";int bfs( ) {    int id = 1, tmp;    queue<Node> q;    sta[id].state = 1<<(r-1), sta[id].room = 1, sta[id].fa = -1, sta[id].dist = 0, sta[id].id = id, sta[id].op.clear();    used[sta[id].state][sta[id].room] = true;    q.push(sta[id++]);      while ( !q.empty() ) {        Node &now = q.front(); q.pop();        //printf("%d %d\n", now.state, now.room);        if ( now.state == 1 && now.room == r ) {            x = now.id;            int step = sta[x].dist;            return step;        }        for ( int i = 1; i <= r; ++i ) {            tmp = 1 << (r-i);            int t1 = now.state & tmp;            //printf("%d\n", t1);            if ( mp[now.room][i] && (now.state & tmp) != 0 ) {              sta[id].state = now.state;              sta[id].dist = now.dist + 1;              sta[id].fa = now.id;              sta[id].op = move;              sta[id].room = i;              sta[id].id = id;              sta[id].todo = i;              if ( !used[sta[id].state][sta[id].room] ) {                used[sta[id].state][sta[id].room] = true;                q.push(sta[id++]);              }            }        }        for ( int i = 1; i <= r; ++i ) {            tmp = 1 << (r-i);            if ( lin[now.room][i] && i != now.room ) {                if ( ( now.state & tmp ) == 0 ) {                    sta[id].op = On;             //printf("%d%d\n", now.state, tmp);                }                else sta[id].op = off;                sta[id].state = now.state ^ tmp;             //cout << now.state << " " << sta[id].state<< endl;                sta[id].room = now.room, sta[id].dist = now.dist+1, sta[id].fa = now.id, sta[id].id = id;                sta[id].todo = i;                if ( !used[sta[id].state][now.room] ) {                    used[sta[id].state][now.room] = true;                    q.push(sta[id++]);                }            }        }    }    return INF;}void print( int num ) {    if ( sta[num].fa == -1 ) return;    print( sta[num].fa );    cout << sta[num].op << sta[num].todo << "." << endl;}int main(){    int icase = 1, start = 1, end;     while ( scanf("%d%d%d", &r, &d, &s) != EOF && ( r||d||s ) ) {        memset( mp, 0, sizeof(mp) );        memset( lin, 0, sizeof(lin) );        memset( used, 0, sizeof(used) );        for ( int i = 0; i < d; ++i ) {            scanf("%d%d", &d1, &d2);            mp[d1][d2] = mp[d2][d1] = 1;        }        for ( int i = 0; i < s; ++i ) {            scanf("%d%d", &d1, &d2);            lin[d1][d2] = 1;        }        int step = bfs();        printf("Villa #%d\n", icase++);        if ( step == INF ) printf("The problem cannot be solved.\n");        else {            printf("The problem can be solved in %d steps:\n", step);            print( x );        }        cout << endl;    }}


原创粉丝点击