1. 程式人生 > >P3880[JLOI2008]提示問題 洛谷 (C++)(模擬)(字串處理)

P3880[JLOI2008]提示問題 洛谷 (C++)(模擬)(字串處理)

題意很好理解,但這道題實在太考細節了... 隨便亂打的一個測試樣例竟然幫我找到第八組測試樣例過不去的原因??hhhh... 有個小地方忘寫了導致第十組樣例一直WA... 為各位dalao獻上蒟蒻的程式碼,詳情請看註釋。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <cmath>
#include <queue>
#include <cmath>
#include <ctype.h>
#define ll long long

using namespace std ;

string str1 ;   //輸入的原始串
string str2 ;   //根據第1個提示之後的串
string str3 ;   //將第2個提示之後的串複製到str3中
//string str4 ; str4 ? 並沒有 str4,由str3或str2與str1可直接得出最後一個提示的串
int tot_alpha ;     //統計總共的字母數字
bool check = false ;        //檢查第3個提示中是否有可顯示的母音字母
int indexx ;        //找到第2個提示第N個字母的位置

int closest(double a , double b , double c){    //在第二個提示中比較誰更接近,也可如上面幾位dalao的round函式
    if ( fabs(c - a) > fabs(c - b) ){       //比較浮點數絕對值,誰小誰更接近
        return b ;
    }
    return a ;
}

void display_one(){         //提示1,直接處理字串
    str2 = str1 ;
    for ( int i = 0 ; i < str1.size() ; i ++ ){
        if ( isalpha(str2[i]) ){
            str2[i] = '.' ;
            tot_alpha ++ ;
        }
    }
    cout << str2 << endl ;
    return ;
}

void display_two(){         //提示2,由str1和str2組合而成
    double number = tot_alpha / 3.0 ;
    /*天花板ceil(element) 和 地板函式floor(element) (霧
    ceil()向上取整,返回不小於element的最大的整數,
    floor()向下取整,返回不大於element的最小的整數
    */
    int num = closest(ceil(number) , floor(number) , number) ;      //找到離商最接近的自然數N
    int count_ = 0 ;        //記錄到目前出現的字母個數
    for ( int i = 0 ; i < str1.size() ; i ++ ){
        str3[i] = str1[i] ;         //將串複製到str3,便於第三個提示的處理 *ps:之前覺得這個str3會用到,但寫到後面發現沒什麼用...於是一直WA第十組樣例的噩夢開始了...
        /*紀念找到這個BUG的此組胡亂敲打的樣例....
            input:  asd132asd123zxc
            output: ...132...123...
            output: asd132...123...
            output: as.132a..123...    正確輸出->  output: asd132a..123...
          所以有了之後的 “用不著str3” 的瘋狂打臉...
        */
        if ( isalpha(str1[i]) ){        //ctype.h 標頭檔案判斷字元是否是字母函式
            cout << str1[i] ;           //輸出原串str1中的對應字元
            count_ ++ ;                 //若真字母個數+1 
        }else {
            cout << str1[i] ;           //輸出原串str1中的對應字元
        }
        if ( count_ == num ) {      //當字母個數等於N時,記錄下標,並跳出
            indexx = i ;            //記錄第N個字母的位置
            break ;
        }
    }
    for ( int i = indexx + 1 ; i < str1.size() ; i ++ ){        //輸出str2之後的串
        str3[i] = str2[i] ;
        cout << str2[i] ;
    }
    cout << endl ;
    return ;
}

void display_thr(){
    /*str3 = str1 ;   
    此處若加上這語句會出現一個未知的錯誤..
    如果有dalao知道為什麼請告訴我,感激不盡!
    */
    for ( int i = indexx + 1 ; i < str1.size() ; i ++ ){
        /*
        cytpe.h標頭檔案 tolower() 函式將一個字母轉換成小寫字母,與之對應的是 toupper() 
        此處統一轉成小寫字母,便於處理大寫母音字母與小寫母音字母
        */
        if ( tolower(str1[i]) == 'a' || tolower(str1[i]) == 'e' || tolower(str1[i]) == 'i' || tolower(str1[i]) == 'o' || tolower(str1[i]) == 'u' ){
            check = true ;      //說明有可顯示的母音字母
        }
    }
    if ( check ){   //若真,則由原串str1和str3組合生成答案
        for ( int i = 0 ; i < indexx ; i ++ ){      //輸出到第N個字母的位置
            cout << str1[i] ;
        }
        for ( int i = indexx ; i < str1.size() ; i ++ ){    
            /*輸出第N個字母之後的字元,並判斷是否有母音字母,
            若有則輸出str1中的字母,若無則輸出str3中的字元
            */
            if ( tolower(str1[i]) == 'a' || tolower(str1[i]) == 'e' || tolower(str1[i]) == 'i' || tolower(str1[i]) == 'o' || tolower(str1[i]) == 'u' ){
                cout << str1[i] ;
            }else{
                cout << str3[i] ;
            }
        }
    }else{  //若非真,則由原串str1與str2組合生成答案
        double number = tot_alpha / 3.0 * 2.0 ;
        int count_ = 0 ;
        int num = closest(ceil(number) , floor(number) , number) ;
        for ( int i = 0 ; i < str1.size() ; i ++ ){
            if ( count_ < num ){            //顯示前2/3個字母
                if ( isalpha(str1[i]) ){
                    cout << str1[i] ;
                    count_ ++ ;
                }else{
                    cout << str1[i] ;
                }
            }
            else{       //若字母個數等於num則輸出str2之後的串
                cout << str2[i] ;
            }
        }
    }
    return ;
}

int main(){
    getline(cin , str1) ;
    str3 = str1 ;           //若不加上此句在 codeblocks 下會返回非零...如果有dalao知道是什麼原因請告訴我,感激不盡!
    display_one() ;
    display_two() ;
    display_thr() ;
    return 0 ;
}