【poj 1141】Brackets Sequence 经典的区间dp

时间:2021-10-15 08:16:33

定义f[i][j]表示要使i到j这一段合法最少需要多少加入多少个括号,不难写出转移

1.l==r 至少添加一个所以f[i][j]=1

2.l==r-1&&s[l]==s[r]不用加

3.s[l]==s[r]  min(x,dfs(l+1,r-1))两边不加、

4.min( dfs(l,i)+dfs(i+1,r))很好理解把

至于输出的话 ,怎么转移就怎么输出吧

!!!!!!!!!结尾必须输出一个‘’\n‘’也是坑的要死

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 102
#define inf 0x3f3f3f3f
using namespace std;
int f[maxn][maxn],n;
char s[maxn*3];
bool check(int x,int y){
	if(s[x]=='('&&s[y]==')')return true;
	if(s[x]=='['&&s[y]==']')return true;
	return false;
}
int dfs(int l,int r){
	int& x=f[l][r];
	if(l>r||(r-l==1&&check(l,r)))return x=0;
	if(l==r)return x=1;
	if(x!=inf)return x;
	if(check(l,r))x=min(x,dfs(l+1,r-1));
	for(int i=l;i<r;i++)x=min(x,dfs(l,i)+dfs(i+1,r));
	return x;
}
void print(int l,int r){
	if(r-l==1&&check(l,r)){
		if(s[l]=='(')printf("()");
		else printf("[]");return;
	}
	if(l==r&&f[l][r]==1){
		if(s[l]=='('||s[l]==')')printf("()");
		else printf("[]");return;
	}
	if(check(l,r)&&f[l][r]==f[l+1][r-1]){
		if(s[l]=='(')printf("(");else printf("[");
		print(l+1,r-1);
		if(s[r]==')')printf(")");else printf("]");return;
	}
	for(int i=l;i<=r;i++)if(f[l][r]==f[l][i]+f[i+1][r]){
		print(l,i);print(i+1,r);return;
	}
}
int main(){
	scanf("%s",s+1);n=strlen(s+1);
	memset(f,inf,sizeof(f));
	dfs(1,n);
	print(1,n);
	printf("\n");
	return  0;
}