hrbust 哈理工oj 1834 括号匹配【好题】【floyd+dp】

括号匹配
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 133(51 users) Total Accepted: 39(28 users) Rating:  Special Judge: No
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);
    }
}










你可能感兴趣的:(哈理工oj,1834,hrbust,1834)