codeforces 149D Coloring Brackets (区间DP + dfs)
2024-08-29 09:54:40
题目链接:
codeforces 149D Coloring Brackets
题目描述:
给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的。
1,每个括号只有三种选择:涂红色,涂蓝色,不涂色。
2,每对括号有且仅有其中一个被涂色。
3,相邻的括号不能涂相同的颜色,但是相邻的括号可以同时不涂色。
解题思路:
这个题目的确是一个好题,无奈我太蠢,读错题意。以为(())这样的括号序列在涂色的时候,第一个括号与第三个括号也可以看做是一对。这样的话还要统计合法的括号匹配数目,还要计算涂色的方案。然后想了好久好久。最后发现并不是这样的,给出的括号序列,括号的匹配都是固定的,也就是说只需要给这些固定匹配的括号按照上面限制涂色就好啦。
可以定义 dp[l][r][x][y] 表示区间 [l, r] 在左端点涂x色,右端点涂y色的情况下的方案数。其中0代表不涂色, 1代表涂红色, 2代表涂蓝色。
窝们可以把括号序列可以分为两类分别进行状态转移:
括号套括号,状态转移是:dp[l][r][x][y] += dp[l+1][r-1][x'][y'] (0<=x'<3, x'!=x, 0<=y'<3, y!=y')
多个匹配串连起来,转台转移是:dp[l][r][x][y] += dp[l][nu][x'][y'] * dp[nu][r][x''][y''] (nu是l对应的另一边括号)
当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;
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef __int64 LL;
const LL mod = ;
const LL maxn = ;
LL dp[maxn][maxn][][], match[maxn], tep[maxn]; void get_macth (char a[])
{
int p = ;
for (int i=; a[i]; i++)
{
if (a[i] == '(')
tep[p ++] = i;
else
{
match[i] = tep[p-];
match[tep[p-]] = i;
p --;
}
}
} void dfs (int l, int r)
{
if (l + == r)
{
dp[l][r][][] = ;
dp[l][r][][] = ;
dp[l][r][][] = ;
dp[l][r][][] = ;
return ;
} else if (match[l] == r)
{
dfs (l+, r-);
for (int i=; i<; i++)
for (int j=; j<; j++)
{
if (j != )
dp[l][r][][] = (dp[l][r][][] + dp[l+][r-][i][j]) % mod;
if (i != )
dp[l][r][][] = (dp[l][r][][] + dp[l+][r-][i][j]) % mod;
if (j != )
dp[l][r][][] = (dp[l][r][][] + dp[l+][r-][i][j]) % mod;
if (i != )
dp[l][r][][] = (dp[l][r][][] + dp[l+][r-][i][j]) % mod;
}
return ;
} else
{
int nu = match[l];
dfs (l, nu);
dfs (nu+, r); for (int i=; i<; i++)
for (int j=; j<; j++)
for (int x=; x<; x++)
for (int y=; y<; y++)
if (!(x==&&y== || x==&&y==))
dp[l][r][i][j] = (dp[l][r][i][j] + dp[l][nu][i][x]*dp[nu+][r][y][j]) % mod;
} } int main ()
{
char s[maxn]; while (scanf ("%s", s) != EOF)
{
memset(dp, , sizeof(dp));
int len = strlen (s);
get_macth (s);
dfs (, len-); LL ans = ;
for (int i=; i<; i++)
for (int j=; j<; j++)
ans = (ans + dp[][len-][i][j]) % mod;
printf ("%I64d\n", ans); }
return ;
}
最新文章
- IOS开发之视图和视图控制器
- Android 调用浏览器和嵌入网页
- D&;F学数据结构系列——二叉排序树
- jQuery对select标签的常用操作
- 【学习笔记】【C语言】自增自减
- Stage3D学习笔记(二):使用GPU绘制一个三角形
- BAT互联网公司是如何内部推荐的?
- python之面向对象那点事
- fetch()的用法
- AT24C02使用详解
- Unity3d_GUI_2__(能量条的学习)
- Linux 桌面玩家指南:05. 发博客必备的图片处理和视频录制神器
- 如何解决fiddler的响应显示乱码问题
- 通过pycharm将代码push到远程仓库
- 今天这篇内容分享Apache由http自动跳转到https的多种方法
- 045 RDD与DataFrame互相转换
- js封装Cookie操作 js 获取cookie js 设置cookie js 删除cookie
- python计算机硬件基础以及变量常量常量池,解释器编译器比较,python的两种运行方式
- Python基础一数据类型之数字类型
- SQLite3动态库、静态库编译
热门文章
- snip_opencv环境配置和测试程序
- 赵雅智_SimpleCursorAdapter
- all rows from client_id can grow infinitely compared to a single node when hashing by client_id
- Smoke testing (software)
- 移动web开发适配rem
- (linux)tasklet
- IntelliJ IDEA 2017 反向代理工具新方法激活
- ExtJS常用代码集合
- WAS:节点不同步问题
- BDB c++例子,从源码编译到运行