括号匹配 | ||||||
| ||||||
Description | ||||||
给出一个括号序列括号类型包括'(',')','[',']'求最大的括号匹配数。 | ||||||
Input | ||||||
本题有多组测试数据。每组数据是一个长度不超过100的括号序列。 | ||||||
Output | ||||||
最大的括号匹配数 | ||||||
Sample Input | ||||||
((())) ()()() ([]]) )[)( ([][][) | ||||||
Sample Output | ||||||
6 6 4 0 6 |
直接用两层for的方法来记录匹配括号成功数来求结果的话,并不属于最优解。两层for可以用来判断括号是否匹配,但是不能得到最优匹配数。
既然想到了动态规划,那么最首先需要想到的东西是所有情况都扫到、这里我们这样来完成:
两层for,外层控制匹配长度changdu,内层for控制起始位子i、那么如果我们设j=i+changdu,并且a【i】和a【j】符合括号匹配的情况的话,我们这里可以得到这样的动态规划转移方程:
dp【i】【j】=dp【i+1】【j-1】+1(表示我们得到了一组匹配。)//这里的dp【i】【j】表示从i开始到j的这段子串最优匹配数,(最大匹配数)。
我们这里的思路只能保证把一些个情况列举出来,比如样例中的第一组样例:
((())),在状态转移的过程中,因为中间括号有匹配上,而且在+1的时候,带上了中间匹配上的+1,所以能一直+1,这个加到最后得到的是3,最终结果确实能得到6、但是如果变成了第二组样例那样,()()(),明显+1的时候都是在0上加的,不像上一种情况会在1的基础上+1、那怎么办才行呢?
使用floyd思维递推关系、
如果dp【i】【j】+dp【j】【k】>dp【j】【k】,那么dp【j】【k】=dp【i】【j】+dp【j】【k】、很容易就把问题解决了。
AC代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int dp[101][101];
int main()
{
char a[105];
while(~scanf("%s",a))
{
memset(dp,0,sizeof(dp));
int n=strlen(a);
for(int changdu=1;changdu<n;changdu++)
{
for(int i=0;i+changdu<n;i++)
{
int j=i+changdu;
if(a[i]=='('&&a[j]==')'||a[i]=='['&&a[j]==']')
{
dp[i][j]=dp[i+1][j-1]+1;
}
for(int k=0;k<n;k++)
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
}
printf("%d\n",dp[0][n-1]*2);
}
}