2014牡丹江——Known Notation

題目鏈接

  • 題意:
    輸入一個長度不超過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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章