Date:January 28th Title: 集训Day1-锻炼身体的路径 题解

本文介绍了一个基于深度优先搜索(DFS)的经典迷宫问题解决方法。该问题要求在一个由空地、高楼和小信家组成的地图中寻找一条长度至少为4的闭合路径。文章详细解释了使用DFS进行路径探索的过程,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xjoi题解:P7268 炼身体的路径

时间:1s 空间:256M

题目描述:

有一个 n×m 的地图,空地为'.',高楼为'#',小信的家在 'S'。

小信想找一条锻炼身体的路径,路径需要从家出发,不经过相同的空地,最后回到家。出于锻炼身体的目的,这条路径的长度必须至少为4,也就是说除了终点和起点都是家以外,经过的不同的空地个数至少为 3

小信想知道这样的路径存不存在。当然,小信无法通过有高楼的地方,所以可能不存在这样的路径。

输入格式:

第一行包含两个整数 n,m

接下来包含一个 n×m 的地图,地图只包含 '.','#','S' 三种字符。

输出格式:

如果存在锻炼身体的路径,输出"Yes",否则输出"No"。

样例1输入:

4 4

....

#.#.

#S#.

....

样例1输出:

Yes

样例2输入:

4 4

.#..

#.#.

#S#.

....

样例2输出:

No

约定:

对于100%的数据,2≤n,m≤1064≤n⋅m≤106

题意:

从点S的位置走,只能往上下左右,判断小信是否能从一条路走出从另外一条路回来。

分析:

典型的走迷宫问题啊!当然用的是dfs,既然是上下左右,所以我们要用一个行动数组表示如何走

int tx[4] = {1, -1, 0, 0};
int ty[4] = {0, 0, -1, 1};

数据范围是个好东西,乍一看(对于100%的数据,2≤n,m≤1064≤n⋅m≤106。),如果开个数组,肯定会超空间,我们也无法用具体的数来开一个数组,所以我们想到要用一个map来存,我们在输入的时候要一边输入一边记录,将高楼记为1,将空地标为0

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            char ch;
            cin >> ch;
            if (ch == 'S') {
                ii = i;
                jj = j;
                mp[ {i, j}] = 1;

            } else if (ch == '#') {
                mp[ {i, j}] = 0;
            } else {
                mp[ {i, j}] = 1;
            }
        }
    }

在dfs的过程中,要开一个step步数变量,step=0并不是结束条件,用一个mp数组来存放迷宫可走的情况,另外用一个数组flag来存放哪些点走过了。每个点用两个数字来描述,一个表示行号,另一个表示列号。对于某一个点(x,y)要试探四个方向,如果没有走过(数组flag相应的点的值为0)且可以走(数组mp相应点的值为'.')同时不越界,就走过去,再看有没有到达终点,到了终点则输出Yes,否则继续走下去,走不通则输出No。

void dfs(int x, int y, int x_end, int y_end, int step = 0) {
    if (x == x_end && y == y_end && step) {
        if (step >= 4) {
            cout << "Yes";
            exit(1);
        } else return;
    }
    if (step && step <= flag[ {x, y}]) {
        return;
    } else {
        flag[ {x, y}] = step;
    }
    for (int i = 0; i < 4; i++) {
        int fx = x + tx[i];
        int fy = y + ty[i];
        if (fx >= 1 && fx <= n && fy >= 1 && fy <= m && mp[ {fx, fy}]) {
            mp[ {fx, fy}] = 0;
            dfs(fx, fy, x_end, y_end, step + 1);
            mp[ {fx, fy}] = 1;
        }
    }
    return;
}

完整代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
int tx[4] = {1, -1, 0, 0};
int ty[4] = {0, 0, -1, 1};
int n, m;
map<pair<int, int>, bool>mp;
map<pair<int, int>, int>flag;
void dfs(int x, int y, int x_end, int y_end, int step = 0) {
    if (x == x_end && y == y_end && step) {
        if (step >= 4) {
            cout << "Yes";
            exit(1);
        } else return;
    }
    if (step && step <= flag[ {x, y}]) {
        return;
    } else {
        flag[ {x, y}] = step;
    }
    for (int i = 0; i < 4; i++) {
        int fx = x + tx[i];
        int fy = y + ty[i];
        if (fx >= 1 && fx <= n && fy >= 1 && fy <= m && mp[ {fx, fy}]) {
            mp[ {fx, fy}] = 0;
            dfs(fx, fy, x_end, y_end, step + 1);
            mp[ {fx, fy}] = 1;
        }
    }
    return;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int ii, jj;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            char ch;
            cin >> ch;
            if (ch == 'S') {
                ii = i;
                jj = j;
                mp[ {i, j}] = 1;

            } else if (ch == '#') {
                mp[ {i, j}] = 0;
            } else {
                mp[ {i, j}] = 1;
            }
        }
    }
    dfs(ii, jj, ii, jj);
    cout << "No";
}

The End

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值