师傅又被妖怪抓走了

来源:互联网 发布:粤语教程软件 编辑:程序博客网 时间:2024/04/28 16:23

师傅又被妖怪抓走了

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述

话说唐僧复得了孙行者,师徒们一心同体,共诣西方。自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便为师傅去化斋,等悟空回来,悟净慌慌张张的对悟空说:“不好了,不好了”,还没等悟净说完,悟空说:“师傅又被妖怪抓走了”,悟净:“NO ,悟空一脸茫然,悟净:“师傅和二师兄都被妖怪抓走了”。悟空(晕!)。为了防止悟空救人,妖怪先把唐憎和八戒分别藏起来,如果悟空在T分钟之后还没找到人,那必定是被妖怪吃掉了。假设悟空在一个nm列的矩阵内,悟空在每一分钟可以走到上,下,左,右的其中的一个可以走的位置,每次只能走一步。我们把发现定义为可以直接看到对方,也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。

输入
有多组测试数据,每组首先是三个正整数n , m (3<=n,m<=100), T,(0<=T<=100) 分别代表行数,列数,规定的时间。接下来n 行,每行 m 个字符。其中’ S ’ 代表悟空的位置,’ D ’代表师傅位置,’ E ’代表八戒的位置。并且保证都只有一个. ’ X ’代表墙 ,’ . ’代表空地 .
输出
每组先输出一行Case c:(c表示当前的组数,从1开始计数);
接下来一行,如果悟空可以在规定时间内找到两人,则输出最少需要的时间,否则输出-1。
样例输入
5 6 3 XXD.......E.....X.....S. ......5 6 3 XDX... ....E. ...... ....S. ...... 5 6 8 XXDX.. .XEX.. ...... ....S. ......
样例输出
Case 1:-1 Case 2:3 Case 3:

-1

思路:

广搜加状态压缩, 借鉴了下大神的思路。。。

#include <stdio.h>#include <string.h>#include <queue>#include <iostream>#define MAX_SIZE 101using namespace std;typedef struct NODE{    int x, y;    int step, st;}Node;char map[MAX_SIZE][MAX_SIZE];     //地图int mark[MAX_SIZE][MAX_SIZE][4], n, m, maxstep, dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};int check(int x, int y)   //判断节点能不能走{    if(map[x][y] == 'D' || map[x][y] == 'E' || map[x][y] == 'X')    {        return 0;    }    else    {        return 1;    }}char modify(char c, int flag)    //给节点做初始化判断,若可以看到D返回d, 看到E返回e, 看到两个人返回y{    if((flag && c == 'd') || (!flag && c == 'e'))    {        return 'y';    }    else    {        return flag ? 'e' : 'd';    }}void init(int x, int y, int flag)     //将地图上D, E的四周的.初始化为y,d,e优化搜索时间{    int i;    for(i = x-1; i >= 0 && check(i, y); i--)    {        map[i][y] = modify(map[i][y], flag);    }    for(i = x+1; i < n && check(i, y); i++)    {        map[i][y] = modify(map[i][y], flag);    }    for(i = y-1; i >= 0 && check(x, i); i--)    {        map[x][i] = modify(map[x][i], flag);    }    for(i = y+1; i < m && check(x, i); i++)    {        map[x][i] = modify(map[x][i], flag);    }}int getMark(char c, int flag)     //队列节点中的标记,d:01,e:10, y:11{    if(c == 'd')    {        flag |= 1;    }    else if(c == 'e')    {        flag |= 2;    }    else if(c == 'y')    {        flag |= 3;    }    return flag;}int bfs(Node sp)     //普通广搜, 注意mark数组是三维的,每种状态都不同,可以来回走{    Node temp, t;    sp.step = 0;    sp.st = getMark(map[sp.x][sp.y], 0);    memset(mark, 0, sizeof(mark));    queue<Node> q;    q.push(sp);    mark[sp.x][sp.y][sp.st] = 1;    while(!q.empty())    {        temp = q.front();        q.pop();        if(temp.st == 3)        {            return temp.step;        }        for(int i = 0; i < 4; i++)        {            t.x = temp.x + dir[i][0];            t.y = temp.y + dir[i][1];            t.step = temp.step + 1;            if(t.x >= 0 && t.x < n && t.y >= 0 && t.y < m && check(t.x, t.y) && !mark[t.x][t.y][temp.st] && t.step <= maxstep)            {                t.st = getMark(map[t.x][t.y], temp.st);                mark[t.x][t.y][t.st] = 1;                q.push(t);            }        }    }    return -1;}int main(){    int i, j, t = 0, ans;    Node sp;    while(scanf("%d%d%d", &n, &m, &maxstep) != EOF)    {        for(i = 0; i < n; i++)        {            for(j = 0; j < m; j++)            {                cin>>map[i][j];                if(map[i][j] == 'S')                {                    sp.x = i;                    sp.y = j;                }            }        }        for(i = 0; i < n; i++)     //预处理地图        {            for(j = 0; j < m; j++)            {                if(map[i][j] == 'D')                {                    init(i, j, 0);                }                else if(map[i][j] == 'E')                {                    init(i, j, 1);                }            }        }        ans = bfs(sp);           //搜索        printf("Case %d:\n%d\n", ++t, ans);    }    return 0;}


0 0