解題思路:動態規劃。在每一個位置的狀態考慮,當前這個位置的狀態是由哪些狀態轉移過來的。
dp[i][j][u][v]表示在(i,j)這個位置,拿到u個物品,且這些物品的最大價值是v。
我們可以考慮當前位置(i,j)拿不拿當前這個物品,如果不拿那麼可以從dp[i-1][j][u][v]、dp[i][j-1][u][v]轉移過來,表示上一個位置已經拿到了u個物品最大價值為v的。如果拿則可以從dp[i-1][j][u-1][c]、dp[i][j-1][u-1][c]轉移過來,表示上一個位置拿了u-1個,並且最大價值為c(c為小於v的數),最後再把最後手上可能拿的價值的方案數加起來即可。
ps:因為這道題的所有物品價值範圍是0…120…12,可以把他們全部都遞增,範圍就變成了1…131…13,因為我們記錄的是方案數,只關心各個物品之間的大小關係,具體數值不影響答案,但是這樣的做法可以把00作為一個特殊邊界來處理
#include<bits/stdc++.h>
#define x first
#define y second
#define mem(h) memset(h,-1,sizeof h)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
namespace IO{
inline LL read(){
LL o=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){o=o*10+c-'0';c=getchar();}
return o*f;
}
}using namespace IO;
const int N=50+7,M=2e5+7,INF=0x3f3f3f3f,mod=1e9+7,P=131;
int dp[N][N][13][14];
int n,m,k;
int w[N][N];
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>w[i][j];
w[i][j]++;
}
}
dp[1][1][1][w[1][1]]=1;
dp[1][1][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==1&&j==1)continue;
for(int u=0;u<=k;u++){
for(int v=0;v<=13;v++){
int &val=dp[i][j][u][v];
val=(val+dp[i-1][j][u][v])%mod;
val=(val+dp[i][j-1][u][v])%mod;
if(u>0&&v==w[i][j]){
for(int c=0;c<v;c++){
val=(val+dp[i-1][j][u-1][c])%mod;
val=(val+dp[i][j-1][u-1][c])%mod;
}
}
}
}
}
}
int res=0;
for(int i=0;i<=13;i++){
res=(res+dp[n][m][k][i])%mod;
}
cout<<res<<endl;
return 0;
}