(原創(chuàng)PAT乙級1085 PAT單位排行)

題目

1085 PAT單位排行 (25 分)
每次 PAT 考試結束后抠艾,考試中心都會發(fā)布一個考生單位排行榜。本題就請你實現這個功能。
輸入格式:
輸入第一行給出一個正整數 N(≤10的5次方)缰泡,即考生人數。隨后 N 行代嗤,每行按下列格式給出一個考生的信息:
準考證號 得分 學校
其中準考證號是由 6 個字符組成的字符串棘钞,其首字母表示考試的級別:B代表乙級,A代表甲級干毅,T代表頂級宜猜;得分是 [0, 100] 區(qū)間內的整數;學校是由不超過 6 個英文字母組成的單位碼(大小寫無關)硝逢。注意:題目保證每個考生的準考證號是不同的姨拥。
輸出格式:
首先在一行中輸出單位個數绅喉。隨后按以下格式非降序輸出單位的排行榜:
排名 學校 加權總分 考生人數
其中排名是該單位的排名(從 1 開始);學校是全部按小寫字母輸出的單位碼叫乌;加權總分定義為乙級總分/1.5 + 甲級總分 + 頂級總分*1.5的整數部分柴罐;考生人數是該屬于單位的考生的總人數。
學校首先按加權總分排行憨奸。如有并列革屠,則應對應相同的排名,并按考生人數升序輸出排宰。如果仍然并列似芝,則按單位碼的字典序輸出。

思考過程

做題過程中板甘,咋看上去邏輯很簡單党瓮,做起來卻在某個點里想了好久,代碼也隨之更換了幾次版本盐类,這個點就是map的思想寞奸,一開始有考慮map,但是不想這么快就用傲醉,想想用以往的知識是否可以代替這個功能蝇闭。

先說說我的解題邏輯:

根據題目要求,建立學校結構體硬毕,包含著學校名字呻引,各考試類型分數,還有總分和該校的考試人數吐咳,并建立該結構體數組逻悠。
1.每錄入一個學生的考試類型,成績和學校名字韭脊,然后根據其考試類型童谒,計入該學生所屬學校的總分。
2.上面錄完全部學生信息沪羔,這時學校的總分和考試人數信息也搞完了饥伊,接著就是排序,按照題目的要求來排序蔫饰,這里我試過了兩種排序琅豆,一個stl的sort,另一種是自己寫的堆排序篓吁,結果是前者略快一點茫因,唉
3.輸出

這里唯一令我嘗試了多種方法的是怎么讓錄入已經重復學校的信息能盡快找出來對應的,其實就是map功能杖剪。
主要分成三次嘗試

第一次嘗試冻押,計算學校名字字符串的hash值驰贷,自定義的,二十六進制洛巢,6位括袒,理論上程序是走得通,或者小量數據也可稿茉,但是乘法原理就是加法箱熬,十萬個數據,數組空間達到了3E以上狈邑,每算一個學生的學校名字時候一直用乘法計算它的hash值,在最后測試點內存超限了蚤认,果然不行米苹。
第二次嘗試,我嘗試再第一次的基礎上改進砰琢,減少乘法蘸嘶,并且減少空間,采用之前學過的鏈地址法+3位二十六進制+對比后三位字符串陪汽,每發(fā)現新的就重新開辟一個训唱,理論上程序也是走得通,或者小量數據也可挚冤,但是測試點就是這么神奇况增,你開辟空間太多次了,倒數第二個測試點就運行超時训挡,估計這個測試點澳骤,讓我的hash重復率高導致開辟次數達到上萬次,這的確耗時澜薄,比較傷心为肮,當然你可以把全空間預先全部覆蓋好,弄成二維數組肤京,第一維的維數會高達上萬颊艳,空間浪費太大,加上鏈地址法上查找也會按照O(n)時間復雜度查找忘分,已經達不到map的功能棋枕。然后我又想嘗試投石問路,把二十六進制推進到4位又或者3位26進制+后三位的ASCII值饭庞,但覺得此時在此題浪費時間過多了戒悠,不想繼續(xù)了,日后再想想舟山。
第三次嘗試绸狐,基于這個查找的特點卤恳,我只需要查重而已,直接啟用C++的unordered_map寒矿,來代替自定義計算hash值突琳,其余邏輯沒變,通過...

