题目描述
代码我利用的C语言网bobby同学的,但原文没有解释,本文加上了我的一些理解,附上原文代码
https://blog.dotcpp.com/a/77354
整体思路
深度遍历
我的理解就是一头扎到底,一个节点继续往下走,直到走不通或达到限制要求为止
这道题目也是一样,利用一个数组存储到这个点的时候,某一个数量的宝物在确定最大价值的条件下有几种方案
记忆性递归
例如计算斐波那契数时,另外创建一个数组来存储每一个已经完成计算的斐波那契数,以便用时调用。
而普通的递归计算f(4)时还需要计算f(3)+f(2)但是计算f(3)的时候还要计算f(2)+f(1),这样重复计算f(2),导致时间花费较多
此处也是一样,利用一个四维数组,存储某一个坐标的具体信息,例如:状态列表dp[1][2][3][4]=5 表示坐标(1,2)这个点物
品数量为3最大价值为4的方案有5种
此处有点类似之前做的“危险系数”,也是利用了类似的方法
代码实现过程
1、数据的输入
在此处把状态列表dp中每个数都定义成-1
# main
n,m,k=map(int,input().split())
# 记录迷宫的宝贝价值
table=[]
for _ in range(n):
table.append(list(map(int,input().split())))
# 状态列表dp[1][2][3][4]=5 表示坐标(1,2)这个点物品数量为3最大价值为4的方案有5种
dp=[[[[-1]*15 for _ in range(15)] for _ in range(51)]for _ in range(51)]
2、深度遍历过程
向定义的函数中传递四个数,(x, y, xum, max),也就是四维列表的四个部分,分别代表横坐标,纵坐标,现在已经拿的物品总量,其中最大价值
然后一共有四种情况
2.1、“如果这个方案先前采用过了,就会有一个值而不是初始值-1”
这也是我起初最不理解的一个地方,在另外一篇文章中看到这样的解释:“此处为什么max+1,因为题目中宝物价值是:Ci (0< =Ci< =12),包含0,所以可能取到0,那我在main函数调用时初始化max只能是负数,否则如果起始点为0,我就不能拾起了,但数组下标又不能是负数,干脆直接化为max+1,max+1>=0说明拾起第一件宝物”
我的理解:上面的解释应该是对把dp最初定义为-1的原因,但是
2.2、到达终点
达到终点又分为最后一个格子的物品可以拿和不可以拿
2.3、向下走
向下走又分为拿物品、不拿物品
2.4、向右走
向右走又分为拿物品、不拿物品
完整代码
# main
n,m,k=map(int,input().split())
# 记录迷宫的宝贝价值
table=[]
for _ in range(n):
table.append(list(map(int,input().split())))
# 状态列表dp[1][2][3][4]=5 表示坐标(1,2)这个点物品数量为3最大价值为4的方案有5种
dp=[[[[-1]*15 for _ in range(15)] for _ in range(51)]for _ in range(51)]
#深度遍历
def dfs(x,y,sum,max):
#因为如果这个方案先前采用了,就会有一个值而不是初始值-1
if dp[x][y][sum][max+1]!=-1:
#直接将记录过的状态返回
return dp[x][y][sum][max+1]
#方案数
t=0
#到达终点
if x==n-1 and y==m-1:
#最后一个格子能选
if table[x][y]>max:
#可选可不选,若选那么只能再选最后一个(先前有k-1个)
if sum==k or sum==k-1:
t+=1
elif k==sum:
#不能选也算一种方案
t+=1
dp[x][y][sum][max+1]=t
#返回终点的方案数
return dp[x][y][sum][max+1]
#向下走
if x+1<n:
#可选
if table[x][y]>max:
t+=dfs(x+1,y,sum+1,table[x][y])
t%=1000000007
#不选
t+=dfs(x+1,y,sum,max)
t%=1000000007
#向右走
if y+1<m:
#可选
if table[x][y]>max:
t+=dfs(x,y+1,sum+1,table[x][y])
t%=1000000007
#不选
t+=dfs(x,y+1,sum,max)
t%=1000000007
dp[x][y][sum][max+1]=t
return dp[x][y][sum][max+1]
dp[0][0][0][0]=dfs(0,0,0,-1)
print(dp[0][0][0][0])