感想:较好的入门题,关键这里可以让你学到记录路径的方法,也可以算做dp记路径的入门题了吧。
思路: 这题的思路关键在于 (A) 或(B) AB这几种请况,所以在dp的过程中 要找这几种的最小值,
首先 dp[ i ][ i ]肯定是1,因为只有一个单括号的话,必须要来一个括号来进行匹配;
状态转移方程 dp[ i ][ j ] = min(dp[ i ][ z ] +dp[ z ][ j ] ) i<=z<j 如果str[ i ]和str[ j ]是一对匹配的字符串 则->
dp[ i ][ j ] = min(dp[ i+1 ][ j-1 ], dp[ i ][ j ] ); 这里必须明白 无论str[ i ]是否和str[ j ]匹配 都需要去求其分割的结果
比如这种情况就需要 ( ... )( ... )求这2中情况的最小值
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#define min(aa,bb) (aa)>(bb)?(bb):(aa)
#define MAXN 105
#define INF 100000000
using namespace std;
string str;
int size;
int dp[MAXN][MAXN];
int pos[MAXN][MAXN];
void DP()
{
size = str.size();
for(int i=0;i<size;++i)
dp[i][i] = 1;//一个字符的时候必须得匹配另外一个
for(int k=1;k<size;++k)
for(int i=0,j=i+k;j<size&&i<size;++j,++i)
{
dp[i][j] = INF;
if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']'))
{
if(k==1)
{
dp[i][j] = 0;
pos[i][j] = -1;
}
else//这里i+1可能比j-1大,所以需要加个判断
{
dp[i][j] = dp[i+1][j-1];
pos[i][j] = -1;
}
}
for(int e=i;e<j;++e)
if(dp[i][e]+dp[e+1][j]<dp[i][j])
{
dp[i][j] = dp[i][e] + dp[e+1][j];
pos[i][j] = e;
}
}
}
void print(int l,int r)
{
if(l<=r)
{
if(l==r)
{
if(str[l]=='('||str[l]==')')
cout<<"()";
else
cout<<"[]";
}
else
{
if(pos[l][r]==-1)
{
cout<<str[l];
print(l+1,r-1);
cout<<str[r];
}
else
{
print(l,pos[l][r]);
print(pos[l][r]+1,r);
}
}
}
}
int main()
{
cin>>str;
DP();
print(0,str.size()-1);
cout<<endl;
return 0;
}
本文介绍如何使用动态规划解决括号匹配问题,并详细解释了状态转移方程的运用,通过实例展示了算法的实现过程。
4219

被折叠的 条评论
为什么被折叠?



