1. 程式人生 > >ZOJ 3829 Known Notation(貪心)題解

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