贪心算法:
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
简单来说就是从一点开始,以每一步最优的方式去寻求最优解,但不保证是全局最优,只保证是每步最优。
例子:
有十一个快件,每个快件有送货的起始时间,要求用最少的车,运送完所有的快件。
快件1:1:00-4:00
快件2:3:00-5:00
快件3:0:00-6:00
快件4:5:00-7:00
快件5:3:00-8:00
快件6:5:00-9:00
快件7:6:00-10:00
快件8:8:00-11:00
快件9:8:00-12:00
快件10:2:00-13:00
快件11:12:00-14:00
实现:
/**
* 派送货件的小车
*
* @author simoniu
*
*/
public class Car {
private ArrayList<Things> thingsList = new ArrayList<Things>();// 车子一天跑的趟数
public ArrayList<Things> getThingsList() {
return thingsList;
}
public void setThingsList(ArrayList<Things> thingsList) {
this.thingsList = thingsList;
}
public Integer addThing(Things thing) // 车子跑一趟, 返回跑了多少趟,包括此趟
{
thingsList.add(thing);
return thingsList.size();
}
}
/**
* 快件类
*
* @author simoniu
*
*/
public class Things {
// 时间设置为24小时制,从0-23
private String name; // 邮件的名字
private Integer startTime; // 一批邮件过来的时间
private Integer endTime; // 结束时间 (endTime - startTime
// 为送完这批快件所需时间,在endTime之前必须送完)
public Things(Integer startTime, Integer endTime, String name) {
this.endTime = endTime;
this.startTime = startTime;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStartTime() {
return startTime;
}
public void setStartTime(Integer startTime) {
this.startTime = startTime;
}
public Integer getEndTime() {
return endTime;
}
public void setEndTime(Integer endTime) {
this.endTime = endTime;
}
}
/**
* 快速排序 平均时间复杂度nlogn,最多n*n
*
* @author simoniu
*
*/
public class Sort {
public static void SortByendTime(ArrayList<Things> thingsSorted,
Integer start, Integer end) {
if (start >= end) // 递归结束的条件
{
return;
}
Things key = thingsSorted.get(start); // 关键数据
Integer i = start; // 最左边的游标
Integer j = end; // 最右边的游标
while (i < j) {
while (j > i
&& thingsSorted.get(j).getEndTime() >= key.getEndTime())// 当后面的值大于key时,不交换,继续向前走
{
j--;
}
if (j > i) {
Things t = thingsSorted.get(i);
thingsSorted.set(i, thingsSorted.get(j));
thingsSorted.set(j, t);
}
while (i < j
&& thingsSorted.get(i).getEndTime() <= key.getEndTime()) // 当前面的值小于等于key时,不交换,继续向后走
{
i++;
}
if (i < j) {
Things t = thingsSorted.get(j);
thingsSorted.set(j, thingsSorted.get(i));
thingsSorted.set(i, t);
}
}
SortByendTime(thingsSorted, start, j - 1); // 对前半部分递归
SortByendTime(thingsSorted, j + 1, end); // 对后半部分递归
}
}
import java.util.ArrayList;
import java.util.Iterator;
public class GreedyTest {
public static ArrayList<Car> cars = new ArrayList<Car>();
public static void main(String[] args) {
ArrayList<Things> thingsList = new ArrayList<Things>(); // 用来装快件的,无序
/****** 输入了11批快件 ****/
Things thing8 = new Things(8, 11, "派件8");
thingsList.add(thing8);
Things thing9 = new Things(8, 12, "派件9");
thingsList.add(thing9);
Things thing10 = new Things(2, 13, "派件10");
thingsList.add(thing10);
Things thing11 = new Things(12, 14, "派件11");
thingsList.add(thing11);
Things thing1 = new Things(1, 4, "派件1");
thingsList.add(thing1);
Things thing2 = new Things(3, 5, "派件2");
thingsList.add(thing2);
Things thing3 = new Things(0, 6, "派件3");
thingsList.add(thing3);
Things thing4 = new Things(5, 7, "派件4");
thingsList.add(thing4);
Things thing5 = new Things(3, 8, "派件5");
thingsList.add(thing5);
Things thing6 = new Things(5, 9, "派件6");
thingsList.add(thing6);
Things thing7 = new Things(6, 10, "派件7");
thingsList.add(thing7);
/*** 给所有派件按结束时间递增排好序 ***/
System.out.print("排序前:");
for (Things t : thingsList) {
System.out.print(t.getName()+":"+t.getStartTime()+"-"+t.getEndTime() + ",");
}
Sort.SortByendTime(thingsList, 0, thingsList.size() - 1); // 排序算法
System.out.print("\n排序后:");
for (Things t : thingsList) {
System.out.print(t.getName()+":"+t.getStartTime()+"-"+t.getEndTime() + ",");
}
GreedySelect(thingsList); // 进行贪心算法
System.out.println("\n最少需要" + cars.size() + "辆车");
int i = 1;
for (Car car : cars) {
System.out.println("第" + i + "辆车装的派件有:");
for (Things t : car.getThingsList()) {
System.out.print(t.getName() + ",");
}
System.out.println("\n");
i++;
}
}
//这个是贪婪算法的核心算法
public static void GreedySelect(ArrayList<Things> thingsList) {
//新建一个小车
Car car = new Car();
//获取该快件的最后时间
Integer middleTime = thingsList.get(0).getEndTime();
car.addThing(thingsList.get(0));
thingsList.remove(0);
cars.add(car);
//循环快件的集合
for (Iterator<Things> t = thingsList.iterator(); t.hasNext();) // 上面注释的for循环和这种迭代方法都行,动态删除容器中的元素
{
Things tt = t.next();
if (middleTime <= tt.getStartTime()) {
middleTime = tt.getEndTime();
car.addThing(tt);
//加到小车后就从几何删除
t.remove();
}
}
//如果快件集合中还有快件,则继续新建小车运快件
if (thingsList.size() != 0) // 递归
{
GreedySelect(thingsList);
}
}
}
转载于:https://blog.51cto.com/wukong0716/1696462