[Blue Bridge Cup] [previous questions] take the underground palace treasure

Description

King's X has a treasure trove underground palace. Is nxm lattice matrix. Each grid put a baby. Each baby close to the value of the label.
Underground palace entrance at the top left corner, exit at the bottom right corner.
Bob was taken to the inlet of the underground palace, the king asked him to walk to the right or down only.
Walked by a grid, the grid value if the baby is larger than the value of the hands of any baby Xiao Ming, Xiao Ming can pick it up (of course, you can not take).
When Bob went to the exit, if he happens to be in the hands of baby k pieces, then the baby will be given to Bob.
Please help Xiao Ming told, in a given situation, he has a number of different courses of action to get this k treasures.

Input

3 integer input line, separated by spaces: NMK (. 1 ≤  n-, m ≤  50,. 1 ≤  K ≤  12 is) .

Then there are n rows, each row having m integers Ci (0 ≤ Ci ≤ 12) representative of the value of the lattice on the treasure.

Output

A required output integer representing the number of action programs just taking the k baby. This number may be large, its output modulo 1000000007.

Sample Input

2 2 2
1 2
2 1

Sample Output

2



 1 #include<iostream>
 2 #include<cstring>
 3 #define N 1000000007
 4 using namespace std;
 5 int n,m,k;
 6 int map[103][103];
 7 int dp[53][53][15][15];/* 6 */  
 8 int dir[4][2]={1,0,0,1};
 9 int DFS ( int X, int Y, int NUM, int MAXA) {
 10      IF (DP [X] [Y] [NUM] [MAXA + . 1 ] = -! . 1 ) / * . 1 * /  // before if this has been marked, and do not have to continue searching for the direct use of this value 
. 11          return DP [X] [Y] [NUM] [MAXA + . 1 ];
 12 is      IF (X == n-&& Y == m) { // if reaching the outlet a, 
13 is          IF (NUM == K || (== - K-NUM . 1 && MAXA <Map [X] [Y])) / * 2 * /  // if they meet these two cases 
14              return DP [X] [Y ] [NUM] [MAXA + . 1] = 1 ; // put the assigned array 1 
15          the else 
16              return DP [X] [Y] [NUM] [MAXA + 1 ] = 0 ; // zero otherwise     
. 17      }
 18 is      Long  Long S = 0 ; / * 5 * /  // every time dfs should enter the initialization s is 0 
. 19      int DX, Dy;
 20 is      for ( int I = 0 ; I < 2 ; I ++ ) {
 21 is          DX = X + the dir [I] [ 0 ];
 22 is          the dir = Y + Dy [I] [ . 1 ];// determine the coordinates of a position 
23 is          IF (DX <= n-&& Dy <= m) { / * . 3 * /  // If this position in the range of FIG. 
24              IF (MAXA <Map [X] [Y]) / * 4 * /  // If treasure this position can take 
25                  S + = DFS (DX, Dy, NUM + . 1 , Map [X] [Y]); // put take the treasure then search 
26 is              S + = DFS (DX, Dy , NUM, MAXA); // this is not the search take the treasure     
27          }
 28      }
 29      return DP [X] [Y] [NUM] [MAXA + . 1 ] = S% N;
 30  }
 31 is  int main () {
 32     scanf("%d%d%d",&n,&m,&k);
33     for(int i=1;i<=n;i++){
34         for(int j=1;j<=m;j++){
35             scanf("%d",&map[i][j]);
36         }
37     }
38     memset(dp,-1,sizeof(dp));
39     printf("%d",dfs(1,1,0,-1));
40     return 0;
41 } 

The method of solving the problem is the memory search

The direct use of search time out

以下是对代码中/* */地方的注释

/* 6 */ 解释下dp数组的意思,举例说明 dp[3][4][5][6]=7 代表的意思是
当小明走到第3行第3列(从第0行第0列开始算)的格子的时候,小明身上有5件宝贝,在这5件宝贝中,
价值最高的那件宝贝的价值是6,在这样的情况下,小明走到终点拿到k件宝物的方案数是7
  这也体现了记忆化搜索的特点,因为我们要记录在搜索过程中的信息,这个dp数组记录的信息就是
位置,此时的宝贝数量,还有价值最高的宝贝的价值,这些信息就足够分明每一种情况,在这样的情况下,
从这个格子开始搜索,得到的结果都是一样的,那么每种情况就只搜索一次就行了,下次再遇到这种情况,
就直接用结果就行了
  那么为什么要记录最大值这个信息呢,因为题目中有个条件是,当这个格子里的宝物的价值大于小明
手上拿的任意的宝物的价值的话,小明就可以拿走这个格子里的宝物,那么当这个格子里的宝物大于小明
手上拿的最大价值的宝物的价值的话,这个格子里的宝物的价值就一定大于小明手上拿的任意的宝物的价值
记录最大价值这条信息就是为了方便判断是否符合这个条件,否则你还得拿每一个小明手中的宝物来和格子里
的宝物相比较,那样太麻烦了。

/* 1 */ 这就是记忆化搜索中记忆的部分,一开始dp数组的值都是-1,如果dp数组的值不是-1了,
那就代表这个地方被搜索过了,那么我们就不用再搜索一遍了,我们直接用存储再这个数组里的值就行了,
这就相当于从这开始搜索了一编

/* 2 */ 解释下这两种情况都是什么,
第一种情况:小明走到了出口,并且手上的宝物整好有k件,
第二种情况:小明走到了出口,手上的宝物有k-1件,并且此时小明可以拿走出口格子里的宝物,
那么当小明拿走出口格子的宝物之后,小明手上就有了k件宝物

/* 3 */ 一般的搜索中,主人公都是可以上下左右的走,所以设置限制条件的话,都是这样的
dx>=1&&dx<=n&&dy>=1&&dy<=m
但在这道题中,主人公只能向右和向下走,所以只要判断它会不会超过右边的边界和下面的边界就行了
所以条件就是
dx<=n&&dy<=m
就行了
/* 4 */ 这个前面说到了,当这个格子的宝物的价值大于小明手上拿的价值最大的宝物的价值的时候,
小明就可以拿走这个格子里的宝物了
/* 5 */ s存储的是当前这个格子到终点有多少条行动方案能得到k件宝物,一个格子的行动方案数等于
它右边格子的行动方案数加上它下边格子的行动方案数,并且在向右边或下边探索的时候,分别有两种情况
一种是拿了这个格子里的物品再向右边或下边探索,另一种是没拿这个格子里的物品再继续向右边或下边
探索
另外,在定义s的时候得用long long 用int会越界
O(∩_∩)O



Guess you like

Origin www.cnblogs.com/fate-/p/12337083.html