区间dp的题.
思路
可先用stake将每个位置的括号的匹配找出来,我们把他叫love数组
即
lovei=jlovej=ilovei=jlovej=i
(当然他们匹配) 我们可以开一个数组叫dp[i][j][0/1/2][0/1/2]
表示在左端点为i右端点为j左端点染了0/1/2右端点染了0/1/2时的方案数
分类讨论
- 当二者相邻,dp[l][r][0][1]=dp[l][r][0][2]=dp[l][r][1][0]=dp[l][r][2][0]=1;dp[l][r][0][1]=dp[l][r][0][2]=dp[l][r][1][0]=dp[l][r][2][0]=1;
- 否则,当二者匹配
for i=0,i−>2,i++for j=0,j−>2;j++if(i!=1)dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r−1][i][j]);if(j!=1)dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r−1][i][j]);if(j!=2)dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r−1][i][j]);if(i!=2)dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r−1][i][j]);for i=0,i−>2,i++for j=0,j−>2;j++if(i!=1)dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r−1][i][j]);if(j!=1)dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r−1][i][j]);if(j!=2)dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r−1][i][j]);if(i!=2)dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r−1][i][j]);
二者不匹配
for(LL i=0;i<=2;i++)
for(LL j=0;j<=2;j++)
for(LL k=0;k<=2;k++)
for(LL v=0;v<=2;v++)
{
if(!((k==1&&v==1)||(k==2&&v==2)))
dp[l][r][i][j]=((dp[l][loser][i][k]*dp[loser+1][r][v][j])%mod+dp[l][r][i][j]);for(LL i=0;i<=2;i++) for(LL j=0;j<=2;j++) for(LL k=0;k<=2;k++) for(LL v=0;v<=2;v++) { if(!((k==1&&v==1)||(k==2&&v==2))) dp[l][r][i][j]=((dp[l][loser][i][k]*dp[loser+1][r][v][j])%mod+dp[l][r][i][j]);然后dfs记忆化就行了.
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL dp[744][744][3][3];
LL b[703];
LL love[703];
LL num=0;
const LL mod = 1000000007;
LL n;
void st()
{
stack<LL>s;
for(LL i=1;i<=n;i++)
{
if(b[i]==1) s.push(i);
else
{
love[s.top()]=i;
love[i]=s.top();
s.pop();
}
}
}
void dfs(LL l,LL r)
{
if(l==r-1)
{
dp[l][r][0][1]=dp[l][r][0][2]=dp[l][r][1][0]=dp[l][r][2][0]=1;
return;
}
if(love[l]==r)
{
dfs(l+1,r-1);
for(LL i=0;i<=2;i++)
for(LL j=0;j<=2;j++)
{
if(i!=1)
dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;
if(j!=1)
dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;
if(j!=2)
dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;
if(i!=2)
dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;
}
return;
}
else
{
LL loser=love[l];
dfs(l,loser);
dfs(loser+1,r);
for(LL i=0;i<=2;i++)
for(LL j=0;j<=2;j++)
for(LL k=0;k<=2;k++)
for(LL v=0;v<=2;v++)
{
if(!((k==1&&v==1)||(k==2&&v==2)))
dp[l][r][i][j]=((dp[l][loser][i][k]*dp[loser+1][r][v][j])%mod+dp[l][r][i][j])%mod;
}
return;
}
}
int main()
{
string a;
cin>>a;
for(LL i=0;i<a.size();i++)
{
if(a[i]=='(')
b[i+1]=1;
else
b[i+1]=0;
}
n=a.size();
st();
dfs(1,n);
LL ans=0;
for(LL i=0;i<=2;i++)
for(LL j=0;j<=2;j++)
{
ans+=dp[1][n][i][j]%mod;
ans%=mod;
}
cout<<ans;
}