贪婪算法是解决最优化问题的一种基本方法。它采用逐步构造最优解的思想,在问题求解的每一个阶段,都作出一个在一定标准下看上去最优的决策;决策一旦作出,就不可再更改。制定决策的依据称为贪婪准则。贪婪算法需要考虑以下步骤:
1 、明确问题的求解目标。
2 、分析问题所包含的约束条件。
3 、建立优化函数。优化函数通常可以通过综合分析问题的求解目标及约束条件归纳出来。
4 、制定贪婪准则。清楚问题的求解目标、所包含的约束条件及优化函数之后,就可以着手制定一个可行的贪婪准则。贪婪准则的制定是用贪婪算法解决最优化问题的关键,它关系到问题能否得到成功解决及解决质量的高低。
接下来列举一些具体的例子: 例 1 : 计算发放工资时所需的最少人民币张数。输入数据为职工的工资数。要求统计并输出应发给该职工面值 100 元、 50 元、 20 元、 10 元、 5 元、 2 元、 1 元的人民币各多少张,使总张数最少。
分析:为了使总张数最少,那么最大面额的数量就会尽量的多。
例 2 : 旅行家的预算( 1999 年全国青少年信息学(计算机)奥林匹克分区联赛高中组复赛试题第三题)
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离 d1 、汽车油箱的容量 c (以升为单位),每升汽油能行驶的距离 d2 、出发点每升汽油的价格 p 和沿途油站数 n ( n 可以为零),油站 i 离出发点的距离 di 、每升汽油的价格 pi ( i=1,2, ……n )。
计算结果四舍五入至小数点后两位。
如果无法到达目的地,则输出 “No solution” 。
输入描述
输入数据可能有多行:
第1行:
D1:两个城市之间的距离;C:汽车油箱的容量;D2:每升汽油能行驶的距离;P:出发点每升汽油价格;N:沿途油站数
第2到n+1行,共n行,依次表示各个加油站信息,每行有两个数据:第i+1行表示第i个油站,离出发点的距离Di;每升汽油价格Pi
输出描述
输出共一行:表示最小费用,四舍五入至小数点后两位。
如果无法到达目的地,则输出“No solution”。
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
输出样例
26.95
程序代码:写程序的时候本来考虑用当前最小的油价到尽可能远的距离,不一定到某一个站点,可以在站点和站点之间,然后再取第二大的油价判断可以到哪里,这个需要牵扯到邮箱容量什么的。比较复杂。后来发觉只能用下面的简单一点的贪婪法计算了。
package com.fnk.acm;
import java.text.DecimalFormat;
import java.util.ArrayList;
public class GreedyMinCost {
private double cityDistance = 275.6; // 两座城市之间的距离
private double capacity = 11.9; // 汽车油箱的容量
private double disCanMoveEveryUnit = 27.4; // 每升汽油能行驶的距离
private double priceInStartCity = 2.8;// 出发点每升汽油价格
//private int NumOfOieStation = 2;// 沿途油站数
private ArrayList<OilStation> osArray = new ArrayList<OilStation>();
public GreedyMinCost() {
osArray.add(new OilStation(102.0, 2.9));
osArray.add(new OilStation(220.0, 2.2));
//将终点加到next location列表里面
osArray.add(new OilStation(cityDistance, -1));
}
class OilStation {
private double distance;// 离出发点的距离
private double price;// 每升汽油价格
public OilStation(double distance, double price) {
this.distance = distance;
this.price = price;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
public double getMinCost(){
double bestPrice = priceInStartCity;
double currentPostion = 0;
double cost = 0;
for(int j = 0 ; j < osArray.size();j ++ ){
for(int i = j; i <osArray.size(); i ++){
//根据贪婪算法判断当前的油价可以到的最远的距离。如果距离方面不超出,尽可能用油价低的油到尽可能远的加油站
if(bestPrice > osArray.get(i).price || disCanMoveEveryUnit * capacity + currentPostion < osArray.get(i).getDistance()){
if(i == j)
return -1;
cost += bestPrice * (osArray.get(i).getDistance() - currentPostion) / disCanMoveEveryUnit;
bestPrice =osArray.get(i).price;
j=i -1;
currentPostion = osArray.get(i).getDistance();
break;
}
}
}
return cost;
}
public static void main(String[] args){
GreedyMinCost gmc = new GreedyMinCost();
//用于四舍五入
DecimalFormat df = new DecimalFormat("#.00");
double minCost = gmc.getMinCost();
if(minCost <0 )
{
System.out.println("No Solution!");
}
else{
System.out.println(df.format(minCost));
}
}
}