unordered_map內部實現了一個哈希表(也叫散列表符相,通過把關鍵碼值映射到Hash表中一個位置來訪問記錄拆融,查找的時間復雜度可達到O(1),其在海量數據處理中有著廣泛應用)
優(yōu)點: 因為內部實現了哈希表啊终,因此其查找速度非常的快
缺點: 哈希表的建立比較耗費時間

一刷代碼

image.png
#include <stdio.h>
#include <string.h> 
#include <algorithm>
#include <stdlib.h>
#define MAX_LENGTH 26 * 26 * 26 * 26 * 26 * 26 + 6 

/*
1085 PAT單位排行 (25 分)

*/
using namespace std;
typedef struct School
{
    int id; //學校字符串的hash值 
    char name[7];
    int cScore;//乙級 
    int bScore;//甲級 
    int aScore;//頂級 
    int scores;
    int personCount;
}School;


typedef struct HashMap
{
    unsigned int hashTableKey, hashTableValue;
}HashMap;


int GetIntputToInt();
void GetInputToChar(char ch[]);
bool cmp(School a, School b);
int hashFunc(char S[]);
//void HeapSort(School target[],int n);
//void Sift(School target[],int low,int high);
//void SwapSchool(School target[],int a,int b);

//HashMap map[MAX_LENGTH];

int main()
{
    HashMap *map = (HashMap*)malloc(sizeof(HashMap)*MAX_LENGTH);
    int N = GetIntputToInt();//考生總數 
    School *school = (School*)malloc(sizeof(School)*N);//考慮最壞情況镜豹,每個學生就代表一個不同的學校 

    //1.輸入每個學生的情況 
    char stuNoTemp[7], nameTemp[7];
    int tempScore, schoolNum = 0;
    char c;
    for (int i = 0; i<N; i++)
    {//i負責遍歷學生,j負責學校個數 
        //1.獲取編號
        GetInputToChar(stuNoTemp);
        c = stuNoTemp[0];//取出其考試類型 
        //2.獲取成績
        tempScore = GetIntputToInt();
        //3.獲取學校名字
        GetInputToChar(nameTemp);
        int id = hashFunc(nameTemp);
        int tempSchoolPos = schoolNum;
        if (map[id].hashTableKey)
        {//id存在的話蓝牲,要向前找 
            //          while (school[--tempSchoolPos].id != id&&tempSchoolPos >= 0)//超時原因 
            //              ;
            tempSchoolPos = map[id].hashTableValue;
        }
        else
        {//不存在的話
            map[id].hashTableKey = 1;
            map[id].hashTableValue = tempSchoolPos;
            school[tempSchoolPos].id = id;
            strcpy(school[tempSchoolPos].name, nameTemp);
            schoolNum++;//學校數量增1 
        }

        //根據考試類型增加其對應考試類型的總分 
        switch (c)
        {
        case 'a':school[tempSchoolPos].bScore += tempScore;//a是advanced趟脂,對應bscore 
            break;
        case 'b':school[tempSchoolPos].cScore += tempScore;//b是basic,對應cscore 
            break;
        case 't':school[tempSchoolPos].aScore += tempScore;
            break;
        default:break;
        }
        //更新該學校參與考試的人數
        school[tempSchoolPos].personCount++;
    }

    //2.統(tǒng)計學校的總分
    for (int i = 0; i<schoolNum; i++)
        school[i].scores = school[i].cScore / 1.5 + school[i].bScore + school[i].aScore*1.5;

    //3.排序
    sort(school, school + schoolNum, cmp);

    //4.輸出
    printf("%d\n", schoolNum);
    for (int i = 0, j = 1; i<schoolNum; i++)
    {
        if (i>0 && school[i].scores != school[i - 1].scores)
            j = i + 1;
        printf("%d %s %d %d\n", j, school[i].name, school[i].scores, school[i].personCount);
    }
    //5.釋放
    //free(hashTableKey);
    //free(hashTableValue);
    //hashTableKey = NULL;
    //hashTableValue = NULL;

    return 0;
}

bool cmp(School a, School b)
{
    if (a.scores != b.scores) return a.scores>b.scores;
    else if (a.personCount != b.personCount) return a.personCount<b.personCount;
    else return strcmp(a.name, b.name)<0;
}

void GetInputToChar(char ch[])
{
    int i = 0;
    char c;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
    {
        if (c >= 'A'&&c <= 'Z')
            c = c + 32;
        ch[i++] = c;
    }
    ch[i] = '\0';
}

int GetIntputToInt()
{
    char c;
    int sum = 0;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
        sum = sum * 10 + c - '0';
    return sum;
}

