常规线性dp,需要时就加一维。(dp[i][j][t][s])表示在点((i,j))时瓶子里剩(t)且为(s)走(0代表小a,1代表uim)时的方案数。
de了半天发现是初次尝试的快速取模少写个等号……然鹅改了以后为什么比正常写跑得慢……
#include <cstdio>
const int mod = 1e9 + 7;
int n, m, k, ans;
int a[805][805], dp[805][805][20][2];
void add(int &x, int y, int mod) {
x += y;
if (x >= mod) x -= mod;
if (x < 0) x += mod;
}
int main() {
scanf("%d %d %d", &n, &m, &k);
k++;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", &a[i][j]);
dp[i][j][a[i][j]][0] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
add(ans, dp[i][j][0][1], mod);
for (int s = 0; s < 2; s++) {
for (int t = 0; t < k; t++) {
if (i < n) {
int tmp = t;
add(tmp, (s ? 1 : -1) * a[i + 1][j], k);
add(dp[i + 1][j][tmp][1 - s], dp[i][j][t][s], mod);
}
if (j < m) {
int tmp = t;
add(tmp, (s ? 1 : -1) * a[i][j + 1], k);
add(dp[i][j + 1][tmp][1 - s], dp[i][j][t][s], mod);
}
}
}
}
}
return !printf("%d
", ans);
}