DP练习题:最大括号匹配问题(区间DP)

【题目描述】
给定一个括号字符串,让你求出最大括号匹配的括号数

【思路】
dp[i][j]表示区间i到j中的最大括号匹配数,分析发现,它与小区间的括号问题是相关联的,具有最优子结构性质。这是一个区间dp问题。

比如:假定我们求()))()这个括号串的最大括号匹配数,即f(0, 5)的结果
显然,f(0, 5) = f(0, 1) + f(1, 5)
f(0, 5) = f(0, 2) + f(2, 5)等等。。。我们要求出大区间的结果必须先求出小区间的结果,这就是区间dp的基本思想!

关于区间dp,这是我第一次接触到,同类型的问题还有矩阵链乘
核心就是大区间分成多个小区间,只要把小区间的结果算出,大区间就算出了。遍历顺序是对角线的方向,和以往的有点不同,刚开始在这里也有点难理解

参考代码:

#include
using namespace std;

const int maxn = 100;
string str;
int length;
int dp[maxn][maxn];

int DP()
{
	//base
	for(int i = 0;i <= length - 1;i++)
	{
		dp[i][i] = 0;
	}
	
	for(int len = 1;len <= length - 1;len++)
	{
		for(int i = 0;i <= length - 1;i++)
		{
			int j = len + i;
			if(str[i] == '(' && str[j] == ')')		//即使匹配也不一定就是 dp[i][j] = dp[i + 1][j - 1] + 2;
			{										//可能是这种情况()))() 
				dp[i][j] = dp[i + 1][j - 1] + 2;
			}										//所以还是要进行下面的分区间筛选 
			int max_res = dp[i][j];
			for(int k = i;k < j;k++)
			{
				if(dp[i][k] + dp[k + 1][j] > max_res)
					max_res = dp[i][k] + dp[k + 1][j];
			}
			dp[i][j] = max_res;
		}
	}
	//print dp
	for(int i = 0;i <= length - 1;i++)
	{
		for(int j = 0;j <= length - 1;j++)
		{
			cout << dp[i][j] << " ";
		}
		cout << endl;
	}
	return dp[0][length - 1];
}

int main()
{
	cin >> str;
	length = str.length();
	cout << DP() << endl;
	return 0;
}

这题还可以变一下,就是求括号串的最少添加数,那就是总字符串长度减去最大匹配数就可以了!

你可能感兴趣的:(DP,数据结构与算法,算法)