【搜索】难缠的值周生

【问题描述】
小 P 上学总是迟到,迟到了以后常常会被值周生发现。被值周生发现就会给他所在的班级扣分,被扣了分不免要挨班主任的训,这令小P 很不爽。不过,聪明的他经过观察发现,值周生通常会站在固定的位置,并且他们都很笨,只会向
固定的同一个方向看。于是小P 经过潜心研究,把值周生的站位和方向以及学校的地形绘成一张地图,你的任务是编写一个程序,帮助小P 找出一条路从大门到达教室并且不被值周生发现。
【输入文件】
输入文件的第一行是两个整数 N,G,代表学校是一个N × N 的正方形,其中有G 个值周生。
接下来输入一个N × N 的矩阵,代表学校。其中.代表空地,X(大写英文字母)代表墙,E 代表学校的大门,小P 将从这里进入学校,C 代表教室,小P 到达这里就胜利了。数字代表值周生,数字的值代表值周生的编号,显然值周生不
能穿墙透视,但是小P 也不能翻墙或者站到墙上去。
接下来有G 行,每行包含一个数字Gi 和一个字母,代表第Gi 个值周生的朝向。其中N 表示北,S 表示南,E 表示东,W 表示西。显然,如果你撞上值周生(走到值周生所在的格子上),也会被值周生发现。
【输出文件】
输出文件包含任意一个行走方案,每行一个字母,表示小 P 每步走的方向。如果无论小P 怎么走都不能不被值周生发现的走到教室,则输出一行整数-1。
【样例输入】
5 3
..E.1
...XX
.2.X.
.C.X.
...X3
1 E
2 E
3 W
【样例输出】
S
W
W
S
S
E
(注意这只是可能的行走方案之一)
【数据规模】
对于100%的数据,满足0 ≤ G < 10,1 < N ≤ 10。
很标准的搜索,只是要注意人和人的视线可以交叉。
Accode:

#include <cstdio>
#include <cstdlib>
#include <algorithm>

const char fi[] = "guard.in";
const char fo[] = "guard.out";
const int maxN = 20;

char tmp[maxN][maxN];
int mp[maxN][maxN];
int x[maxN], y[maxN];
int n, m, Sx, Sy, Tx, Ty;

void init_file()
{
    freopen(fi, "r", stdin);
    freopen(fo, "w", stdout);
    return;
}

void readdata()
{
    scanf("%d%d\n", &n, &m);
    for (int i = 1; i < n + 1; ++i)
    {
        gets(tmp[i] + 1);
        for (int j = 1; j < n + 1; ++j)
        switch (tmp[i][j])
        {
        case '.': mp[i][j] = 1; break;
        case 'E':
            mp[i][j] = 1;
            Sx = i; Sy = j;
            break;
        case 'C':
            mp[i][j] = 1;
            Tx = i; Ty = j;
            break;
        case 'X': mp[i][j] = 0; break;
        default:
            mp[i][j] = 1;
            x[tmp[i][j] - '0'] = i;
            y[tmp[i][j] - '0'] = j;
            break;
        }
    }
    for (; m; --m)
    {
        int ID; char dir;
        scanf("%d %c", &ID, &dir);
        int i = x[ID], j = y[ID];
        switch (dir)
        {
        case 'E':
            for (; mp[i][j]; ++j)
                mp[i][j] = -1;
            break;
        case 'W':
            for (; mp[i][j]; --j)
                mp[i][j] = -1;
            break;
        case 'N':
            for (; mp[i][j]; --i)
                mp[i][j] = -1;
            break;
        case 'S':
            for (; mp[i][j]; ++i)
                mp[i][j] = -1;
            break;
        }
    }
    return;
}

void print(int tot)
{
    for (int i = 1; i < tot; ++i)
    {
        if (x[i] + 1 == x[i + 1]
            && y[i] == y[i + 1])
            printf("S\n");
        else if (x[i] - 1 == x[i + 1]
                 && y[i] == y[i + 1])
            printf("N\n");
        else if (x[i] == x[i + 1]
                 && y[i] + 1 == y[i + 1])
            printf("E\n");
        else if (x[i] == x[i + 1]
                 && y[i] - 1 == y[i + 1])
            printf("W\n");
    }
    exit(0);
}

void Dfs(int i, int _x, int _y)
{
    x[i] = _x; y[i] = _y;
    if (_x == Tx && _y == Ty)
    {print(i); return;}
    mp[_x][_y] = 0;
    if (mp[_x][_y + 1] > 0)
        Dfs(i + 1, _x, _y + 1);
    if (mp[_x][_y - 1] > 0)
        Dfs(i + 1, _x, _y - 1);
    if (mp[_x + 1][_y] > 0)
        Dfs(i + 1, _x + 1, _y);
    if (mp[_x - 1][_y] > 0)
        Dfs(i + 1, _x - 1, _y);
    x[i] = y[i] = 0;
    mp[_x][_y] = 1;
    return;
}

void work()
{
    if (mp[Sx][Sy] > 0 && mp[Tx][Ty] > 0)
        Dfs(1, Sx, Sy);
    printf("-1\n");
    return;
}

int main()
{
    init_file();
    readdata();
    work();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值