NYOJ 15 括号匹配(二) dp

题目连接:check here~

题意是说给一个字符串,包含‘(‘,‘)‘,‘[‘,‘]‘四种字符,判断至少需要添加几个字符使所给字符串括号匹配。

区间型动态规划,设dp[i][j]表示在字符串s中i位置到j位置所需要添加的最少的字符(i <= j)

有两种情况:

1、dp[i][j] = dp[i+1][j] + 1;

表示:在i到j之间没有与s[i]相匹配的括号,则必须添加一个字符来与之匹配,问题就转化为:从i+1位置到j位置所需要添加的最少的字符+1。

2、dp[i][j] = min{ dp[i+1][k-1] + dp[k+1][j] }; (i < k <= j)

表示:在i到j之间找到一个k使得s[i]与s[k]相匹配,则问题就转化为求:从i+1到k-1所需要添加的最少字符个数+从k+1到j之间所需要添加的最少字符个数(即dp[i+1][k-1] + dp[k+1][j])。因为k可能有多个,所以在其中所有的k的情况中取最小的。

求出两种情况后,这两种之间再求最小值,可以直接把dp[i][j]的初始值赋为dp[i+1][j]+1,然后进行第二种情况的求解

动态转移方程出来之后需要判断写几层循环和每层循环的起点和终点,从方程可以看出,有3层循环(i, j, k),对于dp[i][j]来说,必须先求出i之后的行的前j个,所以有两种循环的方法,我用的是第二种方法,感觉相对好理解。如下图。

方式一:从左往右更新                         方式二:从下往上更新

初始化:只有一个字符时至少添加一个字符,所以dp[i][i] = 1;

附上AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[110][110];
char s[110];
bool judge(int i, int j)//判断i,j位置是否匹配
{
    if ((s[i]==‘(‘ && s[j]==‘)‘) || (s[i]==‘[‘ && s[j]==‘]‘))
        return true;
    else return false;
}
int main()
{
	int n;
	scanf("%d", &n);
	while (n--)
	{
	    scanf("%s", s+1);
	    memset(dp, 0, sizeof(dp));
	    int len = strlen(s+1);
	    for (int i=1; i<=len; i++) dp[i][i] = 1;
	    for (int i=len-1; i>=1; i--)//从下至上
	    {
	        for (int j=i; j<=len; j++)//从左至右
	        {
	            dp[i][j] = dp[i+1][j]+1;//赋初值为第一种情况
                for (int k=i+1; k<=j; k++)
                {
                    if (judge(i, k))
                        dp[i][j] = min(dp[i][j], dp[i+1][k-1]+dp[k+1][j]);
                }
	        }
	    }
	    printf("%d\n", dp[1][len]);
	}
	return 0;
}

NYOJ 15 括号匹配(二) dp

时间: 2024-10-08 19:01:04

NYOJ 15 括号匹配(二) dp的相关文章

nyoj 15 括号匹配(二)

括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来.如:[]是匹配的([])[]是匹配的((]是不匹配的([)]是不匹配的 输入 第一行输入一个正整数N,表示测试数据组数(N<=10)每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不

hihoCoder 1300 展胜地的鲤鱼旗 (括号匹配问题 dp)

#1300 : 展胜地的鲤鱼旗 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 岩手县北上市的「北上市立公园展胜地」,是陆奥国三大樱花名所之一.每年的四月中旬到五月初,这里都会举办盛大的祭奠.除了可以在盛开的樱花步道上乘坐观光马车徐行.还有横跨北上川上的鲤鱼旗,河畔还有当地特有的为祭奠祖先而编创的北上鬼剑舞. 假设,我们用一个包含 '(', ')'的括号字符串来区别每面鲤鱼旗的方向.一段括号序列被称为合法的,当且仅当满足两个条件:一.对于整个序列,左括号数量等于右括

poj 2955 Brackets 括号匹配 区间dp

题意:最多有多少括号匹配 思路:区间dp,模板dp,区间合并. 对于a[j]来说: 刚開始的时候,转移方程为dp[i][j]=max(dp[i][j-1],dp[i][k-1]+dp[k][j-1]+2), a[k]与a[j] 匹配,结果一组数据出错 ([]]) 检查的时候发现dp[2][3]==2,对,dp[2][4]=4,错了,简单模拟了一下发现,dp[2][4]=dp[2][1]+dp[2][3]+2==4,错了 此时2与4已经匹配,2与3已经无法再匹配. 故转移方程改为dp[i][j]=

imooc数据结构探险-栈篇 栈应用括号匹配二 由群友启发改良james_yuan老师算法

如图所示 引用群友内容 //老师代码有点麻烦了,不用声明两个mystack的,直接判断是否是左括号, //是的话就在mystack中push另一半括号:如果是右括号且又不是需要的括号, //就直接打印不匹配,如果是需要的右括号,就pop掉左括号.最后看mystack中栈顶是否为0,为0则打印括号匹配 /* 老师最后一点其实错了,default 其实没有必要写,只要把pNeedStack->pop(currentNeed)改为 if(!pNeedStack->pop(currentNeed))

[poj2955]括号匹配(区间dp)

解题关键:了解转移方程即可. 转移方程:$dp[l][r] = dp[l + 1][r - 1] + 2$ 若该区间左右端点成功匹配.然后对区间内的子区间取max即可. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namesp

poj2955括号匹配 区间DP

类似于上一篇博文. #include<stdio.h> #include<string.h> const int maxn = 120; char s[maxn]; int dp[maxn][maxn]; int max(int x,int y) { return x>y?x:y; } int main() { int i,j,k; while(scanf("%s",s)) { if(strcmp(s,"end")==0) break;

nyoj 2 括号匹配(栈的基本运用)

括号配对问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 现在,有一行括号序列,请你检查这行括号是否配对. 输入 第一行输入一个数N(0<N<=100),表示有N组测试数据.后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于10000,且S不是空串),测试数据组数少于5组.数据保证S中只含有"[","]","(",")"四种字符 输出 每组输入数据的输出占一行,

区间dp 括号匹配 nyoj 15

题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=15 括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来. 如: []是匹配的 ([])[]是匹配的 ((]是不匹配的 ([)]是不匹配的 输入 第一行输入

NYOJ 括号匹配系列2,5

本文出自:http://blog.csdn.net/svitter 括号匹配一:http://acm.nyist.net/JudgeOnline/problem.php?pid=2 括号匹配二:http://acm.nyist.net/JudgeOnline/problem.php?pid=15 之前被这个题目难住,现在看动态规划就顺便过来AC了它.结果发现当年被难住一点也不丢人.. 括号匹配一很简单,就是栈的应用,AC代码: //================================