UESTC 1321 柱爷的恋爱 (区间DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UESTC 1321 柱爷的恋爱 (区间DP)相关的知识,希望对你有一定的参考价值。

原题地址

 

题意:

给定一个括号序列,问删去一个子集,得到一个非空的合法序列的方案数。

题解

题目实际上就是问给定序列中存在多少非空子集为合法序列

首先想到的是枚举分界点,dp[l][r]=sigma(dp[l][k]*dp[k+1][r],l<=k<=r),但是必然存在重复计数的情况。

考虑区间左端点的配对括号,以左端点配对的括号作为分界点,可以保证无重复同时不遗漏

dp[l][r]表示[l,r]中合法的子集数。

如果s[l]为右括号,那么dp[l][r]=dp[l+1][r]

如果s[l]为左括号:

如果s[l]不参与配对,dp[l][r]+=dp[l+1][r]。

如果s[l]参与配对,那么dp[l][r]=sigma(dp[l+1][k-1]*dp[k+1][r],s[k]与s[l]配对)

 

#include<bits/stdc++.h>

#define clr(x,y) memset((x),(y),sizeof(x))

using namespace std;
typedef long long LL;

const int maxn=300;
const int h=1e9+7;

LL dp[maxn+5][maxn+5];
char s[maxn+5];
int n;

bool match(int i,int j)
{
    if (s[i]==( && s[j]==)) return true;
    if (s[i]==[ && s[j]==]) return true;

    return false;
}

LL DP(int l,int r)
{
    if (dp[l][r]!=-1) return dp[l][r];
    if (l>=r) return dp[l][r]=0;
    if (s[l]==) || s[l]==]) return dp[l][r]=DP(l+1,r);

    dp[l][r]=DP(l+1,r);
    for (int k=l+1;k<=r;++k)
    {
        if (match(l,k))
            dp[l][r]=(dp[l][r]+(DP(l+1,k-1)+1)*(DP(k+1,r)+1)%h)%h;
    }

    return dp[l][r];
}

int main(void)
{
    #ifdef ex
    freopen ("../in.txt","r",stdin);
    //freopen ("../out.txt","w",stdout);
    #endif

    scanf("%d",&n);
    scanf("%s",s+1);

    clr(dp,-1);
    LL ans=DP(1,n);
    printf("%lld\n",ans);
}

 

以上是关于UESTC 1321 柱爷的恋爱 (区间DP)的主要内容,如果未能解决你的问题,请参考以下文章

CDOJ 1330 柱爷与远古法阵高斯消元,卡精度

UESTC 电子科大专题训练 DP-N

UESTC 电子科大专题训练 DP-E

uestc 94(区间更新)

UESTC - 1137 数位DP

UESTC - 1724 GCD区间求和