第一眼:感觉能切。
GO:传送门
看一眼数据,觉得是O(nmk)的。
尝试设f[i][j][k][l]表示在(i,j)时,此时分别有k和l的药的总方案数。
这里把两个人的行走直接算作一步。
f[i][j][k][l]=f[i-2][j][k-a[i-1][j]][l-a[i][j]]+...分别表示通过右右,右下,下右,下下达到该点的方案数。
预处理一下,以某一个点为起点,那么f[i][j][0][0]=1.
时间复杂度O(nmkk)太大,发现没必要把两个人行走算作一步(我好蠢)
直接一点,
f[i][j][k][0/1]表示(i,j)位置,此时两人液体差为k,0表示a走,1表示uim先走。
转移没啥好难想的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int read(){ 4 int x=0,f=1; 5 char c=getchar(); 6 while(!isdigit(c)){ 7 if(c=='-') f=-1; 8 c=getchar(); 9 } 10 while(isdigit(c)){ 11 x=x*10+c-'0'; 12 c=getchar(); 13 } 14 return x*f; 15 } 16 typedef long long ll; 17 const int N=810; 18 const int p=1e9+7; 19 int n,m,k,mod; 20 int a[N][N]; 21 int f[N][N][16][2]; 22 int main(){ 23 n=read();m=read();k=read(); 24 mod=k+1; 25 for(int i=1;i<=n;i++){ 26 for(int j=1;j<=m;j++){ 27 f[i][j][a[i][j]=read()][0]=1; 28 } 29 } 30 for(int i=1;i<=n;i++){ 31 for(int j=1;j<=m;j++){ 32 for(int c=0;c<=k;c++){ 33 if(i-1>0){ 34 (f[i][j][c][0]+=f[i-1][j][(c-a[i][j]+mod)%mod][1])%=p; 35 (f[i][j][c][1]+=f[i-1][j][(c+a[i][j])%mod][0])%=p; 36 } 37 if(j-1>0){ 38 (f[i][j][c][0]+=f[i][j-1][(c-a[i][j]+mod)%mod][1])%=p; 39 (f[i][j][c][1]+=f[i][j-1][(c+a[i][j])%mod][0])%=p; 40 } 41 } 42 } 43 } 44 ll ans=0; 45 for(int i=1;i<=n;i++){ 46 for(int j=1;j<=m;j++){ 47 ans+=f[i][j][0][1]; 48 ans%=p; 49 } 50 } 51 printf("%lld",ans); 52 return 0; 53 }