贪心算法的基础是贪心选择性质和最优子结构性质。这是能否使用贪心算法的本质。下面介绍几种用贪心算法为基础解决的几个基本问题:
1.0-1背包问题:
给n种物品,第i个物品质量为wi,价格为vi,容量为c,应如何选择物品,使得背包装的物品价值最大,在这个背包问题中,每个物品两种选择,装入或不装入,而且装入不可以只装部分,既不可拆分。
2. 活动(理发,接水等)安排问题;
假设共有n个节目,而需要同一个舞台,每个节目有着不同的使用时间,或者是有一个要求的起始时间或结束时间,前者的话一般要求是使所有人等待时间最少来完成表演,后者一般是在所有时间段中选择最多的节目。
前者更好解决,只需要排序以运算规则相加即可,而后者是以结束时间排序,以结束时间早的,并把时间不冲突加上,就可以得到我们想要的结果。
3. 最优装载问题:
有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为Wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。
与上题0-1,以及2问题中前者相似,将集装箱以质量排序,将质量轻的放上轮船即可。
4. Dijkstra算法:
说到贪心算法,那就不得不提提我前面写过的dij算法了,给定带权的有向图,每条边的权是非负实数,给一个起点,找到从起点到各点的最短距离。附一段dij算法实现代码:
int i,j,k,min,tmp;
void dij(int start,int dist【】,flag【】) //dist【i】意是点start到点i的距离,flag【i】=0意思是点start到i的距离最小值未得到,=1意思是已经得到最短距离。我们确立flag的目的是防止重复与过多的循环。
{
for(i=1;i<=n;++i) //详细的没有指出,n是指全部的点
{flag[i]=0;
dist[i]=long[1][i] //long表示1-i之间的距离 }
flag【start】=1; //出发点与出发点的最短距离,默认为已知
dist【start】=0; //出发点与出发点的距离0;
//这之后就是在从start1步到达end和n-1步到达end的最短距离的比较选择,也是dij中的核心
for(i=1;i<n;++i){
min=inf; //inf是一个极大值,表示无穷大的数。
for(j=1;j<=n;++j) if(flag[j]==0&&dist[j]<min) {min=dist[j]; k=j;}
flag[k]=1; //因为一步里面到达的它是距离最少的,所以start到k点距离最小。
//下面的循环就是求第二步到第n-1步最小值的。不太好掌握
for(j=1;j<=n;++j){ tmp= long[k][j]==INF ? INF : (min + mMatrix[k][j])); if(flag[j]==0&&dist[j]>temp) dist【j】=tmp;}//不仅如此,在这一步中我们得到了每一个分两步到达各点的距离的最小值,然后返回上一个循环找到两步到达的最小值的点,然后再进行这一个循环得到分三步到达的点的距离的最小值,以此类推。
然后我们想要到哪个点,直接用dist【i】就是最小距离点了。