[关闭]
@WangYixu 2018-06-16T05:17:36.000000Z 字数 746 阅读 763

[LgP1373] 小a和uim之大逃离

OI 题解 DP

算法:矩形DP

首先很自然的写出状态:f[i][j]表示(i, j)点处的方案数,但是,这样无法转移,首先,我们不知道这个点上是谁,所以改进为f[i][j][2],第三维表示是a还是uim。但是这样还不够,我们依旧是无法转移,注意到如果把a和uim看作一个人装,一个人倒,那就是相当于要求差值模k+1为0,所以改进为f[i][j][k][2],k表示差值。

为了避免讨论,我们将a[i][j]奇偶染色,这样,就保证了每一步都是一加一减。

由于起点不定,每个点都要初始化为1。

代码

  1. inline int mod(int n, int md) { return (n % md + md) % md; }
  2. int main() {
  3. scanf("%d%d%d", &n, &m, &k);
  4. ++k; // 方便做
  5. for (int i = 1; i <= n; ++i) {
  6. for (int j = 1; j <= m; ++j) {
  7. scanf("%d", &a[i][j]);
  8. if ((i + j) & 1) a[i][j] *= -1; // 奇偶染色
  9. a[i][j] = mod(a[i][j], k);
  10. f[i][j][a[i][j]][0] = 1;
  11. for (int res = 0, y; res < k; ++res) {
  12. y = mod(res-a[i][j], k);
  13. f[i][j][res][0] = ((f[i][j-1][y][1] + f[i-1][j][y][1]) % MOD
  14. + f[i][j][res][0]) % MOD;
  15. f[i][j][res][1] = ((f[i][j-1][y][0] + f[i-1][j][y][0]) % MOD
  16. + f[i][j][res][1]) % MOD;
  17. }
  18. ans = (ans + f[i][j][0][1]) % MOD;
  19. }
  20. }
  21. printf("%d\n", ans);
  22. return 0;
  23. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注