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