您的位置:首页 > 产品设计 > UI/UE

UESCTC-2016dp专题 D 柱爷的恋爱

2016-05-13 23:48 561 查看

柱爷的恋爱

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

题目链接
http://acm.uestc.edu.cn/#/contest/show/96
Description

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

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

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

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

Input

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

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

数据保证:

1≤N≤3001≤N≤300

Output

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

Sample input and output

Sample InputSample Output
4
()[]

3

3
())

2

Hint

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

如果S是合法序列,那(S)和[S]也是合法序列;

如果A和B都是合法序列,那么AB也是合法序列.

例如,下面的字符串都是合法序列:

(), [], (()), ([]), ()[], ()[()]

题意

给你一个字符序列,对他进行删除操作,可以不删,但不能全删,问最后得到合法序列的删除方法数

思路

区间dp,定义dp[l][r]为处理完[l,r]区间后得到的合法序列的个数,考虑转移方程,可由两个状态转移而来:

1.删除第l个括号,则此时dp[l][r]=dp[l+1][r]

2.不删除第l个括号,则需要在后面枚举与其配对的括号,将两个区间分别操作,将结果相乘即可。

注意不要爆int了。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int maxn=300+7;
const int mod=1000000007;
int n;
string s;
long long int dp[maxn][maxn];

bool match(int l,int r)  //匹配括号
{
if((s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']'))
return true;
return false;
}
long long int dfs(int l,int r)
{
if(~dp[l][r]) return dp[l][r];
long long int &ans=dp[l][r]=0;
if(l>r) return ans=1;
if(l==r) return ans=1;
ans=dfs(l+1,r);   //删除括号
ans%=mod;
for(int i=l;i<=r;i++){   //枚举配对
if(match(l,i)){
ans+=dfs(l+1,i-1)*dfs(i+1,r);
ans%=mod;
}
}
return ans%mod;
}
int main()
{
scanf("%d",&n);
cin>>s;
memset(dp,-1,sizeof(dp));
long long int ans=(dfs(0,n-1)-1)%mod;
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: