标签:四维dp
思路:用dp[i][j][k][p] 记录通过(i,j)点以拿到k个宝物,且宝物最大价值为p的方案数。
当拿取(i,j)点上的宝物时:
dp[i][j][k][map[i][j]]=dp[i-1][j][k-1][pp]+dp[i][j-1][k-1][pp] (pp=0~map[i][j]-1)
当不拿(i,j)点上的宝物时:
dp[i][j][k][p]=dp[i-1][j][k][p]+dp[i][j-1][k][p];
初始化取/不取(0,0)点宝物的方法数为1
AC代码:
#include<iostream>
using namespace std;
const int MOD = 1000000007;
int main()
{
int n,m,kk;
cin>>n>>m>>kk;
int map[52][52];
int dp[52][52][13][14];
int ans=0;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
cin>>map[i][j];
//dp[i][j][0][0]=dp[i][j][1][map[i][j]]=1;
map[i][j]++;//有物品价值为0,所以设没有拿物品价值为-1,-1会数组越界,因此将所有价值都加1
}
}
dp[1][1][0][0]=1;
dp[1][1][1][map[1][1]]=1;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(i==1&&j==1) continue;
for(int k=0;k<=kk;++k)
{
for(int p=0;p<=13;++p)
{
//不取
int &val=dp[i][j][k][p];//引用简写
val=(val+dp[i-1][j][k][p])%MOD;
val=(val+dp[i][j-1][k][p])%MOD;
//取
if(k>0&&p==map[i][j])
{
for(int pp=0;pp<p;pp++)
{
val=(val+dp[i-1][j][k-1][pp])%MOD;
val=(val+dp[i][j-1][k-1][pp])%MOD;
}
}
}
}
}
}
for(int i=0;i<=13;++i)
{
ans=(ans+dp[n][m][kk][i])%MOD;
}
cout<<ans<<endl;
return 0;
}