题目链接
思路:考虑递推
f
[
i
]
[
j
]
[
a
]
[
b
]
f[i][j][a][b]
f[i][j][a][b]表示,表示第
i
,
j
i,j
i,j个宝藏选了
a
a
a个,其中最大是
b
b
b的方案数。
每个宝藏都有两种,选或者不选。
初始条件为:
f
[
1
]
[
1
]
[
0
]
[
0
]
=
f
[
1
]
[
1
]
[
1
]
[
a
[
1
]
[
1
]
]
=
1
f[1][1][0][0]=f[1][1][1][a[1][1]]=1
f[1][1][0][0]=f[1][1][1][a[1][1]]=1
不选:
f
[
i
]
[
j
]
[
x
]
[
p
]
+
=
f
[
i
−
1
]
[
j
]
[
x
]
[
p
]
+
f
[
i
]
[
j
−
1
]
[
x
]
[
p
]
f[i][j][x][p]+=f[i-1][j][x][p]+f[i][j-1][x][p]
f[i][j][x][p]+=f[i−1][j][x][p]+f[i][j−1][x][p]
选:
f
[
i
]
[
j
]
[
x
]
[
a
[
i
]
[
j
]
]
+
=
f
[
i
−
1
]
[
j
]
[
x
−
1
]
[
p
]
+
f
[
i
]
[
j
−
1
]
[
x
−
1
]
[
p
]
,
p
<
a
[
i
]
[
j
]
f[i][j][x][a[i][j]]+=f[i-1][j][x-1][p]+f[i][j-1][x-1][p],p<a[i][j]
f[i][j][x][a[i][j]]+=f[i−1][j][x−1][p]+f[i][j−1][x−1][p],p<a[i][j]
注意处理一下细节即可。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 2e5 +11;
const LL mod=1e9+7;
LL f[55][55][14][14],n,m,k,a[100][100];//第i行第j个选a个最大是b的方案,f[i][j][a][b]
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j],a[i][j]++;
f[1][1][1][a[1][1]]=1;
f[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 x=0;x<=k;x++){
for(int p=0;p<=13;p++)f[i][j][x][p]+=f[i-1][j][x][p]+f[i][j-1][x][p],f[i][j][x][p]%=mod;
if(x>=1)for(int p=0;p<a[i][j];p++)f[i][j][x][a[i][j]]+=f[i-1][j][x-1][p]+f[i][j-1][x-1][p];
f[i][j][x][a[i][j]]%=mod;
}
}
}
LL ans=0;
for(int i=1;i<=13;i++)ans+=f[n][m][k][i],ans%=mod;
cout<<ans<<endl;
return 0;
}