01迷宫

题目描述

有一个仅由数字0与1组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。
你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。

输入输出格式

输入格式:
输入的第1行为两个正整数n,m。
下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。
接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。

输出格式:
输出包括m行,对于每个询问输出相应答案。

输入输出样例

输入样例#1:
2 2
01
10
1 1
2 2

输出样例#1:
4
4

说明
所有格子互相可达。
对于20%的数据,n≤10;
对于40%的数据,n≤50;
对于50%的数据,m≤5;
对于60%的数据,n≤100,m≤100;
对于100%的数据,n≤1000,m≤100000。
.
.
.
.
.
.
.

分析

由于每次只向四个方向尝试移动,所以可采用深搜。
然而数据规模中,n<=1000,m<=100000,如果每次输入坐标时重新走一次将会超时。
再想想,每一次搜索会找到一个区块,该区块中所有点的答案都相同,所以,答案可以存在一个数组里

题目每给出一个坐标,先判断该坐标是否已有答案(通过前面已给出的点搜索获得的),是则直接输出,否则深搜:先重置pl,为了将该点所属区块都染上色(不能在深搜内部染色,因为过程中并不知道区域内到底有多少连通点),在一趟深搜过程中,每到一个新的点就pl+1,并将该点的坐标存在临时数组里,搜索结束后再依据坐标数组把答案数组的对应位置填上pl。
.
.
.
.
.
.
.
.

程序:
const
x1:array[1..4]of longint=(1,-1,0,0);
y1:array[1..4]of longint=(0,0,1,-1);
var
a,ans:array[0..1001,0..1001]of longint;
x,y:array[0..1000001]of longint;
n,m,pl,i,j:longint;
ch:char;

procedure dfs(p,q:longint);
var
i,u,v:longint;
begin
    inc(pl);
    x[pl]:=p;
    y[pl]:=q;
    ans[p,q]:=1;
    for i:=1 to 4 do
    begin
        u:=p+x1[i];
        v:=q+y1[i];
        if (u<1)or(u>n)or(v<1)or(v>n) then continue;
        if (ans[u,v]>0) then continue;
        if (a[u,v]=a[p,q]) then continue;
        dfs(u,v);
    end;
end;

begin
    fillchar(ans,sizeof(ans),0);
    readln(n,m);
    for i:=1 to n do
    begin
        for j:=1 to n do
        begin
            read(ch);
            a[i,j]:=ord(ch)-ord('0');
        end;
        readln;
    end;
    for i:=1 to m do
    begin
        pl:=0;
        readln(x[i],y[i]);
        if ans[x[i],y[i]]>0 then
        begin
            writeln(ans[x[i],y[i]]);
            continue;
        end;
        dfs(x[i],y[i]);
        for j:=1 to pl do
        ans[x[j],y[j]]:=pl;
        writeln(pl);
    end;
end.
### NOIP P1141 01迷宫 解题报告 #### 题目背景 在一个由 `n` 行 `m` 列组成的矩形网中,每个子要么是 `0` 要么是 `1`。现在有一个机器人位于左上角 `(1, 1)` 的位置,目标是要到达右下角 `(n, m)` 的位置。 #### 题目描述 给定一个 `n × m` 的矩阵,其中 `0` 表示可以通过的路径,`1` 表示障碍物。机器人的移动方式有两种:向右一格或向下一格。求从起点到终点的不同路径数。如果无法到达,则输出 `-1`。 #### 输入式 输入的第一行为两个整数 `n` 和 `m` (1 ≤ n,m ≤ 20),表示地图的高度和宽度;接下来有 `n` 行每行包含 `m` 个字符 `'0'` 或者 `'1'` 描述这个迷宫的地图。 #### 输出式 输出仅一行,即方案总数取模后的结果。如果不存在可行路线则输出 `-1`。 #### 数据范围与提示 对于全部数据,保证起始点和终止点均为可通行区域(`0`)。 #### 思路分析 此问题可以采用深度优先搜索(DFS)+记忆化搜索的方法来解决。通过递归遍历所有可能的状态,并利用缓存保存已经访问过的状态的结果以减少重复计算[^1]。 ```python MOD = int(1e9 + 7) def dfs(x, y, memo, grid): # 边界条件判断 if x >= len(grid) or y >= len(grid[0]) or grid[x][y] == '1': return 0 # 终止条件 if x == len(grid)-1 and y == len(grid[0])-1: return 1 # 记忆化处理 key = f"{x},{y}" if key in memo: return memo[key] ways = 0 # 向右/向下探索新路径 for dx, dy in [(0, 1), (1, 0)]: nx, ny = x + dx, y + dy ways += dfs(nx, ny, memo, grid) memo[key] = ways % MOD return memo[key] if __name__ == "__main__": import sys input_data = [] for line in sys.stdin: input_data.append(line.strip()) rows_cols = list(map(int, input_data[0].split())) matrix = [[char for char in row] for row in input_data[1:]][:rows_cols[0]] result = dfs(0, 0, {}, matrix) print(-1 if not result else result) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值