[ZOJ1301][POJ1137] The New Villa

来源:互联网 发布:网易贵金属行情软件 编辑:程序博客网 时间:2024/06/06 11:01

ZOJ: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1301

POJ: http://poj.org/problem?id=1137


题目大意:
每个房间的开关经常是控制别的房间的灯的。
Mr.Black站在走廊,灯全是熄灭的。Mr.Black怕黑,所以他不敢进入黑的屋子,也不敢关掉他所在屋子的灯。
走廊是亮的,所有屋子是黑的。不准走进黑屋子,且最后到达卧室,卧室以外的灯全灭。找到步骤最小的方式,“房间之间的移动”、“开灯”、“关灯”都算一个步骤。


解题思路:
由求最短步骤和r很小,且灯的状态可以用01表示,想到可以用广搜。

状态最多1024*10种,每种最多有10种移动方式+10种开灯方式+10种关灯方式共30种操作,时间上是允许广搜的。


注意点:

1、写输出部分的时候犹豫了一下,把步骤等于0和1的地方写了step的单数形式,步骤大于1的时候使用step复数形式,结果居然WA掉了。

2、注意操作步骤和短线"-"之间有空格,之后才注意到的,果然还是应该把sample output复制到记事本里看……


源代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <queue>#include <algorithm>using namespace std;#define maxn 15#define maxs 20010#define MOVETO 20#define SWITCHON 10#define SWITCHOFF 0int r;int control[maxs];                      //状态转移i由control[i]得到 int op[maxs];                           //状态i通过op[i]由上一步得到 bool visited[maxs];bool g[maxn][maxn], light[maxn][maxn]; bool init(){    int t1, t2, d, s;    scanf("%d%d%d", &r, &d, &s);    if (r==0) return false;    memset(g, false, sizeof(g));        //g[i][j]==true 表示房间ij之间互通     for (int i=0; i<d; i++)    {        scanf("%d%d", &t1, &t2);        t1--; t2--;        g[t1][t2]=g[t2][t1]=true;    }    memset(light, false, sizeof(light));  //-1: 无控制, i控制light[i]     for (int i=0; i<s; i++)    {        scanf("%d%d", &t1, &t2);        t1--; t2--;        light[t1][t2]=true;    }    return true;}bool checkstay(int u){    int pos=u%16;    int tmp=u/16;    int j=1<<pos;    if (tmp&j) return true;    return false;}int bfs()                               //return -1 or number of steps{    queue<int> q;    queue<int> step;    int target =(1<<(r+4-1))+r-1;    int u=(1<<4), k=0;    int u_new, uu, pos;    memset(visited, 0, sizeof(visited));    memset(control, 255, sizeof(control));        visited[u]=true;    q.push(u);    step.push(k);        while (!q.empty())    {        u=q.front(); q.pop();        k=step.front(); step.pop();        pos=u%16; uu=u>>4;        if (u==target){return k;}                   //状态低4位留给位置         for (int i=0; i<r; i++)                     //move操作        {            if (g[pos][i])                          //可以从pos到房间i            {                u_new=u-pos+i;                if (!visited[u_new] && checkstay(u_new))                {                    q.push(u_new); step.push(k+1); visited[u_new]=true;                    control[u_new]=u;                    op[u_new]=MOVETO+i;                }            }         }        for (int i=0, j=(1<<4); i<r; i++, j=j<<1, uu=uu>>1)   //开关灯操作             if (light[pos][i])            {                if (uu&1)                {                    u_new=u-j;                    if (!visited[u_new] && checkstay(u_new))                    {                        q.push(u_new); step.push(k+1); visited[u_new]=true;                        control[u_new]=u;                        op[u_new]=SWITCHOFF+i;                    }                }                else                {                    u_new=u+j;                    if (!visited[u_new] && checkstay(u_new))                    {                        q.push(u_new); step.push(k+1); visited[u_new]=true;                        control[u_new]=u;                        op[u_new]=SWITCHON+i;                    }                }            }    }    return -1;}void dfsprint(int u){    int u_new;    if (u==(1<<4)) return;    u_new=control[u];    dfsprint(u_new);    if (op[u]>=MOVETO) printf("- Move to room %d.\n", op[u]-MOVETO+1);    else if (op[u]>=SWITCHON) printf("- Switch on light in room %d.\n", op[u]-SWITCHON+1);    else if (op[u]>=SWITCHOFF) printf("- Switch off light in room %d.\n", op[u]-SWITCHOFF+1);}void print(int cs, int steps){    printf("Villa #%d\n", cs);    if (steps==-1)        printf("The problem cannot be solved.\n");    else    {        printf("The problem can be solved in %d steps:\n", steps);        dfsprint((1<<(r+4-1))+r-1);    }    printf("\n");}int main(){    int steps;    for (int cs=1; ;cs++)    {        if (!init()) break;        steps=bfs();        print(cs, steps);    }    return 0;}



原创粉丝点击