uva 321 The New Villa

题目地址:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=110&page=show_problem&problem=257

题目描述:

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 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.

题意:

有1到r个房间,每个房间有控制其他房间灯的开关(不止一个),要求从初始状态1号房间灯亮其他全灭 人在1号房间,到,目标状态r号房间灯亮 其他全灭 人在r号房间,并且要求人在过程中,人停留的所在的房间必须是亮的。求最短路径及步骤。

题解:

BFS + BKDR hash
同样是初始状态到目标状态,一样是把每个状态当做一个节点。
然后最短路径,广搜初始状态展开,直到展开生成了目标状态或者全部搜索完毕,标志过程结束。
而在判重上用了BKDRhash 做了hash的值的生成,hash的存储上用了白书上八数码问题(p131 ~ p136)标准的head和next数组。
在路径记录上我用了数组来记录,并且定义了几种特殊标志, 供后面解析输出: -i 表示 i号房间关灯 ; i 表示 i号房间开灯 ; i * 100 表示 移动到 i号房间。

代码:

#include<stdio.h>
#include<string.h>
#define MS 1000003
int r,d,s;
bool door_con[100][100]={false};//begin with 1, undirected graph
bool switch_con[100][100]={false};//begin with 1, directed graph
int cases = 0;
typedef struct st
{
    int rooms[15];//0 is light off and 1 is light on,  begin with 1
    int pos;//the people in the room with number
    int ft[100];//footprint,begin with 0;+2 -> switch on 2 room , -2 -> switch off 2 room , 200 -> move to 2 room
    int ft_len;
    st()
    {
        memset(rooms, 0, sizeof(rooms));
        pos = 0;
        memset(ft, 0, sizeof(ft));
        ft_len = 0;
    }
}st, * st_link;
int head[MS], next[MS];
st sq[MS];
int front = 0, rear = 0;
bool is_reached(int cur)
{
    if(sq[cur].pos != r)
        return false;
    for(int i = 1; i <= r - 1; i++)
        if(sq[cur].rooms[i] == 1)//1 ~ r-1 room must be off light
            return false;
    if(sq[cur].rooms[r] == 0)//r room must be on light
        return false;
    return true;
}
int clone_st(int src, int des)
{
    memcpy(sq[src].rooms, sq[des].rooms, sizeof(sq[src].rooms));
    memcpy(sq[src].ft, sq[des].ft, sizeof(sq[src].ft));
    sq[src].pos = sq[des].pos;
    sq[src].ft_len = sq[des].ft_len;
    return 0;
}
int BKDR_hash(st cur)
{
    int seed = 131;
    int hash = 0;
    for (int i = 1; i <= r; i++)
    {
        hash += hash * seed + cur.rooms[i];
    }

    return hash % MS;
}
int sq_cmp(int s1, int s2)
{
    if(sq[s1].pos != sq[s2].pos)
        return 1;
    for(int i = 1; i <= r; i++)
        if(sq[s1].rooms[i] != sq[s2].rooms[i])
            return 1;
    return 0;
}
int try_to_insert(int s)
{
    int h = BKDR_hash(sq[s]);
    int u = head[h];
    while (u)
    {
        if(sq_cmp(u, s) == 0) return 0;
        u = next[u];
    }
    next[s] = head[h];
    head[h] = s;
    return 1;
}
int BFS()
{
    //init the first status
    sq[rear].rooms[1] = 1;
    sq[rear].pos = 1;
    sq[rear].ft_len = 0;
    rear ++;
    while (front < rear)
    {
        //sq[front] is pop father, then generate kinds of children
        if(is_reached(front)) return 1;
        //switch on/off light
        for(int i = 1; i <= r; i++)
        {
            if(switch_con[sq[front].pos][i])
            {
                clone_st(rear, front);
                sq[rear].rooms[i] = sq[rear].rooms[i] ^ 1;// 0 ^ 1 = 1 , 1 ^ 1 = 1. just like switch
                if(sq[rear].rooms[i] == 0 && sq[front].pos == i)//the people at the room which must be on light
                    continue;
                if(try_to_insert(rear))
                {
                    if(sq[rear].rooms[i] == 0) sq[rear].ft[sq[rear].ft_len++] = 0 - i;//record footprint , switch off
                    else sq[rear].ft[sq[rear].ft_len++] = i;//switch on
                    rear++;//push the children to the queue
                }
            }
        }
        //move to room
        for(int i = 1; i <= r; i++)
        {
            if(door_con[sq[front].pos][i] || door_con[i][sq[front].pos])//connected room
            {
                if(sq[front].rooms[i] == 1)//move the room which must be on light
                {
                    clone_st(rear, front);
                    sq[rear].pos = i;//move to the i room
                    if(try_to_insert(rear))
                    {
                        sq[rear].ft[sq[rear].ft_len++] = i * 100;//foot print
                        rear++;
                    }
                }
            }
        }
        front++;//pop the father
    }
    return 0;
}
int print_st(int cur)
{
    printf("The problem can be solved in %d steps:\n", sq[cur].ft_len);
    for(int i = 0; i <= sq[cur].ft_len - 1; i++)
    {
        if(sq[cur].ft[i] < 0)
            printf("- Switch off light in room %d.\n", 0 - sq[cur].ft[i]);
        if(sq[cur].ft[i] > 0 && sq[cur].ft[i] < 100)
            printf("- Switch on light in room %d.\n", sq[cur].ft[i]);
        if(sq[cur].ft[i] >= 100)
            printf("- Move to room %d.\n", sq[cur].ft[i] / 100);
    }
    return 0;
}
int main()
{
    while(scanf("%d%d%d",&r,&d,&s)!=EOF && (r + d + s) > 0)
    {
        memset(door_con, false, sizeof(door_con));
        memset(switch_con, false, sizeof(switch_con));
        memset(head, 0, sizeof(head));
        memset(next, 0, sizeof(next));
        front = rear = 0;
        cases++;
        for(int i = 1; i <= d; i++)
        {
            int indoor = 0, outdoor = 0;
            scanf("%d%d",&indoor, &outdoor);
            door_con[indoor][outdoor] = true;
            door_con[outdoor][indoor] = true;
        }
        for(int i = 1; i <= s; i++)
        {
            int doorn = 0, doorl = 0;
            scanf("%d%d", &doorn, &doorl);
            switch_con[doorn][doorl] = true;
        }
        printf("Villa #%d\n", cases);
        if(BFS() == 1)
            print_st(front);
        else
            printf("The problem cannot be solved.\n");
        printf("\n");
    }
    return(0);
}

猜你喜欢

转载自blog.csdn.net/hackerwin7/article/details/44599375
new