题目链接
- 题意:
输入一个长度不超过1000的字符串,包括数字(1-9)和星号(*)。字符串中的空格已经丢失,所以连起来的数字串可以看成许多分开的数,也可以看成连续的数,即可以随意添加空格。现在有两种操作:1)在任意位置添加任意类型的字符(数字或者星号) 2)交换字符串中的任意两个字符
求:最少操作多少次,使得得到的串是一个合法的逆波兰式 - 分析:
对于n个星号,n+1个数字的字符串,如果将星号都移动到串的末尾,那么一定是合法的
对于操作1,如果需要插入数字,那么插入到字符串的最前边是最优的
对于操作2,只可能将星号和数字交换,并且将星号移到了字符串的后边
那么,先对串进行操作1,使得数字个数不小于星号的个数加一;然后从左到右扫描字符串,如果当前星号前边的数字和星号不满足对应关系(同上),需要将当前星号与最后一个数字交换;最后,如果字符串最后不是星号,答案加一 - 注意:
如果最后得到的串最后不是星号,那么必然答案加一
如果输入没有星号,那么答案是0
const int maxn = 1100;
char s[maxn];
int n;
vector<int> v;
int main()
{
int T;
RI(T);
while (T--)
{
v.clear();
RS(s);
n = strlen(s);
int num = 0, sig = 0;
REP(i, n)
{
if (s[i] == '*') sig++;
else
{
v.push_back(i);
num++;
}
}
int ans = 0;
int preadd = 0;
if (!sig)
{
ans = 0;
}
else
{
if (num < sig + 1)
{
preadd = sig + 1 - num;
ans += preadd;
}
int sig_num = 0;
for (int i = 0; i < n; i++)
{
if (s[i] == '*')
{
sig_num++;
if (preadd < sig_num + 1)
{
int sz = v.size();
int id = v[sz - 1];
v.pop_back();
swap(s[i], s[id]);
sig_num--;
preadd++;
ans++;
}
}
else preadd++;
}
if (s[n - 1] != '*')
ans++;
}
printf("%d\n", ans);
}
return 0;
}