[luogu1373]小a和uim之大逃离【动态规划】

传送门:https://www.luogu.org/problemnew/show/P1373


定义状态是:\(f[i][j][h][0..1]\)表示在\([i,j]\)两个人相差为h,让某一个人走的方案数。(0表示小a,1表示uim)。
我们让小a走,那么状态转移方程就是\(f[i][j][h][0]=f[i][j][h][0]+f[i-1][j][(h-a[i][j]+k)mod \ k][1]+f[i][j-1][(h-a[i][j]+k)mod \ k][1]\)这里防止状态里面出现负数,就加模取模,这里的意思就是小a的状态必须是由先让uim走来的,那么这样原来的差距更小。
同理:\(f[i][j][h][1]=f[i][j][h][1]+f[i-1][j][(h+a[i][j])mod \ k][0]+f[i][j-1][(h+a[i][j]) mod \ k][0]\),也就是前一个人走。

#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 805
using namespace std;
template <typename T>
inline void read(T &x) {
    x = 0; T fl = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') fl = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x *= fl;
}
int n, m, k;
int a[N][N];
int f[N][N][20][2];
int main() {
    read(n); read(m); read(k);
    ++ k;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            read(a[i][j]);
            f[i][j][a[i][j] % k][0] = 1;
        }
    }
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            for (int h = 0; h <= k; h ++) {
                f[i][j][h][0] = (f[i][j][h][0] + f[i - 1][j][(h - a[i][j] + k) % k][1] + f[i][j - 1][(h - a[i][j] + k) % k][1]) % mod;
                f[i][j][h][1] = (f[i][j][h][1] + f[i - 1][j][(h + a[i][j]) % k][0] + f[i][j - 1][(h + a[i][j]) % k][0]) % mod;
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            ans = (ans + f[i][j][0][1]) % mod;
        }
    }
    printf("%d\n", ans);
    return 0;
}
上一篇:jquery 中的 $("#id") 与 document.getElementById("id") 的区别


下一篇:Spring Boot中使用Flyway来管理数据库版本