Codeforces 629C 简单DP

来源:互联网 发布:天刀冷艳御姐捏脸数据 编辑:程序博客网 时间:2024/04/29 09:17

【题目链接】
http://codeforces.com/problemset/problem/629/C

【解题报告】
比赛的时候跑去做D了,这道题只是简单看了看,赛后补题把它补掉。这个题目只要想通了还是很水的。

题意很简单,给你一个长度为m的串S,让你求不同的串P和Q的方案数使长度为n的串P+S+Q为一个合法括号序列。
合法的括号序列要满足:
1.左括号和右括号数量相同
2.该串的任意一个前缀满足左括号数>=右括号数。

那么我们设dp[i][j]表示长度为i的串,(比)多j个的方案数
递推式可以列写为:dp[i]j[]=dp[i-1][j-1]+dp[i-1][j+1]
之后我们预处理出s中(比)多的个数,枚举左边(比)多的个数即可。

【解题报告】

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int INF=2e9;const int maxn=2e5;const int mod=1e9+7;LL dp[2010][2010]={0};void init( int k ){      dp[0][0]=1;      for(  int i=1;i<=k;i++  )      {            dp[i][0]=dp[i-1][1];            for( int j=1;j<=i;j++ )            {                  dp[i][j]=(dp[i-1][j-1]+dp[i-1][j+1])%mod;            }      }}int main(){      int n,m; cin>>n>>m;      char s[maxn]; cin>>s;      init( n-m );      int pre=-INF,suf,sum=0;      for(  int i=0;i<m;i++ ){            if( s[i]==')' )sum++;                  else sum--;            pre=max( pre,sum );      }     sum=0;      for( int i=m-1;i>=0;i-- )  {            if( s[i]=='(' )sum++;                  else sum--;      }      suf=sum;      LL ans=0;      for(  int i=0;i<=n-m;i++ )            for( int j=0;j<=n-m;j++)            {                  int k=j+sum;                  if(   j>=pre && k>=suf && k<=n-m   )                  {                        ans+=dp[i][j]*dp[n-m-i][k]%mod;                        ans%=mod;                  }            }      cout<<ans<<endl;      return 0;}
0 0