地宫寻宝
思路
一道蓝桥杯省选题,不是很难,只不过因为没加记忆化逝了……
DFSDFSDFS
爆搜肯定不行,会 TLETLETLE ,只能得 606060 分
有四种状态,拿,往下走,不拿,往下走,拿,往右走,不拿,往右走。到终点之后要判断是否拿到 kkk 件物品,或者在马上到终点时(即 [i−1][i-1][i−1] [j][j][j] 或 [i][i][i] [j−1][j-1][j−1])是否拿到 k−1k-1k−1 件物品。
要加记忆化,降低时间复杂度,应该可以拿满
因为可能会有重复,会浪费很多时间,我们用一个 MarkMarkMark 数组来储存已计算过的路径,降低复杂度,避免不必要的重复。即 if(mark[x][y][maxk+1][k]!=−1)returnif(mark[x][y][maxk+1][k]!=-1) returnif(mark[x][y][maxk+1][k]!=−1)return mark[x][y][maxk+1][k];mark[x][y][maxk+1][k];mark[x][y][maxk+1][k];
DPDPDP
动态规划可能会比较难理解
用 dpdpdp 数组存当前位置拿的宝物的数量,最后输出就行了。
下面附上 DFSDFSDFS 代码
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int mark[55][55][14][14],a[55][55],n,m,k;
int dfs(int x, int y, int maxk, int k){
if(x==n+1||y==m+1) return 0;
if(mark[x][y][maxk+1][k]!=-1) return mark[x][y][maxk+1][k];
long long cnt=0;
if(x==n&&y==m) if(k==k||k==k-1&&a[x][y]>maxk){ cnt++;
else{
cnt+=dfs(x,y+1,maxk,k);
if(a[x][y]>maxk) cnt+=dfs(x,y+1,a[x][y],k+1);
cnt+=dfs(x+1,y,maxk,k);
if(a[x][y]>maxk) cnt+=dfs(x+1,y,a[x][y],k+1);
}
mark[x][y][maxk+1][k]=cnt%mod;//注意一定要摸
returnmark[x][y][maxk+1][k];
}
int main() {
cin>>n>>m>>k;
for(inti=1;i<=n;i++) for(intj=1;j<=m;j++) cin>>a[i][j];
memset(mark,-1,sizeof(mark));
cout<<dfs(1,1,-1,0);
return 0;
}