Codeforces 1152 D Neko and Aki's Prank 题解(记忆化搜索)

题目:CF1152D
题目大意:将所有长度为 2 n 2n 2n的括号序列(对于每个位置前面的左括号数量必须大于右括号数量)插入一个Trie中,然后给选出这棵Trie中的一个边集使得这些边没有交点,使得边集大小最大.
1 ≤ n ≤ 1 0 3 1\leq n\leq 10^3 1n103.

我们可以考虑大力dfs构造出这棵Trie并在这棵Trie上DP统计,但是这个算法的复杂度是指数级的,根本无法接受.

容易发现若两个子Trie的根到大Trie的根这一条链上已用左括号和右括号数量相同时,两个子Trie一定是相同的,两个相同的子Trie是不是不需要重复计算了呢?

那么我们就可以设 d p [ l ] [ r ] [ 0 / 1 ] dp[l][r][0/1] dp[l][r][0/1]表示已用左括号 l l l个右括号 r r r个时,根被选 / / /不被选时的方案数,这样子就可以做到 O ( n 2 ) O(n^2) O(n2)解决这个问题了,具体实现可以用记忆化搜索.

代码如下:

#include<bits/stdc++.h>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=1000,mod=1000000007;

int n,dp[N+9][N+9][2],vis[N+9][N+9][2];

int dfs(int l,int r,int k){
  if (vis[l][r][k]) return dp[l][r][k];
  vis[l][r][k]=1;
  int ans=0,t=k;
  if (l<n){
  	ans=(ans+dfs(l+1,r,t^1)+(t^1))%mod;
  	t=1;
  }
  if (l>r) ans=(ans+dfs(l,r+1,t^1)+(t^1))%mod;
  return dp[l][r][k]=ans;
}

Abigail into(){
  scanf("%d",&n);
}

Abigail outo(){
  printf("%d\n",(1+dfs(1,0,1))%mod);
}

int main(){
  into();
  outo();
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值