CDOJ 1321柱爷的恋爱 (区间dp)

柱爷的恋爱

Time Limit: 1000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

她手里有刚刚收到从远方的括号序列(仅包含( ) [ ]的序列),然而序列已经是一团乱麻,不堪入目,柱爷看到她坐在位子掩面哭泣,便上前安慰一番,她向柱爷提出自己的"无理"申请.

她"蛮横"地要求柱爷计算出:删去这个括号序列的一个子集(不可以把整个括号序列都删去,那可是她的心爱之物;可以不完全删;子集可能是不连续的;子集可能为∅),使得这个括号序列合法的方案数.

这个方案数可能很大,所以她只要求柱爷计算出这个方案数%1000000007就好了(她心疼柱爷,不想让柱爷打高精度).

你能帮柱爷解决这个恋爱中的小小问题吗?

Input

第一行一个整数 N N,表示括号序列的长度

接下来一行包含一个长度为 N N的括号序列字符串

数据保证:

  • 1N300 1≤N≤300

Output

一个正整数,表示柱爷要回答她的数.

Sample input and output

Sample Input Sample Output
4
()[]
3
3
())
2

Hint

合法的括号序列定义如下:

  • 如果S是合法序列,那(S)和[S]也是合法序列;
  • 如果A和B都是合法序列,那么AB也是合法序列.
  • 例如,下面的字符串都是合法序列:
  • (), [], (()), ([]), ()[], ()[()]

Source

2016 UESTC Training for Dynamic Programming


题解:看到括号匹配问题,第一时间就想到是区间dp,但是有关方案数之间的关系想了好久,最后总算是想出来了,枚举每一对相匹配的括号,对于每一对括号,组合数是括号内的合法删除方案数*括号外的合法删除方案数,当i=j时,必然没有一对括号,因此必须要全部删除才合法

1.当i=j dp[i][j]=1;

2当i!=j &i,k为一对匹配括号,dp[i][j]=res+dp[i+1][k-1]+dp[k+1][j];

3其他情况 dp[i][j]=dp[i+1][j];

代码如下

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

char s[305];
typedef long long LL;
LL dp[305][305];

LL solve(LL i,LL j)
{
    if(dp[i][j]>=0)
        return dp[i][j];
    if(i>=j)
        return 1;
    LL res=solve(i+1,j);
    char aim='0';
    if(s[i]=='(')
        aim=')';
    else if(s[i]=='[')
        aim=']';
    if(aim!='0')
    {
        for(LL q=i+1;q<=j;q++)
        {
            if(s[q]==aim)
                res=max(res,res+solve(i+1,q-1)*solve(q+1,j))%1000000007;
        }
    }
    dp[i][j]=res;
    return res%1000000007;
}
int main()
{
    long long n;
    cin>>n;
    for(LL i=0;i<=n;i++)
    {
        for(LL j=0;j<=n;j++)
            dp[i][j]=-1;
    }
    //c har s[305];
    cin>>s;
    LL ans=solve(0,n-1)%1000000007-1;
    cout << ans << endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值