int hashFunc(char S[])
{
    int id = 0, i = 0;
    while (S[i] != '\0')
    {
        id = id * 26 + S[i++] - 'a';
    }
    return id + i;//若然是aaa,a這兩個值是相同的例衍,所以把長度也加上昔期。 
}

二刷代碼

image.png
#include <stdio.h>
#include <string.h> 
#include <algorithm>
#include <stdlib.h>

/*
1085 PAT單位排行 (25 分)

*/
using namespace std;
typedef struct School
{
    //int id; //學校字符串的hash值 
    char name[7];
    int scores, ascore, bscore, tscore;
    int personCount;
}School;


typedef struct LinkHashNode
{
    int SchoolPos;
    char str[4];
    int viceHash;
    //char str[7];
    struct LinkHashNode *next;
}LinkHashNode;


int GetIntputToInt();//1.輸入轉成int 
int GetInputToChar(char ch[]);//2.輸入轉成字符串 
bool cmp(School a, School b);//3.STL中的sort用到的cmp方法 


int GetHashFunc(char S[], int *viceHash);//4.計算字符串中的哈希值
//int GetVicHashFunc(char S[]); 
void InsertStrHash(char S[], int id, int NewSchoolPos, int SViceHash);
int IsSchoolPosExists(char S[], int id, int SViceHash);
//unsigned int hashFunc(char S[],int length);
//void HeapSort(School target[],int n);
//void Sift(School target[],int low,int high);
//void SwapSchool(School target[],int a,int b);

const int MAX_LENGTH = 26 * 26 * 26 + 6 + 26 * 3;//26*26*26*26*26*26+6;//(26+26)*26*26*26*26+6;//
LinkHashNode map[MAX_LENGTH];//={{-1."",NULL}};
int main()
{
    int N = GetIntputToInt();//考生總數 
    School *school = (School*)malloc(sizeof(School)*(N));//考慮最壞情況,每個學生就代表一個不同的學校 

    //初始化 
    for (int i = 0; i<N; i++)
        school[i].personCount = school[i].scores = 0;//school[i].aScore = school[i].bScore = school[i].cScore = 
    for (int i = 0; i<MAX_LENGTH; i++)
        map[i].SchoolPos = -1;

    //1.輸入每個學生的情況 
    char stuNoTemp[7], nameTemp[7];
    int tempScore, schoolNum = 0;
    char c;
    for (int i = 0; i<N; i++)
    {//i負責遍歷學生個數佛玄,schoolNum負責學校個數 
        //1.獲取編號
        GetInputToChar(stuNoTemp);
        c = stuNoTemp[0];//取出其考試類型 
        //2.獲取成績
        int tempScore = GetIntputToInt();
        //3.獲取學校名字
        GetInputToChar(nameTemp);
        //int id =  hashFunc(nameTemp,nameLength);//超時原因硼一,乘法太多,加法原理
        int viceHash = 0;
        //viceHash=0;
        int id = GetHashFunc(nameTemp, &viceHash);//主部哈希對比 

        int tmpSchoolPos = IsSchoolPosExists(nameTemp, id, viceHash);

        if (tmpSchoolPos<0) //若然找不到School數組位置 
        {
            tmpSchoolPos = schoolNum++;
            InsertStrHash(nameTemp, id, tmpSchoolPos, viceHash);//這個注釋了就
            strcpy(school[tmpSchoolPos].name, nameTemp);
            //schoolNum++;//學校數量增1
        }

        //根據考試類型增加其對應考試類型的總分 
        switch (c)
        {
        case 'a':school[tmpSchoolPos].ascore += tempScore;//a是advanced梦抢,對應bscore 
            break;
        case 'b':school[tmpSchoolPos].bscore += tempScore;//b是basic般贼,對應cscore 
            break;
        case 't':school[tmpSchoolPos].tscore += tempScore;
            break;
        default:break;
        }
        //更新該學校參與考試的人數
        school[tmpSchoolPos].personCount++;
    }

    //2.統(tǒng)計學校的總分
    for (int i = 0; i<schoolNum; i++)
        school[i].scores = school[i].bscore / 1.5 + school[i].ascore + school[i].tscore*1.5;

    //3.排序
    sort(school, school + schoolNum, cmp);

    //4.輸出
    printf("%d\n", schoolNum);
    for (int i = 0, j = 1; i<schoolNum; i++)
    {
        if (i>0 && school[i].scores != school[i - 1].scores)
            j = i + 1;
        printf("%d %s %d %d\n", j, school[i].name, school[i].scores, school[i].personCount);
    }


    //5.釋放 
    //  free(map);
    //  free(school);
    //  map = NULL;
    //  school = NULL;

    return 0;
}

