uva 321 The New Villa(隐式图搜索)

737 篇文章 0 订阅

 The New Villa 

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 rd, and sr 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.
题目大意:一个2B青年赚钱了于是乐呵呵地跑去买了一栋别墅,结果却发现这栋别墅的电灯电路都接错了,每个房间里的电灯开关控制的不是这个房间的电灯,而是另一个房间的电灯~~ 2B青年很生气,后果很严重,于是严重谴责了装修工人。

一天晚上2B青年回到家里,站在大厅,发现除了大厅其它房间的电灯全部都是灭的。2B青年很怕黑,不敢走进没开灯的房间。所以问题来了,他该怎样从大厅走到自己的卧室?

2B青年还是很聪明的,他发现正好可以利用电灯开关接错而把另一个房间的电灯打开,然后就可以走进开了灯的那个房间(2B青年不会穿墙术 ,所以这两个房间当然必须是相邻的并且有门的)。

2B青年也是个很节约用电的好青年,所以当他走到卧室时,要求其它房间都必须把灭掉。

现在是你大显身手的时候,编写一个程序帮2B青年找出一个步骤最少的方案并且输出。 开灯,关灯,走进另一个房间都算是一个步骤。如果找不出方案的话,2B青年今晚就得睡大厅沙发了。。。

解题思路:BFS,无非移动,开灯,关灯 , 将2每个房间连接的门和灯用邻接表直接储存起来,bfs的时候只要分别考虑就可以了。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;

const int MAXN = 20;
const int N = 20005;
int nRoom, nDoor, nOpen;
int inDoor[MAXN][MAXN], sonDoor[MAXN];
int inOpen[MAXN][MAXN], sonOpen[MAXN];

struct Move {
    int room[MAXN];
    int order[400][2];
    int cnt;
}aid, que[N];
int dis[N];
const int begin[MAXN] = {0, 2, 0};
int end[MAXN];
int head[N], next[N];

void inInit() {
    memset(dis, 0, sizeof(dis));
    memset(que, 0, sizeof(que));
    memset(end, 0, sizeof(end));
    memset(head, 0, sizeof(head));
    memset(next, 0, sizeof(next));
    end[nRoom] = 2;
}

int hash(Move& s) {
    int sum = 0;
    for (int i = 1; i <= nRoom; i++)
        sum = sum * 5 + s.room[i];
    return sum % N;
}

bool tryInsert(Move& s, int cur) {
    int h = hash(s);
    int u = head[h];
    
    while (u) {
        if (memcmp(que[u].room, s.room, sizeof(s.room)) == 0)
            return false;
        u = next[u];
    }
    next[cur] = head[h];
    head[h] = cur;
    return true;
}

int bfs() {
    inInit();
    memcpy(que[1].room, begin, sizeof(begin));
    int front = 1, rear = 2;
    
    while (front < rear) {
        Move& now = que[front];
        
        if (memcmp(now.room, end, sizeof(end)) == 0) {
            aid = now;
            return now.cnt;
        }
        int x;
        for (x = 1; x < nRoom; x++)
            if (now.room[x] == 2)
                break;
        for (int i = 0; i < sonDoor[x]; i++) {
            if (now.room[inDoor[x][i]] == 1) {
                Move net = now;
                net.room[x] = 1;
                net.room[inDoor[x][i]] = 2;
                if (tryInsert(net, rear)) {
                    net.order[net.cnt][0] = 1;
                    net.order[net.cnt][1] = inDoor[x][i];
                    net.cnt++;
                    que[rear++] = net;
                }
            }
        }
        
        for (int i = 0; i < sonOpen[x]; i++) {
            Move net = now;
            net.room[inOpen[x][i]] = net.room[inOpen[x][i]]?0:1;
            if (tryInsert(net, rear)) {
                net.order[net.cnt][0] = net.room[inOpen[x][i]]?3:2;
                net.order[net.cnt][1] = inOpen[x][i];
                net.cnt++;
                if (memcmp(net.room, end, sizeof(end)) == 0) {
                    aid = net;
                    return net.cnt;
                }
                que[rear++] = net;
            }
        }
        front++;
    }
    return -1;
}

int main() {
    int a, b, cas = 1;
    while (scanf("%d%d%d", &nRoom, &nDoor, &nOpen), nRoom + nDoor + nOpen) {
        // Init;
        memset(sonDoor, 0, sizeof(sonDoor));
        memset(sonOpen, 0, sizeof(sonOpen));
        memset(inDoor, 0, sizeof(inDoor));
        memset(inOpen, 0, sizeof(inOpen));
        
        // Read;
        for (int i = 0; i < nDoor; i++) {
            scanf("%d%d", &a, &b);
            inDoor[a][sonDoor[a]++] = b;
            inDoor[b][sonDoor[b]++] = a;
        }
        for (int i = 1; i <= nOpen; i++) {
            scanf("%d%d", &a, &b);
            inOpen[a][sonOpen[a]++] = b;
        }


	for (int i = 1; i <= nRoom; i++) {
	    sort(inDoor[i], inDoor[i] + sonDoor[i]);
	    sort(inOpen[i], inOpen[i] + sonOpen[i]);
	}
	int flag = bfs();

	printf("Villa #%d\n", cas++);
	if (flag >= 0) {
	    printf("The problem can be solved in %d steps:\n", flag);
	    for (int i = 0; i < aid.cnt; i++) {
		if (aid.order[i][0] == 3)
		    printf("- Switch on light in room %d.\n", aid.order[i][1]);
		else if (aid.order[i][0] == 2)
		    printf("- Switch off light in room %d.\n", aid.order[i][1]);
		else
		    printf("- Move to room %d.\n", aid.order[i][1]);
	    }
	}
	else
	    printf("The problem cannot be solved.\n");
	printf("\n");
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值