Codeforces 1152D - Neko and Aki's Prank (dp)

题意

求由所有长度为 2 n 2n 2n的合法括号匹配序列组成字典树的二分图最大匹配(给边染色是的染色的边没有交点)

做法

考虑树形 d p dp dp(可能不是?).
d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] dp[i][j][0/1]表示当前节点已经有 i i i个左括号, j j j个右括号, 且改节点与父亲节点的边是否染色 ( 0 / 1 ) (0/1) (0/1)的方案数
则有转移方程:
d p [ i ] [ j ] [ 0 ] = d p [ i ] [ j − 1 ] [ 1 ] ( j > i ) + d p [ i − 1 ] [ j ] [ 1 ] dp[i][j][0] = dp[i][j-1][1](j > i) + dp[i-1][j][1] dp[i][j][0]=dp[i][j1][1](j>i)+dp[i1][j][1]
d p [ i ] [ j ] [ 1 ] = m a x ( d p [ i − 1 ] [ j ] [ 0 ] + 1 + d p [ i ] [ j − 1 ] [ 1 ] , d p [ i − 1 ] [ j ] [ 1 ] + 1 + d p [ i ] [ j − 1 ] [ 0 ] ) dp[i][j][1] = max(dp[i-1][j][0] + 1 + dp[i][j-1][1], dp[i-1][j][1] + 1 + dp[i][j-1][0]) dp[i][j][1]=max(dp[i1][j][0]+1+dp[i][j1][1],dp[i1][j][1]+1+dp[i][j1][0])
答案为 d p [ n ] [ n ] [ 1 ] dp[n][n][1] dp[n][n][1], 总状态数 O ( n 2 ) O(n^2) O(n2), 转移 O ( 1 ) O(1) O(1), 总复杂度 O ( n 2 ) O(n^2) O(n2).
但由于转移涉及到大小比较,所以需要用大数,实际不用大数也能过,不知道原因(可能 d p [ i ] [ j ] [ 0 ] dp[i][j][0] dp[i][j][0] d p [ i ] [ j ] [ 1 ] dp[i][j][1] dp[i][j][1]比较接近,而且没有等于1e9+7的情况)

代码

python3太慢(提速技巧: 交pypy3(可提速3倍),尽量少开多维数组,少定义局部变量)

n = int(input())
f = [[0]*(n+1) for i in range(n+1)]
g = [[0]*(n+1) for i in range(n+1)]
mod = 10**9+7
for i in range(1, n + 1):
    f[0][i] = g[0][i - 1]
    g[0][i] = f[0][i - 1] + 1
t = [0, 0]
for i in range(1, n + 1):
    for j in range(i, n + 1):
        if i > 0:
            f[i][j] += g[i - 1][j]
            t[0] = g[i - 1][j]
            t[1] = f[i - 1][j] + 1
        if j > i:
            f[i][j] += g[i][j-1]
            t[0] += f[i][j - 1] + 1
            t[1] += g[i][j - 1]
        for k in t: g[i][j] = max(g[i][j], k)
print(g[n][n]%mod)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值