기술
왕의 X 지하 궁전 관은 보물이있다. 되고, N × M 개의 격자 매트릭스. 각 그리드는 아기를 넣어. 라벨의 값으로 각 아기 가깝습니다.
상단에있는 지하 궁전 입구는 오른쪽 아래 모서리에 코너 종료를 떠났다.
밥이 지하 궁전의 입구에 찍은, 왕이 오른쪽이나 아래에만 도보로 그에게 물었다.
아기가 어떤 아기 샤오 명나라의 손의 값보다 큰 경우 그리드에 의해 걸었다 그리드 값은 샤오 밍은 (물론, 당신이 취할 수 없음)을 선택할 수 있습니다.
밥은 출구에 갔을 때 그는 아기 K 조각의 손에 될 일 경우, 다음 아기가 밥에게 주어집니다.
도움 샤오 밍은 주어진 상황에서, 그는이 K 보물을 얻을 수있는 행동의 다른 코스의 번호를 가지고, 말하십시오.
입력
공백으로 구분 3의 정수 입력 라인 : NMK. (1 ≤ N-, m ≤ 50 ,. 1 ≤ K ≤ 12이다) .
다음에 n 행이 갖는 각 행 m 정수 CI (0 ≤ ≤ 12 CI) 보물에 격자의 대표 값.
산출
A는 단지 K 아기를 복용 액션 프로그램의 수를 나타내는 정수 출력이 필요합니다. 이 수는 클 수 있고, 출력은 모듈로 1,000,000,007.
샘플 입력
2 2 2
1 2
2 1
샘플 출력
이
1 #INCLUDE <iostream>
2 #INCLUDE <CString을>
3 #DEFINE N 1,000,000,007
4 이용한 스페이스 성병;
5 INT N, M, K;
6 INT의 맵 [ 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 * / // 전에 경우 본 표시되었으며,이 값의 직접 사용에 대한 검색을 계속하지 않아도
11. 창 DP [X] [Y] [NUM] MAXA + 1이다. ]
(12)는 IF (X == N - && Y == m) { // 도달하면 콘센트 A,
13은 IF ((|| NUM == K == - K-NUM . 1 && MAXA <맵 [X] [Y])) / * 2 * / // 들은이 두 사례의 경우, 충족하는 경우
14 창 DP [X] [Y를 [NUM] MAXA + . 1= 1 ; // 할당 된 배열을 넣어 1
15 다른
16 반환 DP [X] [Y] [NUM] MAXA + 1 ] = 0 ; // 영 그렇지
17. }
(18)가 긴 롱 S = 0 ; / * 5 * / // 마다 DFS가 초기화 s는 0을 입력한다
(19). INT DX, Dy를하는 단계;
(20)가 대해 ( INT는 = I 0 ; I < 2 ; I ++ ) {
21는 DX = X + 디렉터리 [I]는 [ 0 ]
(22)이다 디렉터리의 Dy = Y + [I] [ 1. ];// 위치의 좌표를 결정
(23) IF (DX <= N - &&의 Dy <= m) { / * . 3 * / // . 경우도 범위에서이 위치
(24) IF (MAXA <맵 [X] [Y]) / * 4 * / // 이 위치를 취할 수 보물 경우
25 S + = DFS (DX, Dy가, NUM + 1. , 맵 [X] [Y]가); // 다음 검색 보물을 넣어
26 것은 S + = DFS (DX, Dy를 , NUM, MAXA는) // 이는 검색 보물을 없다
27 }
28 }
29 리턴 DP [X] [Y] [NUM] MAXA + 1이다. ] = S % N;
30 }
31는 INT 의 main () {
32 scanf와 ( " % D % D % D " , 및 N, M, K);
33 대 ( INT 나 = 1 ; i가 <= N; I ++ ) {
34 대 ( INT J = 1 ; J <= m; J ++ ) {
35 는 scanf ( " %의 D " , 맵 [I] [J]);
36 }
37 }
38 memset 함수 (DP - 1 , 를 sizeof (DP));
39 의 printf ( " %의 D " , DFS ( 1 , 1 , 0- 1 ));
40 반환 0 ;
41 }
이 문제를 해결하는 방법은 메모리 검색입니다
검색 시간 밖으로의 직접 사용
以下是对代码中/* */地方的注释
/* 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