poj1141区间dp路径记录

路径记录,用a【i】【j】记录dp【i】【j】这个状态来源于哪里

思路:dp[i][j]表示从区间i到区间j使其所以括号匹配需要补上的最少括号数,那么当出现一个括号时,首先考虑它不与后面匹配的情况,那么需要加一个相对应的括号,让之匹配dp[i][j]=dp[i+1][j]+1;

然后再考虑,若是后面有括号可以让它匹配的情况,那么假设i<k<=j,当s[i]=='('&&s[k]==')'的时候,考虑动态转移,dp[i][j]=dp[i+1][k-1]+dp[k+1][j]

同时把a【i】【j】设为k,因为括号序列最少添加的括号就是,总括号数减去括号的最大匹配数,也就是我们只需用找出所有可以匹配的括号,以及他们对应括号,把他们设为匹配的,输出时,遇见匹配 的直接输出,没有匹配的加一个左括号或右括号。

///本题感觉还没有那么好,慢慢体会吧

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;

char s[10009];
int f[1009][1009],a[1009][1009],n;
bool b[1009]={false};
void dw(int l,int r)
{
	if (l>=r) return ;
	if (a[l][r]==-1) dw(l+1,r);
	else 
	{
		b[l]=true;b[a[l][r]]=true;
		dw(l+1,a[l][r]-1);
		dw(a[l][r]+1,r);
	}
}//标记是否匹配括号
int main()
{
	while (gets(s))
	{
		n=strlen(s);
		//if (n==0) {printf("\n");continue;}
		memset(f,0,sizeof(f));
		memset(a,-1,sizeof(a));
		memset(b,false,sizeof(b));
		for (int i=n-1;i>=0;i--)
		{
			f[i][i]=1;
			for (int j=i+1;j<n;j++)
			{
				f[i][j]=f[i+1][j]+1;
				for (int l=i+1;l<=j;l++)
				if ((s[i]=='('&&s[l]==')')||(s[i]=='['&&s[l]==']'))
				if (f[i][j]>f[i+1][l-1]+f[l+1][j])//方程
				{
					f[i][j]=f[i+1][l-1]+f[l+1][j];
					a[i][j]=l;
				}
			}
		}
		dw(0,n-1);
		for (int i=0;i<n;i++) if (b[i]) printf("%c",s[i]);
		else if (s[i]=='('||s[i]==')') printf("()");else printf("[]");//如果没有匹配直接输出
		printf("\n");
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值