历届试题 地宫取宝 ios
时间限制:1.0s 内存限制:256.0MB数组
问题描述ide
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每一个格子放一件宝贝。每一个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,若是那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就能够拿起它(固然,也能够不拿)。
当小明走到出口时,若是他手中的宝贝刚好是k件,则这些宝贝就能够送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不一样的行动方案能得到这k件宝贝。spa
输入格式code
输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)
接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)表明这个格子上的宝物的价值blog
输出格式内存
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。ci
样例输入string
2 2 2
1 2
2 1io
样例输出
2
样例输入
2 3 2
1 2 3
2 1 5
样例输出
14
话说这个题目意图仍是蛮明显的,深搜完后返回全部知足的解的个数,不过这个善意的题目,要想彻底正确仍是学须要在处理时注意不少方面。
首先,先来谈第一个问题,写出其状态转移方程,咱们要求的解是从原点手握价值最大的宝物v开始通过不一样的路径到终点得到K件宝物的路径总数,咱们姑且将此状态记为
d(1,1,k(初始为0,还没拿宝贝),-1(此时手上没有宝物,值记为-1))
那么今后状态出发,能够将其转移为以下的决策
这里在补充说明用状态转移方程能够方便将原问题分解成若干个与原问题相同的子问题,且规模变小。
第二个问题,若是仅仅这样的话,必然存在重复计算的问题,为此必需要采起记忆化搜索的方式,对于已经计算过的结点保存其值,就这条题目而言,必需要用一个四维数组保存,由于它的状态跟位置,个数以及当前最大的宝物价值有关。当重复遍历这个结点时,直接传值。
第三个问题,细节决定成败!!
1.类型用long long稳妥,由于即便MOD了,可是若是两个数加起来还有可能超int。
2.我本身作的时候没注意的一个小错误,致使最后始终不对的疏忽。我错误的把r[MAXN][MAXN][15][15]的初始化为了0,这绝对不正确,由于有可能以某种方式走的状态就是无解,就是0,必须将初始值赋为-1。
3.对于有宝物的初始价值为-1,比较好的处理方式是,最后存放是第四维的下标后移一位
4.这里还要注意,k最可能是13,不会超过这个值,因此第三维只要14就够了
其它的就看代码吧:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define MAXN 60 5 #define MOD %1000000007 6 using namespace std; 7 long long r[MAXN][MAXN][15][15];//保存状态 8 long long map[MAXN][MAXN];//初始地图 9 long long m,n,num; 10 long long dfs(long long i,long long j,long long k,long long v) 11 { 12 long long s=0,t; 13 if(r[i][j][k][v+1]!=-1) 14 return r[i][j][k][v+1]; 15 if(i==m&&j==n)//到达终点 16 { 17 if(k==num) 18 { 19 r[m][n][k][v+1]=1; 20 return r[m][n][k][v+1]; 21 } 22 else if(k==num-1&&map[m][n]>v) 23 { 24 r[m][n][k][v+1]=1; 25 return r[m][n][k][v+1]; 26 } 27 else 28 { 29 r[m][n][k][v+1]=0; 30 return r[m][n][k][v+1]; 31 } 32 } 33 else 34 { 35 if(map[i][j]>v) 36 { 37 t=map[i][j]; 38 if(i+1<=m) 39 s=(s+dfs(i+1,j,k+1,t)MOD+dfs(i+1,j,k,v)MOD)MOD; 40 if(j+1<=n) 41 s=(s+dfs(i,j+1,k+1,t)MOD+dfs(i,j+1,k,v)MOD)MOD; 42 } 43 else 44 { 45 if(i+1<=m) 46 s=(s+dfs(i+1,j,k,v)MOD)MOD; 47 if(j+1<=n) 48 s=(s+dfs(i,j+1,k,v)MOD)MOD; 49 } 50 r[i][j][k][v+1]=s MOD; 51 return r[i][j][k][v+1]; 52 } 53 } 54 int main() 55 { 56 // freopen("data.in","r",stdin); 57 // freopen("data.out","w",stdout); 58 memset(r,-1,sizeof(r)); 59 long long i,j,p,q; 60 cin>>m>>n>>num; 61 for(i=1;i<=m;i++) 62 for(j=1;j<=n;j++) 63 cin>>map[i][j]; 64 dfs(1,1,0,-1); 65 cout<<r[1][1][0][0]<<endl; 66 return 0; 67 }