这是一道DP题,大家应该都可以看出来。这题是与地图有关的,所以我的f数组首先带上坐标。
再看k是<=15,所以我的第一个f数组是五维的f[i][j][k][l][1/0],代表在第(i,j)的位置第一个人有k个,第二个人有l个,0是第一个人选,1是第二个人选;的方案数,但是显然时空复杂度都不能接受。
我们再看题目,最终是否是我们的答案只与相对大小有关,所以我们把第三维和第四维合并为两人相差了多少,第一个人捡就加,第二个人捡就减,然后从前往后转移即可。
f[i][j][l][0]=(ll)(f[i][j][l][0]+f[i][j-1][(l-Map[i][j]+k+1)%(k+1)][1])%mod;
f[i][j][l][0]=(ll)(f[i][j][l][0]+f[i-1][j][(l-Map[i][j]+k+1)%(k+1)][1])%mod;
f[i][j][l][1]=(ll)(f[i][j][l][1]+f[i][j-1][(l+Map[i][j])%(k+1)][0])%mod;
f[i][j][l][1]=(ll)(f[i][j][l][1]+f[i-1][j][(l+Map[i][j])%(k+1)][0])%mod;
最后贴上代码:~~~
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define N 805 4 #define K 16 5 #define mod 1000000007 6 using namespace std; 7 int n,m,k,f[N][N][K][2],ans,Map[N][N]; 8 int read() 9 { 10 int x=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();} 13 return x*f; 14 } 15 int main() 16 { 17 n=read();m=read();k=read(); 18 for(int i=1;i<=n;++i) 19 for(int j=1;j<=m;++j) 20 Map[i][j]=read(),f[i][j][Map[i][j]][0]=1; 21 for(int i=1;i<=n;++i) 22 for(int j=1;j<=m;++j) 23 for(int l=0;l<=k;++l) 24 { 25 f[i][j][l][0]=(ll)(f[i][j][l][0]+f[i][j-1][(l-Map[i][j]+k+1)%(k+1)][1])%mod; 26 f[i][j][l][0]=(ll)(f[i][j][l][0]+f[i-1][j][(l-Map[i][j]+k+1)%(k+1)][1])%mod; 27 f[i][j][l][1]=(ll)(f[i][j][l][1]+f[i][j-1][(l+Map[i][j])%(k+1)][0])%mod; 28 f[i][j][l][1]=(ll)(f[i][j][l][1]+f[i-1][j][(l+Map[i][j])%(k+1)][0])%mod; 29 } 30 for(int i=1;i<=n;++i) 31 for(int j=1;j<=m;++j) 32 ans=(ans+f[i][j][0][1])%mod; 33 printf("%lld ",ans); 34 return 0; 35 }
我代码丑,各位老爷将就着看吧~~~