版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/eternity1118_。 https://blog.csdn.net/eternity1118_/article/details/52636957
题目
为庆祝强汉文武盛世暨废除和亲七百周年,武后决定拜孙武和王翳对春夏秋冬四官:细君、昭君、探春、文成四人座军事训练。
孙武和王翳分别负责四官的站军姿和踢正步科目;根据军训要求,只有在学会站军姿之后才能进行踢正步训练,但由于四官天资差别,学习时间如下表:
问题
问:应该如何安排四官的学习时间,才能够使得所有人都学会上述两项技能的时间最短?
算法分析
首先我们来看,如果按原始的顺序,即春夏秋冬四个人的顺序,就是什么安排也不做,最终会耗时多久:
可以看到,如果什么计划和安排也不做,所有人都学会这两项技能就会消耗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;