poj1141

题意:给一组小括号与中括号的序列,添加最少的字符,使该序列变为合法序列,输出该合法序列。

分析:dp,f[i][j]表示从i位到j位的序列变为合法序列最少添加多少个字符。

如果匹配st[s]与st[e]匹配,那么f[s][e] = f[s + 1][e - 1];否则f[s][e] = f[s][k] + f[k + 1][e];

我们还要用v[][]记录每个f[s][e]是从哪得来的。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
using namespace std;

#define maxn 300

char st[maxn];
int f[maxn][maxn], v[maxn][maxn];

bool match( char a, char b)
{
if (a == ' ( ' && b == ' ) ' )
return true ;
if (a == ' [ ' && b == ' ] ' )
return true ;
return false ;
}

char other( char a)
{
if (a == ' ( ' )
return ' ) ' ;
if (a == ' [ ' )
return ' ] ' ;
if (a == ' ) ' )
return ' ( ' ;
return ' [ ' ;
}

void output( int s, int e)
{
if (s > e)
return ;
if (s == e)
{
if (st[s] == ' ( ' || st[s] == ' ) ' )
printf(
" () " );
else
printf(
" [] " );
return ;
}
if (v[s][e] == - 1 )
{
putchar(st[s]);
output(s
+ 1 , e - 1 );
putchar(st[e]);
return ;
}
output(s, v[s][e]);
output(v[s][e]
+ 1 , e);
}

int main()
{
// freopen("t.txt", "r", stdin);
if (gets(st) == NULL)
return 0 ;
int len = strlen(st);
memset(f,
- 1 , sizeof (f));
memset(v,
- 1 , sizeof (v));
for ( int i = 0 ; i < len; i ++ )
{
f[i][i]
= 1 ;
f[i
+ 1 ][i] = 0 ;
}
for ( int i = 1 ; i < len; i ++ )
{
for ( int j = 0 ; j < len - i; j ++ )
{
int s = j, e = j + i;
if (match(st[s], st[e]))
f[s][e]
= f[s + 1 ][e - 1 ];
for ( int k = s; k < e; k ++ )
if (f[s][e] > f[s][k] + f[k + 1 ][e] || f[s][e] == - 1 )
{
f[s][e]
= f[s][k] + f[k + 1 ][e];
v[s][e]
= k;
}
}
}
output(
0 , len - 1 );
putchar(
' \n ' );
return 0 ;
}

你可能感兴趣的:(poj)