bool cmp(School a, School b)
{
    if (a.scores != b.scores) return a.scores>b.scores;
    else if (a.personCount != b.personCount) return a.personCount<b.personCount;
    else return strcmp(a.name, b.name)<0;
}

int GetInputToChar(char ch[])
{
    int i = 0;
    char c;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
    {
        if (c >= 'A'&&c <= 'Z')
            c = c + 32;
        ch[i++] = c;
    }
    ch[i] = '\0';
    return i;
}

int GetIntputToInt()
{
    char c;
    int sum = 0;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
        sum = sum * 10 + c - '0';
    return sum;
}


int GetVicHashFunc(char S[])
{
    int id = 0, i = 3;
    while (S[i] != '\0')
        //id = id * 26+ S[i++] - 'a';//26 
        id += S[i++] - 'a';
    return id + i - 3;//a,aaa也返回0,i-3是其長度避免返回同樣的值 
}

int GetHashFunc(char S[], int *vicHash)
{
    int id = 0, i = 0;
    while (S[i] != '\0'&&i<3)
        id = id * 26 + S[i++] - 'a';//26 

    while (S[i] != '\0'&&i >= 3)//字符長度超出3惑申,就另外計算后面的哈希值
        *vicHash = *vicHash + S[i++] - 'a' + 1;//26 

    return id + i;//若然是aaa,a這兩個值是相同的具伍,所以把長度也加上。 
}

int IsSchoolPosExists(char S[], int id, int SViceHash)
{
    LinkHashNode *tmpNode = &map[id];
    if (tmpNode->SchoolPos >= 0)
    {
        if (SViceHash>0)
        {
            do
            {
                //if(strcmp(S,tmpNode->str)==0)
                if (tmpNode->viceHash == SViceHash)
                {
                    int i = 3, j = 0;
                    //strcmp(S+3,tmpNode->str)==0
                    while (S[i] != '\0')
                    {
                        if (S[i] != tmpNode->str[j])
                            break;
                        i++; j++;
                    }

                    if (S[i] == '\0'&&tmpNode->str[j] == '\0')
                        return tmpNode->SchoolPos;
                }

                tmpNode = tmpNode->next;
            } while (tmpNode);
        }
        else if (SViceHash == 0)
            return tmpNode->SchoolPos;
    }
    return -1;
}

void InsertStrHash(char S[], int id, int NewSchoolPos, int SViceHash)
{
    LinkHashNode *tmpNode = &map[id];
    int i = 0, j = 0;//i控制S圈驼,j控制tmpNode->str 
    if (tmpNode->SchoolPos >= 0)//若然第一個不是空的人芽,向下查空的為止 
    {
        while (tmpNode->next != NULL)
            tmpNode = tmpNode->next;
        LinkHashNode *newNode = (LinkHashNode *)malloc(sizeof(LinkHashNode));
        tmpNode->next = newNode;
        tmpNode = tmpNode->next;
    }

    if (SViceHash>0)
        strcpy(tmpNode->str, S + 3);
    tmpNode->viceHash = SViceHash;//GetHashFunc(S,4);
    tmpNode->SchoolPos = NewSchoolPos;

    tmpNode->next = NULL;
}

三刷代碼

image.png
#include <stdio.h>
#include <string.h> 
#include <algorithm>
#include <stdlib.h>
#include <unordered_map>

/*
1085 PAT單位排行 (25 分)

*/
using namespace std;
typedef struct School
{
    //int id; //學校字符串的hash值 
    //string name;
    char name[7];
    int ascore, bscore, tscore;
    int scores;
    int personCount;
}School;

