Codeforces 629C 简单DP

【题目链接】
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章