標籤:
借用別人一句話,還以為是個高貴的dp... ...
一打眼一看是波蘭式的題,有點懵還以為要用尾碼運算式或者dp以下什麼什麼的,比賽後半階段才開始仔細研究這題發現貪心就能搞,奈何讀錯題了!!交換的時候可以任意兩個字元交換然而就那麼看成了只能相鄰的數字字元與‘*‘字元交換....../(ㄒoㄒ)/~~...但賽後補題的時候發現細節考慮的不好,還是應該鍛煉下自己的邏輯整理...
怎麼貪咧...
第一步,全數字串即合法,直接輸出0即可;
第二步,數字不夠的話要添。所謂數字夠,即數位個數至少要比星號個數多1,否則可以把缺少的數字(al+1-di)加在最開頭,這樣是最直接理想的。相應的,這也相當於增添操作的次數進行了(al+1-di)次;
第三步,在數字個數與星號個數都合法的條件下,不合法星號的位置要進行交換,交換策略是和該星號後的一個數字交換;這樣的話就能保證每一個星號前是合法的,可能會有人對這一步不太理解:
1 for(int i = 0; i < len; i++)2 {3 if(str[i] == ‘*‘) ta++;4 else td++;5 if(td-ta<1)6 {7 td++; ta--; ans++;8 }9 }
因為所有數字個數與字元個數都已經是合法的了,所以大可以不必考慮交換的具體位置,保證星號前合法的交換總會合法的。
附代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 using namespace std; 7 int main() 8 { 9 int T; cin >> T;10 while(T--)11 {12 string str;13 cin >> str;14 int len = str.length();15 16 int al, di; al = di = 0; //初始串的數字個數與星號個數17 for(int i = 0; i < len; i++) if(str[i] == ‘*‘) al++;18 if(al == 0) {printf("0\n"); continue;}19 di = len-al;20 int need; //是否缺少數字字元21 if(di - al >= 1) need = 0; else need = al+1-di;22 23 int td, ta; td = need; ta = 0;24 int ans = need;25 for(int i = 0; i < len; i++)26 {27 if(str[i] == ‘*‘) ta++;28 else td++;29 if(td-ta<1)30 {31 td++; ta--; ans++;32 }33 }34 cout << ans << endl;35 }36 return 0;37 }View Code
【貪心+一點小思路】Zoj - 3829 Known Notation