算法面試題 -- 迷離傍地走

題目

爲慶祝強漢文武盛世暨廢除和親七百週年,武后決定拜孫武和王翳對春夏秋冬四官:細君、昭君、探春、文成四人座軍事訓練。
孫武和王翳分別負責四官的站軍姿踢正步科目;根據軍訓要求,只有在學會站軍姿之後才能進行踢正步訓練,但由於四官天資差別,學習時間如下表:
時間表

問題

問:應該如何安排四官的學習時間,才能夠使得所有人都學會上述兩項技能的時間最短?

算法分析

首先我們來看,如果按原始的順序,即春夏秋冬四個人的順序,就是什麼安排也不做,最終會耗時多久:
最壞的情況
可以看到,如果什麼計劃和安排也不做,所有人都學會這兩項技能就會消耗32個小時,但是能不能做到更少呢?很明顯,先前我們是按照春夏秋冬四個人的原始順序來安排的,如何我們把四官的訓練順序做一下合理的調整呢?這樣會不會降低時間成本呢,好,我們接着往下分析。
上表中可以看到,四官在兩項技能上的最短時間是昭君踢正步,爲1小時,這個時間在所有踢正步的四個人裏是最短的,但是踢正步是必須要在站軍姿學會後才能學習的,所以我們把這一事件放在最後執行;再來看,其中的次短時間是探春的站軍姿,爲2小時,這個時間很明顯也是四個人中(站軍姿)最短的,因爲站軍姿就是位於踢正步之前,所以把這個時間放在第一位執行;然後再看,再次短時間是探春的踢正步,爲3小時,所以把它放在倒數第二位執行,這樣依次下去,學習安排表就顯而易見了。
最好的情況

思路總結:因爲只有兩種學科(站軍姿和踢正步),並且站軍姿在踢正步之前,所以將所有站軍姿的按照時間由少到多正排序,而將踢正步的按照時間由少到多逆排序。

Code

void AllAlgorithms::getShortestTime(const int *a, const int *b, int *c, int size){
    int size2 = size * 2;
    //整理數據
    HLItem *item = new HLItem[size2];
    for (int i = 0; i < size2; i ++) {
        item[i].t = a[i];
        item[i].idx = i;
        item[i].first = true;
        item[i + size].t = b[i];
        item[size + i].idx = i;
        item[size + i].first = false;
    }

    sort(item, item + size2);

    bool *bArrage = new bool[size];//第i號已經安排
    for (int i = 0; i < size; i ++) {
        bArrage[i] = false;
    }

    int from = 0;
    int to = size - 1;
    for (int i = 0; i < size2; i ++) {
        if(bArrage[item[i].idx])//item[i].idx已經確定
            continue;
        bArrage[item[i].idx] = true;
        if (item[i].first) {
            c[from] = item[i].idx;
            from ++;
        }
        else{
            c[to] = item[i].idx;
            to --;

        }
        if(to - from < 0)//提前退出
            break;
    }
    delete [] item;
    delete [] bArrage;
}


typedef struct tagItem{
    int t;
    int idx;
    bool first;
    bool operator < (struct tagItem& item) const{
        return t < item.t;
    }

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