UVa 1626 Brackets sequence (动态规划)

题意:用最少的括号将给定的字符串匹配,输出最优解。可能有空行。

思路:dp。

dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么

如果区间左边是(或[,表示可以和右边的字符串匹配,枚举中间断点k,如果str[i]==str[k]则dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k+1][j])表示不需要加入新的括号,也可以插入新的括号则dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]+1)。

如果区间最左边字符是)或],那么它不可能和右边字符串匹配,状态转移为dp[i][j]=min(dp[i][j],dp[i+1][j]+1)

每次转移的时候记录一下转移路径,最后dfs输出即可。

注意可能有空串,所以要用gets。但是在题中每行读入之间有空行,所以要多用一个gets来吃掉这个空行,否则会出错。

建议交UVa,数据比较强。POJ和ZOJ数据较弱,我最初的代码在POJ和ZOJ都过了,UVa却一直TLE。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
#define INF 10000000
#define LL long long
using namespace std;
int f[105][105];
int flag[105][105];
int pos[105][105];
bool vis[105][105];
char str[105];
int dp(int L,int R)
{
    if(L>R) return 0;
    if(vis[L][R]) return f[L][R];
    vis[L][R]=true;
    f[L][R]=INF;
    if(str[L]==‘(‘||str[L]==‘[‘)
    {
        for(int i=L; i<=R; ++i)
        {
            if((str[L]==‘(‘&&str[i]==‘)‘)||(str[L]==‘[‘&&str[i]==‘]‘))
            {
                int sx=dp(L+1,i-1),sy=dp(i+1,R);
                if(f[L][R]>sx+sy)
                {
                    f[L][R]=sx+sy;
                    flag[L][R]=-1;
                    pos[L][R]=i;
                }
            }
            int dx=dp(L+1,i),dy=dp(i+1,R);
            if(f[L][R]>dx+dy+1)
            {
                f[L][R]=dx+dy+1;
                flag[L][R]=1;
                pos[L][R]=i;
            }
        }
    }
    else
    {
        int sx=dp(L+1,R);
        if(f[L][R]>sx+1)
        {
            f[L][R]=sx+1;
            flag[L][R]=1;
            pos[L][R]=L;
        }
    }
    return f[L][R];

}
void output(int L,int R)
{
    if(L<=R)
    {
        int p=pos[L][R];
        if(flag[L][R]<0)
        {
            putchar(str[L]);
            output(L+1,p-1);
            putchar(str[p]);
            output(p+1,R);
        }
        else
        {
            if(str[L]==‘)‘||str[L]==‘]‘)
            {
                if(str[L]==‘)‘) putchar(‘(‘);
                else putchar(‘[‘);
                putchar(str[L]);
                output(L+1,R);
            }
            else
            {
                putchar(str[L]);
                output(L+1,p);
                if(str[L]==‘(‘) putchar(‘)‘);
                else putchar(‘]‘);
                output(p+1,R);
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    getchar();
    while(T--)
    {
        gets(str);
        gets(str);
        memset(vis,0,sizeof(vis));
        int L=strlen(str);
        dp(0,L-1);
        output(0,L-1);
        putchar(‘\n‘);
        if(T) putchar(‘\n‘);
    }
    return 0;
}

UVa 1626 Brackets sequence (动态规划)

时间: 2024-10-13 23:24:41

UVa 1626 Brackets sequence (动态规划)的相关文章

uva 1626 Brackets Sequence ?(动态规划)

状态表示方法:d[ i ][ j ]表示的是一条序列的开始和结束: 状态定义:d[ i ][ j ]表示字串s[ i~j ] 需要添加的数量. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; char s[105]; int d[105][105]; bool match(char ch1,char ch2) { if((ch1=='['&&am

1626 - Brackets sequence——[动态规划]

Let us define a regular brackets sequence in the following way: Empty sequence is a regular sequence. If S is a regular sequence, then (S) and [S] are both regular sequences. If A and B are regular sequences, then AB is a regular sequence. For exampl

UVA 2451 Brackets sequence

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=452 用dp[i][j] 记录一段序列,starts from index i, ends with index j,需要添加的char的个数.对于一段序列i~j,如果i, j 配对的话,那么dp[i][j]=dp[i+1][j-1].

1626 - Brackets sequence(DP)

和前面一样,要注意状态的枚举顺序,边界是d[i+1][i] = 0 和d[i][i] = 1  ,所以枚举的区间应该从小到大,大区间依赖于小区间的最优解 . 然后就是状态的转移,是如何转移的呢? d[i][j]表示字符串i~j的最优解,那么先检查i与j是否匹配,如果匹配,状态转移可以转移到d[i+1][j-1] . 无论是否匹配,状态还都能转移到子区间上:d[i][k] 和 d[k+1][j] ,这是不是就像最优矩阵链乘问题了?  只不过该题对正规括号序列的定义有一条:如果S是正规括号序列,那么

POJ1141 Brackets Sequence (dp动态规划,递归)

本文出自:http://blog.csdn.net/svitter 原题:http://poj.org/problem?id=1141 题意:输出添加括号最少,并且使其匹配的串. 题解: dp [ i ] [ j ] 表示添加括号的个数, pos[ i][ j ] 表示 i , j 中哪个位置分开,使得两部分分别匹配. pos [ i ][ j ] 为-1的时候,说明i, j 括号匹配. 初始值置dp [ i ] [ i ]  = 1; 如果只有一个括号,那么匹配结果必然是差1. 首先判断括号是

[ACM] POJ 1141 Brackets Sequence (区间动态规划)

Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25087   Accepted: 7069   Special Judge Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a re

uva1626 poj 1141 Brackets Sequence 区间dp 打印路径

// poj 1141 Brackets Sequence // 也是在紫书上看的一题,uva就是多了一个t组数据. // 经典区间dp // dp(i,j)表示区间[i,j]内所需要增加的括号数目 // 则分为两种情况 // 一种是s[i]和s[j]是匹配的则 // dp[i][j] = min(dp[i][j],dp[i+1][j-1]) // 另外一种情况是不匹配 // dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]){i<k<j}; // 但是无

POJ1141 Brackets Sequence

Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a regular sequence, then (S) and [S] are both regular sequences. 3. If A and B are regular sequences, then AB is a regular

uva 116 - Unidirectional TSP (动态规划)

第一次做动规题目,以下均为个人理解以及个人方法,状态转移方程以及状态的定义也是根据个人理解,请过路大神指教. 状态:每一列的每一个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ]的指标函数d[ i ][ j ]为从[ i ][ j ]向右出发的可以得到的最小的整数和: 状态转移方程:d[ i ][ j ]=min(d[ i+1 ][ j+1 ][ i-1 ][ j+1 ][ i ][ j+1 ])+a[ i ][ j ]; 其中a[ i ][ j ]为当前位置的数值: 然后