int GetIntputToInt();//1.輸入轉成int 
int GetInputToChar(char ch[]);//2.輸入轉成字符串 
bool cmp(School a, School b);//3.STL中的sort用到的cmp方法 
int main()
{
    int N = GetIntputToInt();//考生總數 
    School *school = (School*)malloc(sizeof(School)*(N + 1));//考慮最壞情況,每個學生就代表一個不同的學校 
    //  
    //1.輸入每個學生的情況
    unordered_map<string, int> schoolHash;
    char stuNoTemp[7], nameTemp[7];
    int schoolNum = 0;
    char c;
    for (int i = 0; i<N; i++)
    {//i負責遍歷學生個數绩脆,schoolNum負責學校個數 

        //1.獲取編號
        GetInputToChar(stuNoTemp);
        c = stuNoTemp[0];//取出其考試類型 
        //2.獲取成績
        int tempScore = GetIntputToInt();
        //3.獲取學校名字
        GetInputToChar(nameTemp);
        string strSchoolName = nameTemp;//這里strSchoolName只用來unordered_map的比較尋找


        int tmpSchoolPos;
        if (schoolHash.find(strSchoolName) == schoolHash.end())
        {
            schoolHash[strSchoolName] = tmpSchoolPos = schoolNum++;
            strcpy(school[tmpSchoolPos].name, nameTemp);
        }
        else
            tmpSchoolPos = schoolHash[strSchoolName];

        //根據考試類型增加其對應考試類型的總分 
        switch (c)
        {
        case 'a':school[tmpSchoolPos].ascore += tempScore;//a是advanced萤厅,對應bscore 
            break;
        case 'b':school[tmpSchoolPos].bscore += tempScore;// / 1.5;//b是basic,對應cscore 
            break;
        case 't':school[tmpSchoolPos].tscore += tempScore;//*1.5;
            break;
        default:break;
        }
        //更新該學校參與考試的人數
        school[tmpSchoolPos].personCount++;
    }

    //2.統(tǒng)計學校的總分
    for (int i = 0; i<schoolNum; i++)
        school[i].scores = school[i].bscore / 1.5 + school[i].ascore + school[i].tscore*1.5;

    //3.排序
    sort(school, school + schoolNum, cmp);

    //4.輸出
    printf("%d\n", schoolNum);
    for (int i = 0, j = 1; i <schoolNum; i++)
    {
        if (i>0 && school[i].scores != school[i - 1].scores)
            j = i + 1;
        printf("%d %s %d %d\n", j, school[i].name, school[i].scores, school[i].personCount);
    }


    //5.釋放 
    //  free(map);
    //  free(school);
    //  map = NULL;
    //  school = NULL;

    return 0;
}

bool cmp(School a, School b)
{
    if (a.scores != b.scores) return a.scores>b.scores;
    else if (a.personCount != b.personCount) return a.personCount<b.personCount;
    else return strcmp(a.name, b.name)<0;
}

int GetInputToChar(char ch[])
{
    int i = 0;
    char c;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
    {
        if (c >= 'A'&&c <= 'Z')
            c = c + 32;
        ch[i++] = c;
    }
    ch[i] = '\0';
    return i;
}

int GetIntputToInt()
{
    char c;
    int sum = 0;
    while ((c = getchar()) != EOF&&c != ' '&&c != '\n')
        sum = sum * 10 + c - '0';
    return sum;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末靴迫,一起剝皮案震驚了整個濱河市惕味,隨后出現的幾起案子,更是在濱河造成了極大的恐慌玉锌,老刑警劉巖名挥,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異主守,居然都是意外死亡禀倔,警方通過查閱死者的電腦和手機榄融,發(fā)現死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來救湖,“玉大人愧杯,你說我怎么就攤上這事⌒龋” “怎么了力九?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邑闺。 經常有香客問我跌前,道長,這世上最難降的妖魔是什么陡舅? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任舒萎,我火速辦了婚禮,結果婚禮上蹭沛,老公的妹妹穿的比我還像新娘。我一直安慰自己章鲤,他們只是感情好摊灭,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著败徊,像睡著了一般帚呼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上皱蹦,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天煤杀,我揣著相機與錄音,去河邊找鬼沪哺。 笑死沈自,一個胖子當著我的面吹牛,可吹牛的內容都是我干的辜妓。 我是一名探鬼主播枯途,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼籍滴!你這毒婦竟也來了酪夷?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤孽惰,失蹤者是張志新(化名)和其女友劉穎晚岭,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體勋功,經...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡坦报,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年库说,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燎竖。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡璃弄,死狀恐怖,靈堂內的尸體忽然破棺而出构回,到底是詐尸還是另有隱情夏块,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布纤掸,位于F島的核電站脐供,受9級特大地震影響,放射性物質發(fā)生泄漏借跪。R本人自食惡果不足惜政己,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掏愁。 院中可真熱鬧歇由,春花似錦、人聲如沸果港。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辛掠。三九已至谢谦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萝衩,已是汗流浹背回挽。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猩谊,地道東北人千劈。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像牌捷,于是被迫代替她去往敵國和親队塘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內容