ZOJ 3829 贪心

ZOJ 3829
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3829
题意:
给一个字符串,字符串中只包含数字和运算符’*’。
现在问字符串是不是一个合法的逆波兰式。已知逆波兰式的空格消除,也就是说11可以看成11也可以看成1和1.
如果不是,问至少进行几个交换或者插入操作能使它成为一个合法的逆波兰式。
思路:
贪心。
试过分类讨论,然后发现讨论不清楚。
实际上,对于一个总个数上数字个数比*的个数多至少一个、也就是不需要插入只交换就能形成合法的逆波兰式的字符串,可以证明此时交换比插入更高效。
又发现*总是放在后面好,数字总是放在前面好。
所以就产生了一种贪心的算法。
先补齐缺的数字(大于等于的个数+1),然后遍历字符串。发现一处,前面的个数>=数字个数+1时,此*与最后面的数字进行交换。然后统计答案即可。
源码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 1000 + 5;
char str[MAXN];
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%s", str);
        int mark1, mark2;
        mark1 = mark2 = 0;
        int len = strlen(str);
        for(int i = 0 ; i < len ; i++){
            if(str[i] == '*')   mark2++;
            else    mark1++;
        }
        int ans = max(mark2 - mark1 + 1, 0);
// printf("original answer = %d\n", ans);
        int flag = mark2;
        mark1 = mark2 = 0;
        mark1 = ans;
        int rear = len - 1;
        for(int i = 0 ; i < len ; i++){
            if(str[i] == '*'){
                if(mark1 > 1)
                    mark1--;
                else{
                    mark1++;
                    ans++;
                    while(str[rear] == '*' && rear > i)
                        rear--;
                    swap(str[i], str[rear]);
                }
            }
            else
                mark1++;
        }
        printf("%d\n", ans);
    }
    return 0;
}

/* 123456 132*123 1***13 **1 111*** */

你可能感兴趣的:(ZOJ 3829 贪心)