感觉这道题思路还是比较简单的,令 f[i][j][k][0/1] f [ i ] [ j ] [ k ] [ 0 / 1 ] 表示走到 (i,j) ( i , j ) ,两人魔液差为k,最后一步是小a还是uim拿取魔夜的方案数,然后用左边和上边的格子来更新。
这道题有两个问题,第一个是这道题的空间限制很紧,一不小心就MLE了,所以数组要尽量小一些。
第二个在 f f 数组的k那里。一开始我是打算让等于小a魔液量减去uim魔液量在加上15(C++数组下标不能用负数),然而这样大概会MLE,于是就表示成差值的绝对值,但是这样就需要对k的加减进行分类讨论了,因为差值的正负会影响取得魔液后差值的绝对值的加减,问题是我没有分类讨论的代码AC了(至少在洛谷上AC了),所以我在这里有些不解。如果哪位神犇想明白了这个可以在底下评论区说一下想法,毕竟我只是一个蒟蒻啊qwq
PS:怪物说魔液多的那个可以活下来,两人一样多不就是没有更多的了嘛,所以最后俩都要死啊(:з」∠)
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mod=1000000007;
const int N=810;
int n,m,r,ans,a[N][N],f[N][N][16][2];//注意空间啊
int main()
{
scanf("%d%d%d",&n,&m,&r);r++;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);f[i][j][a[i][j]][0]=1;//初始化
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
for(int k=0;k<r;k++)
{
int k1=(k+a[i][j])%r,k2=(k-a[i][j]+r)%r;
f[i][j][k1][0]+=(f[i-1][j][k][1]+f[i][j-1][k][1])%mod;
f[i][j][k2][1]+=(f[i-1][j][k][0]+f[i][j-1][k][0])%mod;
f[i][j][k1][0]%=mod;f[i][j][k2][1]%=mod;
}//枚举差值的绝对值并更新
ans=(ans+f[i][j][0][1])%mod;//直接更新总方案数
}
printf("%d\n",ans);return 0;
}