2014.地宫取宝(DFS+记忆化搜索)
问题描述: X 国王有一个地宫宝库,是 n*m 个格子的矩阵。 每个格子放一件宝贝,每个宝贝贴着价值标签。 地宫的入口在左上角,出口在右下角。 小明被带到地宫的入口,国王要求他只能向右或向下行走。 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。 当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。 输入格式 输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12) 接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值 输出格式 要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。 样例输入 2 2 2 1 2 2 1 样例输出 2 样例输入 2 3 2 1 2 3 2 1 5 样例输出 14
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define ll long long 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 const int MOD=1e9+7; 8 9 int n,m,k; 10 int maze[60][60]; 11 ll dp[60][60][15][15];//记忆化搜索 12 13 ll DFS(int x,int y,int curTot,int curMax) 14 { 15 //须注意的一点是curMax可能有为-1的情况,所以将所有的curMax+1 16 if(dp[x][y][curTot][curMax+1] != -1) 17 return dp[x][y][curTot][curMax+1]; 18 19 if(x == n+1 || y == m+1 || curTot > k) 20 return 0; 21 22 if(x == n && y == m) 23 { 24 if(curTot == k || (curTot == k -1 && maze[x][y] > curMax)) 25 return 1; 26 return 0; 27 } 28 ll ans=0; 29 if(maze[x][y] > curMax) 30 { 31 ans += DFS(x+1,y,curTot+1,maze[x][y]); 32 ans += DFS(x,y+1,curTot+1,maze[x][y]); 33 } 34 ans += DFS(x+1,y,curTot,curMax); 35 ans += DFS(x,y+1,curTot,curMax); 36 ans %= MOD; 37 38 dp[x][y][curTot][curMax+1]=ans; 39 return ans; 40 } 41 int main() 42 { 43 while(~scanf("%d%d%d",&n,&m,&k)) 44 { 45 for(int i=1;i <= n;++i) 46 for(int j=1;j <= m;++j) 47 scanf("%d",&maze[i][j]); 48 mem(dp,-1);//宝贝价值可能为0,所以将dp初始化为-1 49 printf("%lld\n",DFS(1,1,0,-1)); 50 } 51 return 0; 52 }