地宫取宝
题目分析(记忆化递归)
考虑一下dfs需要的参数,首先我每次可以向下和右两个方向走,其次对于当前的宝物我可以选择拿,也可以选择不拿,但是如果要拿一定有一个前提条件就是已经拿的宝物的最大价值小于当前宝物的价值,那么我需要知道已经拿的宝物的最大价值,所以每次dfs的时候都要传参这个最大价值。
接下来考虑dfs的过程,首先是终点判断,当我走到出口时说明递归该结束了,但是最终这个方案是否合法要取决于我当前拿到的宝物个数,所以宝物个数也是dfs的传参。代码如下。
if(x==n&&y==m) {
if(num==k) return 1;
return 0;
}
然后是dfs过程,我们要向两个方向遍历,并且通过拿的宝物的最大价值是否小于当前宝物的价值的判断来决定当前宝物是否可以拿。如果可以拿,那么要更新拿的宝物的最大价值为当前宝物的最大价值,并且拿到的宝物的数量也要加1。拿宝物还有一个前提就是当前宝物数量是小于k的,不然不需要拿。不拿宝物任何时候都可以不拿,所以不需要额外的判断。
for(int i = 0;i < 2;i++) {
int nx = x + nextx[i];
int ny = y + nexty[i];
if(nx>n||ny>m) continue;
if(value[nx][ny]>max&&num<k) res = (res + dfs(nx, ny, value[nx][ny], num+1))%mod;
res = (res + dfs(nx, ny, max, num))%mod;
}
为了提高效率,我们采用记忆化递归,记录当前位置,当前最大值,当前宝物数量的状况下,继续遍历能够得到的方案数。
if(dp[x][y][max][num]!=-1) return dp[x][y][max][num];
long res = 0;
for(int i = 0