前言
贪心算法,总是做出在当前看来时最好的选择。
活动安排问题
给出多个活动的开始时间和结束时间,每个活动都要占用相同的资源,求最大的活动安排。
解析
给出两个数组:
开始时间s和结束时间 j。并对 j 进行递增排列,这个时候s也是要变化的。其实这里也可以用结构体吧,这样在排列的时候更加友好一点,当然这是数据结构的问题了。然后结束时间最早的就可以当作第一个任务,后面从第二个最早结束时间开始,要是第二个最早结束时间的活动它的开始时间大于等于第一个结束时间,那就加入,否则不加入,一次类推。
模板
template<class type>
void GreedySelector(int n, Type s[], Type f[], bool A[]){
A[1] = true;
int j = 1;
for(int i = 2; i <= n i++){
if(s[i] >= f[j]){
A[i] = true;
j = i;
}
else{
A[i] = false;
}
}
}
结语
贪心策略并不能一定求出问题的最优解,但是对于这种活动安排问题,运用最先结束的贪心办法却可以得到其中的最优解。证明一下?(可以用数学归纳法,但是我没有证明过(捂脸))。
背包问题
我们知道0-1背包问题是给定n种物品和一个背包,物品 i 的重量是wi,价值为vi,背包的容量为 c, 问怎么选择装入背包的物品,是的装入的物品的总价值最大。
而背包问题与0-1背包的区别是物品的重量可以选择,而不是每次选择都要选择全部。
分析
明白了问题之后,我们应该可以很快知道问题应该怎么解,我们可以每次都选择性价比(物品价值 / 重量)最大的。
模板
void Knapsack(int n, float M, float v[], float w[], float x[]){
Sort(n, v, m); //依照性价比进行排列
int i;
for(i = 1; i <= n; i++){
x[i] = 0;
}
float c = M;
for(int i = 1; i <= n; i++){
if(w[i] > c){
break;
}
x[i] = 1;
c -= w[i];
}
if(i <= n){
x[i] = c / w[i];
}
}
总结
0-1背包问题的有效解决方法之一是动态规划,贪心算法并不能有效解决。
多机调度问题
有n个独立作业(1,2,…,n),由m台机器进行加工处理,作业 i 所需时间为 ti,现规定,任何作业可以在任何一台机器上加工处理,且只能在一台机器上一直加工到完成时才能结束。
分析
这是一个NP完全问题(什么时NP完全问题?),在这个问题上,可以采用最长处理时间作业优先的贪心策略。当 n <= m 时,这个最短就是最长时间作业那个了。当n > m时, 首先将 n 个作业依其所需的处理时间从大到小排序,然后依次顺序将作业分配给空闲的处理机。
参考资料
计算机算法设计与分析(第四版)——王晓东