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;
}

 

posted @ 2018-12-02 22:10  KirinSB  阅读(179)  评论(0编辑  收藏  举报