Source: 2014 ACM-ICPC Asia Regional Dhaka
Problem:
给你一个只有
′a′
和
′+′
的逆波兰表示法的串,即一个后缀表达式。
有三种操作:
1.添加一个
′a′
2.添加一个
′+′
3.交换两个相邻的字符
问最少的操作使得这个表达式合法。
Idea:
对于一个合法的表达式,令前缀中
a
的数量为
令最小的
num1−num2
为
d
注意到对于
"+aa"
这种情况只需要两次交换,因为他的交换对后面的前缀值不会有影响,对其特判即可。
Code:
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define CLR(A, X) memset(A, X, sizeof(A))
#define bitcount(X) __builtin_popcountll(X)
typedef long long LL;
typedef pair<int, int> PII;
const double eps = 1e-10;
const int MOD = 255;
const int INF = 0x3f3f3f3f;
int dcmp(double x) { if(fabs(x) < eps) return 0; return x<0?-1:1; }
const int MAXN = 1e5+5;
char s[MAXN];
int len;
int solve(char *s) {
int k = 0, mink = MAXN, d, ans;
for(int i = 0; i < len; i++) {
if(s[i] == 'a') k++;
else k--;
if(k < mink) mink = k, d = 1;
else if(k == mink) d = 0;
}
if(mink > 0) ans = k-1;
else if(k == mink) ans = 1-k;
else ans = 1-mink+(1-mink+k-1)-d;
return ans;
}
int main() {
int X;
scanf("%d", &X);
for(int cas = 1; cas <= X; cas++) {
scanf("%s", s);
len = strlen(s);
int ans = solve(s);
if(len>=3 && s[0]=='+' && s[1]=='a' && s[2]=='a') {
swap(s[0], s[2]);
ans = min(ans, solve(s)+2);
}
printf("Case %d: %d\n", cas, ans);
}
return 0;
}