Luogu P1373 小a和uim之dark♂逃离

非常痛快的一道DP。

看到机房的同学在写,所以就跟着拿来练练手。

结果一开始理解错题意......还以为两个人可以从不同的格子出发,导致我丧心病狂地开了一个805×805×805×805的四维数组

不MLE才怪......

读懂题之后,发现只有一个坐标状态需要记录,豁然开朗;

本来打算开成 $ f[805][805][16][16][2] $ 的数组,表示坐标,小a的容量,uim的容量,当前由谁取

试了一下发现还是MLE

又想了一会发现可以将两维压缩为一位,表示两人容量的差值。

于是,就成功地表示出了状态。

$ f[x][y][h][0/1] $ 表示:走到的坐标为(x,y),两人容量差为h,当前应由小a(0)或uim(1)取魔液 该状态下的方案数。

然后考虑初始化:

因为从小a开始走(这一点我自己做的时候居然没看到),所以只需要把所有的 $ f[x][y][a[x][y]][1] $ 赋值为1(方案数为1)即可。

然后就是状态转移方程,主要是处理两人容量差:

$ f[x][y][h][0]+=f[x-1][y][(h-a[i][j]+k)%k][1] $
$ f[x][y][h][0]+=f[x][y-1][(h-a[i][j]+k)%k][1] $
$ f[x][y][h][1]+=f[x-1][y][(h+a[i][j])%k][0] $
$ f[x][y][h][1]+=f[x][y-1][(h+a[i][j])%k][0] $

解释一下: $ h-a[i][j] $ 是转移之前的h值,+k再%k是为了防止负数。

下面的h+a[i][j]同理,只不过不需要+k再%k防负数。

其实写成 $ (h+a[i][j]+k)%k $ 也不会错,亲测。

然后,遍历所有的差值为0的情况的方案数,加起来再模上模数,就是答案了。


LL ans=0;
    for(int i(1);i<=n;i++){
        for(int j(1);j<=m;j++){
            ans=(ans+f[i][j][0][1])%mo; 
        }
    }

猜你喜欢

转载自www.cnblogs.com/soul-M/p/9588557.html