dp uva1626 括号序列

时间:2021-09-27 08:13:26

题目链接


状态转移

d(i,j)表示子串S[i~j]至少需要加几个括号


递推写法 快

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100+5;
char S[maxn];
int n,d[maxn][maxn];

bool match(char a, char b){
	return (a=='(' && b==')') || (a=='[' && b==']');
}

void dp(){
	for(int i=0; i<n; i++){
		d[i+1][i] = 0;
		d[i][i] = 1;
	}

	for(int i=n-2; i>=0; i--)
		for(int j=i+1; j<n; j++){
			d[i][j] = n;
			if(match(S[i],S[j])) d[i][j] = min(d[i][j],d[i+1][j-1]);
			for(int k=i; k<j; k++){
				d[i][j] = min(d[i][j],d[i][k]+d[k+1][j]);
			}
		}
}

void print(int i,int j){
	if(i>j) return ;
	if(i==j){
		if(S[i]=='(' || S[i]==')') printf("()");
		else printf("[]");
		return;
	}
	int ans = d[i][j];
	if(match(S[i],S[j]) && ans==d[i+1][j-1]) {
		printf("%c",S[i]); print(i+1,j-1); printf("%c",S[j]);
		return ;
	}

	for(int k=i; k<j; k++){
		if(ans == d[i][k]+d[k+1][j]){
			print(i,k); print(k+1,j);
			return;
		}
	} 
}

void readline(char* S){
	fgets(S,maxn,stdin);
}

int main(){
	int T;
	readline(S);
	sscanf(S,"%d",&T);
	readline(S);

	while(T--){
		readline(S);
		n = strlen(S)-1;
		memset(d,-1,sizeof(d));
		dp();
		print(0,n-1);
		printf("\n");
		if(T) printf("\n");
		readline(S);
	}


}

记忆化搜索 慢


#include <bits/stdc++.h>
using namespace std;

const int maxn = 100+5;
char S[maxn];
int n,d[maxn][maxn];

bool match(char a, char b){
	return (a=='(' && b==')') || (a=='[' && b==']');
}

int dp(int i,int j){
	if(i > j) return 0;
	if(i==j) return 1;
	if(d[i][j]>=0) return d[i][j];
	d[i][j] = n;
	if(match(S[i],S[j])) d[i][j] = min(d[i][j],dp(i+1,j-1));
	for(int k=i; k<j; k++)
		d[i][j] = min(d[i][j],dp(i,k)+dp(k+1,j));
	return d[i][j];
}

void print(int i,int j){
	if(i > j) return;
	if(i==j){
		if(S[i]=='(' || S[i]==')') printf("()");
		else printf("[]");
		return; 
	}
	int ans = dp(i,j);
	if(match(S[i],S[j]) && ans==dp(i+1,j-1)){
		printf("%c",S[i]);
		print(i+1,j-1);
		printf("%c",S[j]);
		return;
	}

	for(int k=i; k<j; k++)
		if(ans == dp(i,k)+dp(k+1,j)){
			print(i,k);
			print(k+1,j);
			return;
		}
}

void readline(char* S) {
  fgets(S, maxn, stdin);
}

int main() {
  int T;

  readline(S);
  sscanf(S, "%d", &T);
  readline(S);

  while(T--) {
    readline(S);
    n = strlen(S) - 1;
    memset(d, -1, sizeof(d));
    print(0, n-1);
    printf("\n");
    if(T) printf("\n");
    readline(S);
  }
  return 0;
}