poj 1141 动态规划
题意: 黑书P113 括号配对
1 空序列是规则序列
2 如果S是规则序列,则(S)或[S]是规则序列
3 如果A和B是规则序列,则AB是规则序列
给定序列,要求尽可能少的添加括号使其成为规则序列,输出规则序列。
分析:设dp[i][j]为S[i~j]最少需要增加的括号数,
dp[i, j] = ( dp[i+1, j-1], dp[i, k] + dp[k+1, j] ) (i<=k<j)
int dp[105][105],Div[105][105]; string str; void init(){ string temp=""; //去除空格 int len=str.size(); for(int i=0;i<len;i++) if(str[i]!=' ') temp+=str[i]; str=temp; for(int i=0;i<104;i++)//初始化 for(int j=i;j<105;j++){ dp[i][j]=999999; Div[i][j]=0; } for(int i=0;i<104;i++){ dp[i][i]=1;//本身需要一个配对 dp[i+1][i]=0;//空串需要0个 } } int solve(int i,int j){ if(dp[i][j]<999999)return dp[i][j];//记忆化搜索 for(int k=i;k<j;k++){ int t1=solve(i,k),t2=solve(k+1,j);//从k,k+1处分开 if(t1+t2<dp[i][j]){ dp[i][j]=t1+t2; Div[i][j]=k; } } if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']')//不分开,首尾配对 if(dp[i][j]>dp[i+1][j-1]){ dp[i][j]=dp[i+1][j-1]; Div[i][j]=j; } return dp[i][j]; } string add(int i,int j){ if(i>j)return "";//i和i+1配对的情况 if(i==j)//进行配对{ if(str[i]=='('||str[i]==')')return "()"; else if(str[i]=='['||str[i]==']')return "[]"; } int t=Div[i][j]; if(t==j) return str[i]+add(i+1,j-1)+str[j];//首尾配对,对中间部分添补 return add(i,t)+add(t+1,j);//从t处分成两部分,分别添补 } int main(){ getline(cin,str); init(); solve(0,str.size()-1); cout<<add(0,str.size()-1)<<endl; return 0; }