ZOJ 3829 Known Notation(贪心)题解
题意:给一串字符,问你最少几步能变成后缀表达式。后缀表达式定义为,1 * 1 = 1 1 *,题目所给出的字串不带空格。你可以进行两种操作:加数字,交换任意两个字符。
思路:(不)显然,最终结果数字比*号至少多1,如果缺了数字就直接放到字符串最前面(这样肯定能和后面的*运算),加步数。然后遍历,遇到*号如果当前数字够就直接运算,不够那么就把*和最后面的数字交换。讲一下为什么要可以,因为我们要保证末尾不是数字,如果末尾数字数字显然不是后缀表达式,其次我们交换之后当前的运算就没了,那么就过了,然后后面那个我们换过去的*自有最前面的我们加的数字去运算。
代码:
#include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 1e3 + 10; const int seed = 131; const ll MOD = 109; const int INF = 0x3f3f3f3f; char s[maxn]; int main(){ int t, num = 0, star = 0; scanf("%d", &t); while(t--){ scanf("%s", s); int len = 0; num = star = 0; while(s[len] != '\0'){ if(s[len] == '*') star++; else num++; len++; } int save = 0, ans = 0; if(num < star + 1){ save = star + 1 - num; ans += save; } int p = 0, from = len - 1; while(p < len){ if(s[p] != '*'){ save++; p++; } else{ if(save >= 2){ save--; p++; } else{ for(int i = from; i > p; i--){ if(s[i] != '*'){ swap(s[i], s[p]); ans++; save++; break; } } p++; } } } printf("%d\n", ans); } return 0; }