ACM-ICPC Live Archive 2451 Brackets Sequence
动态规划
poj 1141 ural 1183 zoj 1463 都是相同的题目,黑书DP的例题
输入比较恶心,有空串。递推的时间是1s多,记忆化的时间是4.3s勉强过,原理不说了百度各种有
/* 1.dp[i][j]=dp[i+1][j-1] , p[i][j]=-1 , --->p[i+1][j-1] 2.dp[i][j]=dp[i+1][j]+1 , p[i][j]=-2 , --->p[i+1][j] 3.dp[i][j]=dp[i][j-1]+1 , p[i][j]=-3 , --->p[i][j-1] 4.dp[i][j]=dp[i][k]+dp[k+1][j] , p[i][j]=k , --->p[i][k],p[k][j] 5.p[i][j]初始化为0 */ #include <cstdio> #include <cstring> #define MAX 110 #define INF 0x3f3f3f3f char s[MAX]; int dp[MAX][MAX],p[MAX][MAX],n; int min(int a , int b , int *c) { if(a>b) {(*c)=1; return b;} else {(*c)=0; return a;} //c是用于标记有没有更新最小值 } void print(int i ,int j) { if(i>j) return ; if(p[i][j]==-1) { printf("%c",s[i]); print(i+1,j-1); printf("%c",s[j]); return ; } if(p[i][j]==-2) { printf("%c",s[i]); print(i+1,j); if(s[i]=='(') printf(")"); else if(s[i]=='[') printf("]"); return ; } if(p[i][j]==-3) { if(s[j]==')') printf("("); else if(s[j]==']') printf("["); print(i,j-1); printf("%c",s[j]); return ; } int k=p[i][j]; print(i,k); print(k+1,j); return ; } int dfs(int i ,int j) { if(i>j) { return dp[i][j]=0; } //错位 if(dp[i][j]!=-1) return dp[i][j]; int c; dp[i][j]=INF; if( (s[i]=='(' && s[j]==')') || (s[i]=='[' && s[j]==']') ) { dp[i+1][j-1]=dfs(i+1,j-1); dp[i][j]=min(dp[i][j] , dp[i+1][j-1] , &c); if(c) p[i][j]=-1; } if(s[i]=='(' || s[i]=='[') { dp[i+1][j]=dfs(i+1,j); dp[i][j]=min(dp[i][j] , dp[i+1][j]+1 , &c); if(c) p[i][j]=-2; } if(s[j]==')' || s[j]==']') { dp[i][j-1]=dfs(i,j-1); dp[i][j]=min(dp[i][j] , dp[i][j-1]+1 , &c); if(c) p[i][j]=-3; } for(int k=i; k<j; k++) //分块 { dp[i][k]=dfs(i,k); dp[k+1][j]=dfs(k+1,j); dp[i][j]=min(dp[i][j] , dp[i][k]+dp[k+1][j] , &c); if(c) p[i][j]=k; } return dp[i][j]; } int main() { int Case; scanf("%d",&Case); getchar(); while(Case--) { getchar(); gets(s+1); if(s[1]=='\0') { printf("\n"); if(Case) printf("\n"); continue; } n=strlen(s+1); memset(dp,-1,sizeof(dp)); memset(p,0,sizeof(p)); for(int i=1; i<=n; i++) { dp[i][i]=1; if(s[i]=='(' || s[i]=='[') p[i][i]=-2; else p[i][i]=-3; } dfs(1,n); //printf("%d\n",dp[1][n]); print(1,n); printf("\n"); if(Case) printf("\n"); } return 0; }