题解:SP5449 ANARC09A - Seinfeld
可以用动态规划解决。
动态规划思想:
设 \(dp_{i,j}\) 表示处理到字符串的第 \(i\) 个字符,并且未配对的 { 数量为 \(j\) 时,所需的最小操作次数。
状态转移:
-
初始化:
- \(dp_{0,0} = 0\):表示空字符串且没有未配对的
{,显然不需要任何操作。 - 其他所有 \(dp_{0,j}\) 初始化为 INF,表示不可能的状态。
- \(dp_{0,0} = 0\):表示空字符串且没有未配对的
-
状态转移方程:
- 如果当前字符是
{:- 可以选择将它保留为
{,那么我们增加一个未配对的{,即 \(dp_{i,j}=1+dp_{i-1,j-1}\)。 - 如果有未配对的
{,我们也可以选择将这个{改为},这样可以减少一个未配对的{,即 \(dp_{i,j}=\min(dp_{i,j},dp_{i-1,j-1})\)。
- 可以选择将它保留为
- 如果当前字符是
}:- 可以选择将它保留为
},此时如果之前有未配对的{,可以减少一个未配对的{,即 \(dp_{i,j} = dp_{i-1,j-1}\)。 - 也可以选择将这个
}改为{,从而增加一个未配对的{,即 \(dp_{i,j}=\min(dp_{i,j},dp_{i-1,j-1})\)。
- 可以选择将它保留为
- 如果当前字符是
最终结果:
在处理完所有字符后,\(dp_{n,0}\) 就是最终需要的最小操作次数。
代码:
using namespace std;
char str[2001];
int main(){
for(int cs=1;;cs++){
scanf("%s",str);
if(str[0]=='-')return 0;
int N=strlen(str);
vector<vector<int>>dp(N+1,vector<int>(N+1,1e6));
dp[0][0]=0;
for(int i=1;i<=N;i++){
for(int j=0;j<=N;j++){
if(str[i-1]=='{'){
dp[i][j]=1+dp[i-1][j+1];
if(j>0)dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
}else{
dp[i][j]=dp[i-1][j+1];
if(j>0) dp[i][j]=min(dp[i][j],1+dp[i-1][j-1]);
}
}
}
printf("%d. %d\n",cs,dp[N][0]);
}
}

浙公网安备 33010602011771号