【3.29百度笔试编程解析】CodeForces 149D 括号染色问题 dp+dfs好题

题目大意

给一个给定括号序列,给该括号上色,上色有三个要求

1、只有三种上色方案,不上色,上红色,上蓝色

2、每对括号必须只能给其中的一个上色

3、相邻的两个不能上同色,可以都不上色
在这里插入图片描述

题目分析

求0-len-1这一区间内有多少种上色方案,很明显的区间DP

dp[l][r][i][j]表示l-r区间两端颜色分别是i,j的方案数

0代表不上色,1代表上红色,2代表上蓝色

对于l-r区间,有3种情况

1、if(l+1==r) 说明就只有一对,那么

dp[l][r][0][1]=1;
dp[l][r][1][0]=1;
dp[l][r][0][2]=1;
dp[l][r][2][0]=1;

2、if(l与r是配对的)

递归(l+1,r-1)

状态转移

dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod; 

dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod;

dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod;

dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod;

3、if(l与r不配对)

dp[l][r][i][j]=(dp[l][r][i][j]+(dp[l][p][i][k]*dp[p+1][r][q][j])%mod)%mod;

上代码走起

import sys
s=input()
num=strlen=len(s)  
tmp=[0 for i in range(num)] #记录左括号的位置
match=[0 for i in range(num)] #记录右匹配的位置
dp=[[[[0 for i in range(3)]for i in range(3)]for i in range(num)]for i in range(num)]
# 由内向外建立多维dp 数组的形式
# dp=np.arange(3*3*num*num).reshape(num,num,3,3)
mod=1000000007  
def getmatch(len) : 
    p=0
    for i in range(len):
        if(s[i]=='(') :
            tmp[p]=i
            p=p+1
        else:
            match[i]=tmp[p-1]  
            match[tmp[p-1]]=i  
            p=p-1
def dfs(l, r):  
    if (l+1==r):  #边界条件
        dp[l][r][0][1]=1 
        dp[l][r][1][0]=1 
        dp[l][r][0][2]=1
        dp[l][r][2][0]=1
        return   
    if(match[l]==r):    #如果匹配的话方案数相加
        dfs(l+1,r-1) 
        for i in range(3):
            for j in range(3):
                if(j!=1):  
                    dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod;  
                if(i!=1):
                    dp[l][r][1][0]=(dp[l][r][1][0]+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:    #否则方案数相乘,乘法原理
        p=match[l]
        dfs(l,p)  
        dfs(p+1,r) 
        for i in range(3):
            for j in range(3):
                for k in range(3):
                    for q in range(3):
                        if not((k==1 and q==1) or (k==2 and q==2)):
                             dp[l][r][i][j]=(dp[l][r][i][j]+(dp[l][p][i][k]*dp[p+1][r][q][j])%mod)%mod
if __name__=='__main__':
    getmatch(strlen)
    dfs(0,strlen-1) 
    ans=0  
    for i in range(3):
        for j in range(3):
            ans=(ans+dp[0][strlen-1][i][j])%mod;     
    sys.stdout.write(str(ans))

python创建多维数组的3种方式

#coding=utf-8
import numpy as np
#1
image =[[(col+1)*(row+1) for col in range(5)] for row in range(3)]
a = np.array(image)
print(a)
 
#2
new_image =np.zeros((3,5))
 
#3
b = np.arange(12).reshape(3,4)
print(b)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和你在一起^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值