题目描述
题目分析
问题可以转化为有一个矩阵,矩阵上每个点代表从这一步开始最多能走的步数,每次只能往右或者往下走,问从左上角到右下角有多少种方式。
因为每次走的时候不一定要把剩余步数走完,也是说在此前可以到达的点上可以重新选择一条路径。我们可以从左上角开始进行记忆化搜索,把每个点能到达右下角的路径数给记录下来,下次再到达这个点的时候就可以直接应用该数,从而极大减少时间复杂度。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110;
int mp[N][N], ans[N][N]; //mp存储图,ans存储从该点出发的路径数
int n, m, t;
int DFS(int x, int y) {
if(ans[x][y] >= 0) return ans[x][y]; //记忆化搜索
ans[x][y] = 0; //初始值
for(int i = 0; i <= mp[x][y]; i ++) { //在能量允许范围内探索
for(int j = 0; j <= mp[x][y] - i; j ++)
if(x + i >= 1 && x + i <= n && y + j <= m && y + j >= 1) //检查越界
ans[x][y] = (DFS(x + i, y + j) + ans[x][y]) % 10000;
}
return ans[x][y]; //返回答案
}
int main() {
cin >> t;
while(t --) {
cin >> n >> m;
memset(ans, -1, sizeof(ans)); //初始化
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
cin >> mp[i][j];
ans[n][m] = 1; //终点到终点,1种路径
cout << DFS(1, 1) << endl;
}
return 0;
}