算法面试题 -- 迷离傍地走

来源:互联网 发布:sql server数据库大小 编辑:程序博客网 时间:2024/04/27 16:27

      • 题目
      • 问题
      • 算法分析
      • Code

题目

为庆祝强汉文武盛世暨废除和亲七百周年,武后决定拜孙武和王翳对春夏秋冬四官:细君、昭君、探春、文成四人座军事训练。
孙武和王翳分别负责四官的站军姿踢正步科目;根据军训要求,只有在学会站军姿之后才能进行踢正步训练,但由于四官天资差别,学习时间如下表:
时间表

问题

问:应该如何安排四官的学习时间,才能够使得所有人都学会上述两项技能的时间最短?

算法分析

首先我们来看,如果按原始的顺序,即春夏秋冬四个人的顺序,就是什么安排也不做,最终会耗时多久:
最坏的情况
可以看到,如果什么计划和安排也不做,所有人都学会这两项技能就会消耗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;
8 1
原创粉丝点击