其他分享
首页 > 其他分享> > 洛谷 P1373 小a和uim之大逃离

洛谷 P1373 小a和uim之大逃离

作者:互联网

传送门

思路

吐槽

吐槽:话说不应该是他俩都得死嘛qwq

咋做

一道\(DP\)好题.

我们用\(f[i][j][q][p]\)来表示:走到第\(i\)行第\(j\)列魔液差距值为\(q\)且当前为\(p\)走的方案数(\(p\in \{0, 1\} p=0\)表示目前为小\(a\)走,\(p=1\)表示目前为\(uim\)走)

初始条件:\(f[i][j][a[i][j]][0]=1\)表示小\(a\)从每个点开始取,差距值为\(a[i][j]\)的方案数为\(1\)

那么我们可以想出转移方程:

\[f[i][j][p][0]+=f[i-1][j][p-a[i][j]][1]+f[i][j-1][p-a[i][j]][1]\]

这个式子表示目前在第\(i\)行第\(j\)列,差距值为\(p\),当前小\(a\)走的方案数,因为只能往右走或往下走,且上一步一定是\(uim\)走的,所以可以从第\(i-1\)行第\(j\)列、第\(i\)行第\(j-1\)列转移过来,差距值增大

\[f[i][j][p][1]+=f[i-1][j][p+a[i][j]][0]+f[i][j-1][p-a[i][j]][0]\]

同理,这个式子表示目前在第\(i\)行第\(j\)列,差距值为\(p\),当前\(uim\)走的方案数,上一步一定是小\(a\)走的,所以可以从第\(i-1\)行第\(j\)列、第\(i\)行第\(j-1\)列转移过来,差距值减小

我们容易想出,最后的答案就是\(\sum_{i = 1}^{n}\sum_{j = 1}^{m}f[i][j][0][1]\)最后一维是\(1\)是因为最后一步只能由\(uim\)走

空间复杂度\(n*m*k*2\)刚好可以,时间复杂度\(O(n*m*k)\)可以过

注意!

  1. 因为魔液值到达\(k+1\)之后就会清\(0\),所以在过程中要随时对\(k+1\)取模
  2. 空间开好!!不要开太大!因为最后一维只用\(0、1\),所以开\(2\)的数组就好了就行了,开\(3\)会\(MLE\)
  3. 码风丑陋,谨慎阅读\(qwq\)

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int B = 20;
const int A = 800 + 7;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
    char c = getchar(); int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

int n, m, k, a[A][A], f[A][A][B][2];

int main() {
    n = read(), m = read(), k = read() + 1;
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) a[i][j] = read(), 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 p = 0; p <= k; p++) {
                f[i][j][p][0] = (f[i][j][p][0] + f[i - 1][j][(p - a[i][j] + k) % k][1] + f[i][j - 1][(p - a[i][j] + k) % k][1]) % mod;
                f[i][j][p][1] = (f[i][j][p][1] + f[i - 1][j][(p + a[i][j] + k) % k][0] + f[i][j - 1][(p + a[i][j] + k) % k][0]) % mod;
            }
    int ans = 0;
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) ans += f[i][j][0][1], ans %= mod;
    cout << ans << '\n';
    return 0;
}

标签:P1373,洛谷,int,行第,uim,read,const,include
来源: https://www.cnblogs.com/loceaner/p/12141671.html