您的位置:首页 > 产品设计 > UI/UE

poj1141Brackets Sequence(区间dp括号匹配打印路径)

2016-04-26 11:29 465 查看
这道题困扰了我一阵,因为之前只会求最大匹配,不会打印路径,后来发现用递归可以实现,首先我们知道前面定义dp [ i ] [ j ] 为串中第 i 个到第 j 个括号的最大匹配数目

那么假如我们知道任意 i 到 j 从哪儿插入分点使得匹配添加括号最少。那么我们定义pos【i】【j】表示 i 到 j 从哪儿分开使得匹配添加括号最少,如果i和j匹配我们可以让pos【i】【j】=-1;

我们发现在我们之前更新dp [ i ] [ j ] 的时候如果中间点k使得if ( dp [ i ] [ k ] + dp [ k+1 ] [ j ] >= dp [ i ] [ j ] ) ,那么我们从k分开可以让添加的括号最少,最坑的一点是可能有空串,用scanf不行,用gets(s)当s是string型的时候不行,当用gets(s),s是char型的时候可以,当用getline(cin,s)的时候s为string的时候可以,还是太菜

#include <iostream>
#include <string.h>

using namespace std;

string s;
int pos[105][105],dp[105][105];

void show(int i,int j)
{
if(i>j)
return;
if(i==j)//这里是指当递归到只剩一个的时候,如何输出
{
if(s[i]=='('||s[i]==')')
cout<<"()";
else cout<<"[]";
}
else
{
if(pos[i][j]==-1)//匹配
{
cout<<s[i];
show(i+1,j-1);
cout<<s[j];
}
else//更新
{
show(i,pos[i][j]);
show(pos[i][j]+1,j);
}
}
}

int main()
{
while(getline(cin,s))
{
memset(dp,0,sizeof(dp));
memset(pos,0,sizeof(pos));
for(int i=1;i<s.size();i++)
for(int j=0,k=i;k<s.size();j++,k++)
{
if(s[j]=='('&&s[k]==')'||s[j]=='['&&s[k]==']')//如果匹配到,
{
dp[j][k]=dp[j+1][k-1]+2;
pos[j][k]=-1;
}
for(int m=j;m<k;m++)
{
if(dp[j][m]+dp[m+1][k]>=dp[j][k])//这里是更新
{
dp[j][k]=dp[j][m]+dp[m+1][k];
pos[j][k]=m;
}
}
}
show(0,s.size()-1);
cout<<endl;
s.clear();

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 区间dp