USACO蜗牛漫步(DFS)

蜗牛莎莉喜欢在一个 N×N 的方格矩阵中散步。

她每次都从左上角出发。

方格矩阵中有空地(用 “.” 表示)和障碍(用 “#” 表示)。

下面是一个具体示例:

      A B C D E F G H
    1 S . . . . . # .
    2 . . . . # . . .
    3 . . . . . . . .
    4 . . . . . . . .
    5 . . . . . # . .
    6 # . . . . . . .
    7 . . . . . . . .
    8 . . . . . . . .

莎莉只能沿着水平或垂直方向移动。

在开始时,她位于 A1A1 位置,并选择一个方向(向下或向右)开始移动。

她会一直沿着一个方向移动,直到遇到矩阵边缘或障碍。

这时,她将转向 90 度,继续前进。


她在移动过程中,不能走出矩阵,或走进有障碍的格子中,也不能走到之前
走过的格子中。

当她无法进行任何移动时,行动结束。
以下是上述示例中莎莉的一种行走情况:

          A B C D E F G H
        1 S---------+ # .
        2 . . . . # | . .
        3 . . . . . | . .
        4 . . . . . +---+
        5 . . . . . # . |
        6 # . . . . . . |
        7 +-----------+ |
        8 +-------------+

莎莉沿着右,下,右,下,左,上,右的方向走到了 G7 的位置,此时她无法进行任何移动,行动停止。(前方是她走过的格子,不能进入,并且由于前方不是障碍且没有出界所以也不能转向)

给定具体的方格矩阵,请你帮莎莉找到一个最合理的行进路线,使得她可以经过的格子数量尽可能大。

输出可经过格子最大数量。

输入格式
第一行包含两个整数 N 和 B,分别表示矩阵尺寸以及障碍的数量。

接下来 B 行,每行描述一个障碍的具体位置,用如题面所示的字母和数字表示。

注意,当 N>26 时,输入中不会在 Z 列右侧设计障碍。

输出格式
输出一个整数,表示可经过格子的最大数量。

数据范围
1<N≤120
输入样例:
8 4
E2
A6
G1
F5
输出样例:
33
样例解释
一种最佳行进方式如下:

          A B C D E F G H
        1 S . . . . . # .
        2 | . . . # . . .
        3 | . . . +-----+
        4 | . . . | . . |
        5 +-------+ # . |
        6 # . . . . . . |
        7 +------------ |
        8 +-------------+
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 130;

int n;
int g[N][N];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int ans;

void dfs(int x, int y, int d, int k)
{
    if (!x || x > n || !y || y > n || g[x][y]) return;
    stack<PII> stk;
    while (x && x <= n && y && y <= n && !g[x][y])//沿着这个方向一直走、
    {
        g[x][y] = 2;//走过的点
        stk.push({x, y});
        x += dx[d], y += dy[d];
        k ++ ;
    }
    ans = max(ans, k);
    if (!x || x > n || !y || y > n || g[x][y] == 1)//矩阵边缘或障碍才能转向
    {
        x -= dx[d], y -= dy[d];//退回一步
        for (int i = 0; i < 4; i ++ )
            if ((i + d) % 2)//转90度
                dfs(x + dx[i], y + dy[i], i, k);
    }

    while (stk.size())//回溯
    {
        auto t = stk.top();
        stk.pop();
        g[t.x][t.y] = 0;
    }
}

int main()
{
    int m;
    cin >> n >> m;
    while (m -- )
    {
        char a;
        int b;
        cin >> a >> b;
        a = a - 'A' + 1;
        g[b][a] = 1;
    }
    dfs(1, 1, 1, 0);//第三个是方向
    dfs(1, 1, 2, 0);
    cout << ans << endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值