一、题目
1、原题链接
3502. 不同路径数
2、题目描述
给定一个 n×m 的二维矩阵,其中的每个元素都是一个 [1,9] 之间的正整数。
从矩阵中的任意位置出发,每次可以沿上下左右四个方向前进一步,走过的位置可以重复走。
走了 k 次后,经过的元素会构成一个 (k+1) 位数。
请求出 一共可以走出多少个不同的 (k+1) 位数。
输入格式
第一行包含三个整数 n,m,k。
接下来 n 行,每行包含 m 个空格隔开的整数,表示给定矩阵。
输出格式
输出一个整数,表示可以走出的不同 (k+1) 位数的个数。
数据范围
对于 30% 的数据, 1≤n,m≤2,0≤k≤2
对于 100% 的数据,1≤n,m≤5,0≤k≤5,m×n>1
输入样例:
3 3 2
1 1 1
1 1 1
2 1 1
输出样例:
5
1
样例解释
一共有 5 种可能的 3 位数:
111
112
121
211
212
二、解题报告
1、思路分析
思路来源:y总讲解视频
y总yyds
(1)因为走过的位置可以重复走,所以针对每个点,它四个方向且在范围中的点都可以走。
(2)利用dfs对每个点可能构成的(k+1)位数进行搜索,然后将构成的数加入哈希表中去重,最终哈希表中元素的数量,即为不同的(k+1)位数的个数。
(3)模拟上述过程,输出答案,即为所求。
2、时间复杂度
时间复杂度为O(n* m *4k)
3、代码详解
#include <iostream>
#include <unordered_set>
using namespace std;
const int N=10;
int g[N][N];
int dx[]={-1,1,0,0},dy[]={0,0,-1,1}; //记录上下左右四个方向的坐标偏移量
int n,m,k;
unordered_set<int> se; //记录不同数字的个数
void dfs(int x,int y,int u,int sum){ //(x,y)为坐标,u代表当前是第几位数(0~k),sum代表当前数字组成的数的值
if(u==k){ //如果已经有k个数字,结束,收获答案加入哈希表中,并回溯
se.insert(sum);
return;
}
for(int i=0;i<4;i++){ //否则,每个点都可以向上下左右四个方向走,依次枚举
int a=x+dx[i],b=y+dy[i];
if(a>=0&&a<n&&b>=0&&b<m){ //如果走到的点在范围中,继续向下搜索
dfs(a,b,u+1,sum*10+g[a][b]);
}
}
}
int main(){
cin>>n>>m>>k;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>g[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
dfs(i,j,0,g[i][j]);
}
}
cout<<se.size();
return 0;
}
三、知识风暴
深搜DFS
尽量纵深搜索,可以利用栈或递归实现。