P1958 上学路线 题解

· · 题解

P1958 上学路线

考虑用 DFS 解开。

核心变量

int a,b;
int vis[M][M];
int n;
int X,Y;
int nxt[5][3]={{1,0},{0,1}};
int tot;
$vis$ 表示走过的路的记录。 $N$ 表示有 $N$ 个路口在维修。 $X$,$Y$ 表示路口位置。 ``` int nxt[5][3]={{1,0},{0,1}}; ``` 方向数组,代表东和北。 $tot$用来记录路径条数。 #### 深搜代码 注意事项: > 走过的路不能走 > > 不能走到施工区域 > > 不能越界 --- 接着就可以按照思路写下以下代码。 ``` void dfs(int x,int y) { if(x==a&&y==b){ tot++; return; } for(int i=0; i<2; i++){ int nx=nxt[i][0]+x,ny=nxt[i][1]+y; if(vis[nx][ny]||nx<1||nx>a||ny<1||ny>b) continue; else{ vis[nx][ny]=1; dfs(nx,ny); vis[nx][ny]=0; } } } ``` --- #### 主函数部分代码 ``` cin>>a>>b>>n; while(n--){ cin>>X>>Y; vis[X][Y]=1; } vis[1][1]=1; dfs(1,1); cout<<tot; ``` 输入,标记,输出。 --- #### 完整代码(带注释) ``` #include <bits/stdc++.h> #define int long long #define ll ((i)*2) #define rr ((i)*2+1) using namespace std; const int M=1e2+10; const int mod=1e9+7; int a,b; //表示有 a 条南北方向的街道和 b 条东西方向的街道 int vis[M][M]; //标记数组,标记走过的路或者施工路口 int n; //表示有 N 个路口在维修 int X,Y; //表示路口位置 int nxt[5][3]={{1,0},{0,1}}; //方向数组 int tot; //路径条数 void dfs(int x,int y) // x 坐标,y 坐标 { if(x==a&&y==b){ //当 (x,y) == (a,b),路径条数 +1 , return tot++; return; } for(int i=0; i<2; i++){ //两个方向 int nx=nxt[i][0]+x,ny=nxt[i][1]+y; //下一个位置 if(vis[nx][ny]||nx<1||nx>a||ny<1||ny>b) continue; //如果走过(包含施工路口),越界。则跳出第 i 次循环 else{ //否则 vis[nx][ny]=1; //标记 dfs(nx,ny); //dfs~~ vis[nx][ny]=0; //标记还原 } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>a>>b>>n; //输入 while(n--){ cin>>X>>Y; //输入路口位置 vis[X][Y]=1; //标记为 1 } vis[1][1]=1; //第一个位置一定要标记!!! dfs(1,1); //dfs~~ cout<<tot; //输出路径条数 return 0; } ```