括号序列 (tyvj P1193) 题解
定义如下规则序列(字符串):1.空序列是规则序列;2.如果S是规则序列,那么(S)和[S]也是规则序列;3.如果A和B都是规则序列,那么AB也是规则序列。 例如,下面的字符串都是规则序列:(),[],(()),([]),()[],()[()] 而以下几个则不是:(,[,],)(,()),([()现在,给你一些由‘(’,‘)’,‘[’,‘]’构成的序列,你要做的,是找出一个最短规则序列,使得给你的那个序列是你给出的规则序列的子列。(对于序列a1,a2,…, 和序列bl,b2,…, ,如果存在一组下标1≤i1<i2<…< ≤m,使得aj= 对一切1≤j≤n成立,那么a1,a2…, 就叫做b1,b2,…, 的子列。
这题比较简单,直接贴代码了。算法代码没有优化,O(n3)的效率。
/*
keep it in mind:代码含义表达清晰。注意备份
*/
//括号序列 tyvj P1193 2011.4.29 PASS 4171ms O(n3)
#include <iostream>
#include <string.h>
//#include <assert.h>
using namespace std;
#define _D_MIN(a,b) ((a)<(b)?(a):(b))
int _gdp[300][300],_gn;
char _gstr[300];
void _fInit()
{
cin >> _gstr;
_gn = strlen(_gstr);
for( int i = 0;i <= _gn;++i )
for( int j = 0;j <= _gn;++j )
_gdp[i][j] = 0; //让后面处理容易一些 不用判断 j-1>=i+1
for( int i = 0;i < _gn;++i )
_gdp[i][i] = 1; //边界
}
int main()
{
_fInit();
for( int l = 1;l < _gn;++l )
for( int i = 0;i+l < _gn;++i )
{
int j = i+l,min = 0x7fffffff;
if( (_gstr[i] == '(' && _gstr[j] == ')') || (_gstr[i] == '[' && _gstr[j]==']' ))
min = _D_MIN(min,_gdp[i+1][j-1]);
for( int k = i;k < j;++k ) min = _D_MIN(min,_gdp[i][k] + _gdp[k+1][j]);
_gdp[i][j] = min;
}
cout << _gdp[0][_gn-1] << endl;
return 0;
}