贪心法
将问题的求解过程看作是一系列选择,每次选择一个输入,每次选择都是当前状态下的最好选择(局部最优解).每作一次选择后,所求问题会简化为一个规模更小的子问题. 从而通过每一步的最优解逐步达到整体的最优解。
[适用问题] 具备贪心选择(整体的最优解可通过一系列局部最优解达到.每次的选择可以依赖以前作出的选择,但不能依赖于后
面的选择)和最优子结构性质(问题的整体最优解中包含着它的子问题的最优解)的最优化问题
可以依赖前面 不管后面
给的是个例 要从整体出发
[适用问题] 具备贪心选择(整体的最优解可通过一系列局部最优解达到.每次的选择可以依赖以前作出的选择,但不能依赖于后
面的选择)和最优子结构性质(问题的整体最优解中包含着它的子问题的最优解)的最优化问题
可以依赖前面 不管后面
给的是个例 要从整体出发
1、活动安排问题
设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
解法:每次总是选择具有最早完成时间的相容活动加入集和中
活动安排问题贪心算法
template<class Type>
void GreedySelector(int n, Type s[], Type f[], bool A[])//各活动的起始时间和结束时间存储于数组s和f中且按结束时间的非减序排列
{
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;
}
}//未排序时:T(n)=O(nlogn),排序时为n
2、最优装载
有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为Wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。
解法:最优装载问题可用贪心算法求解。采用重量最轻者先装的贪心选择策略,可产生最优装载问题的最优解。
最优装载的贪心算法
template<class Type>
void Loading(int x[], Type w[], Type c, int n)
{
int *t = new int [n+1]; //按货箱重量排序/
Sort(w, t, n);
for (int i = 1; i <= n; i++) x[i] = 0;
for (int i = 1; i <= n && w[t[i]] <= c; i++) {x[t[i]] = 1; c -= w[t[i]];} //调整剩余空间/
}
算法分析: 排序为主要算法时间,所以T(n)=O(nlogn)
3、背包问题
给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。
[算法思路]
1).将各物体按单位价值由高到低排序. 2).取价值最高者放入背包.3).计算背包剩余空间.4).在剩余物体中取价值最高者放入背包.若背包剩余容量=0或物体全部装入背包为止
背包问题的贪心算法
void Knapsack(int n,float M,float v[],float w[],float x[])
{
Sort(n,v,w); //按单位价值排序/
int i;
for (i=1;i<=n;i++) x[i]=0;
float c=M; //c为背包剩余空间/
for (i=1;i<=n;i++) {
if (w[i]>c) break;
x[i]=1;
c-=w[i];
}
if (i<=n) x[i]=c/w[i];
}//T(n)=O(nlogn)
多机调度问
题要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业.
按此策略,当 n<=m时,只要将机器i的[0, ti]时间区间分配给作业i即可,算法只需要O(1)时间。当 n>m 时,首先将n个作业依其所需的处理时间从大到小排序。然后依此顺序将作业分配给空闲的处理机。算法所需的计算时间为O(nlogn)