• 括号匹配(二)


    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=15

    思路:动态规划

    使用二维数组dp保存中间结果,其中dp[i][j]保存的是使得括号子序列s[i]s[i+1]...s[j]正确需补全的最少括号数(以下称之为N(i,j))。

    对于子序列长度为1的情况,即(,),[,]四种情况,显然有N=1. 即dp[i][i]=1. 

    对于子序列长度为n的情况(s[i]s[i+1]...s[j], j-i+1=n),N(i,j)为集合S中的最小值。

    集合S的构造过程:

    0) 将S置为空集

    1) 若(s[i]='['且s[j]=']')或(s[i]='('且s[j]=')'),则将N(i+1,j-1)加入S中. 

    特殊地,当i+1=j时(即s[i]s[j]为"[]"或"()"时),有i+1>j-1且(i+1)-(j-1)=1,因此在预处理时需赋值dp[i][i-1]=0. 

    2) 将N(i,k)+N(k,j)加入S中(其中i≤k≤j),即将s[i]...s[j]分割为2个子串,将两个子串的N相加即为s[i]...s[j]可能取到的一个N值.

    S的计算使用了长度为1,2...n-1的所有s[i]...s[j]的子序列N值。

    随着n的增长,dp中的值也被迭代更新,当子序列成长到整个s时,输出dp[1][s.length]即为s的最小N值.

    参考代码(来源:http://hi.baidu.com/3bian/blog/item/56adfa3f17024ef4828b13d8.html):

    #include <iostream>
    #include
    <string>
    #include
    <climits>

    using namespace std;
    const int MAX=100;
    int dp[MAX][MAX];

    int main()
    {
    int n;
    cin
    >>n;
    while (n--){
    string s;
    cin
    >>s;
    int n=s.length();
    for(int i=1;i<=n;i++)
    dp[i][i
    -1]=0;
    for(int i=1;i<=n;i++)
    dp[i][i]
    =1;
    for(int k=1;k<=n-1;k++) // k = 区间长度
    {
    for(int i=1;i<=n-k;i++) // i = 区间左界(包含)
    {
    int j=i+k; // j = 区间右界(不包含)
    dp[i][j]=INT_MAX;
    if(s[i-1]=='(' && s[j-1]==')' || s[i-1]=='['&& s[j-1]==']')
    dp[i][j]
    =dp[i+1][j-1];
    for(int p=i;p<j;p++)
    {
    if(dp[i][p]+dp[p+1][j]<dp[i][j]) dp[i][j]=dp[i][p]+dp[p+1][j];
    }

    }
    }
    cout
    <<dp[1][s.length()]<<endl;
    }
    return 0;
    }
  • 相关阅读:
    剑指Offer_08_跳台阶
    剑指Offer_07_斐波那契数列
    HDU 4283 You Are the One
    1B. Spreadsheets
    1A Theatre Square
    HDU 2476 String painter(记忆化搜索, DP)
    LightOJ 1422 Halloween Costumes(记忆化搜索)
    POJ 1651 Multiplication PuzzleDP方法:
    POJ 2955 Brackets (区间DP)
    HDU 5452 Minimum Cut
  • 原文地址:https://www.cnblogs.com/mdyang/p/2034530.html
Copyright © 2020-2023  润新知