贪心算法
贪心算法主要适用于:局部最优策略能导致产生全局最优解。也就是当算法终止的时候,局部最优等于全局最优。它不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。
实现
/**
* 会议类,需实现Comparable接口
*/
public class Meeting implements Comparable<Meeting>{
//定义会议属性
private int number;
private int starTime;
private int endTime;
//get set方法
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getStarTime() {
return starTime;
}
public void setStarTime(int starTime) {
this.starTime = starTime;
}
public int getEndTime() {
return endTime;
}
public void setEndTime(int endTime) {
this.endTime = endTime;
}
//构造方法
public Meeting(int number, int starTime, int endTime) {
this.number = number;
this.starTime = starTime;
this.endTime = endTime;
}
@Override
public String toString() {
return "Meeting{" +
"number=" + number +
", starTime=" + starTime +
", endTime=" + endTime +
'}';
}
//需要重写接口的方法
@Override
public int compareTo(Meeting o) {
//按照会议结束时间升序排列
if(this.endTime>o.endTime){
return 1;
}
if(this.endTime<o.endTime){
return -1;
}
return 0;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/**
* 贪心算法,用来解决会议安排问题
*/
public class Greedy {
public static void main(String[] args) {
//得到会议信息
Scanner scan=new Scanner(System.in);
System.out.println("请输入会议数量");
int count=scan.nextInt();
List<Meeting> list=new ArrayList<Meeting>();
for (int i = 0; i < count; i++) {
int starTime=scan.nextInt();
int endTime=scan.nextInt();
Meeting m=new Meeting(i,starTime,endTime);
list.add(m);
}
System.out.println("会议信息");
for (Meeting meeting : list) {
System.out.println(meeting);
}
//贪心策略:按照会议结束时间排序,优先安排最先结束的
//然后接下来从后面的会议里,寻找会议开始时间在当前会议结束时间之后的
Collections.sort(list);
int currentMeetingEndTime=0;
System.out.println("贪心算法后会议安排");
for (int i = 0; i <count; i++) {
//判断会议结束时间
Meeting m=list.get(i);
if(m.getStarTime()>=currentMeetingEndTime){
System.out.println(m);
//更新当前会议结束时间
currentMeetingEndTime=m.getEndTime();
}
}
}
}
动态规划算法
实现
/**
* 背包问题,使用动态规划,即分解子问题,通过局部最大值,逐渐得到全局最大值
*/
public class DP {
public static void main(String[] args) {
//物品重量和价值,一一对应
int[] weight=new int[]{10,20,40};
int[] value=new int[]{60,100,120};
//背包容量50kg
int capacity=50;
//物品个数 3个
int count=3;
//根据表格分析,创建二维数组
int[][] packageValue=new int[count+1][capacity+1];
//动态规划分析,判断每个格子的最大值
for (int i = 1; i <=count; i++) {//外层循环代表放第几个物品
for (int j = 1; j <= capacity; j++) {//内层循环代表背包重量逐渐增加
//根据上述表格的分析,得到如下逻辑
if(weight[i-1]<=j){
//比较没放这个物品时,上一轮的这个背包重量下最大价值,和放上这个物品时的最大价值
//放上这个物品后,还要考虑剩余背包是否能容纳物品
packageValue[i][j]=Math.max(packageValue[i-1][j],value[i-1]+packageValue[i-1][j-weight[i-1]]);
}else{
//背包没达到能容纳的重量,就还是按照上一轮最大价值
packageValue[i][j]=packageValue[i-1][j];
}
}
}
//打印结果
System.out.println("动态规划后最大的价值是:"+packageValue[count][capacity]);
}
}
总结
(1)贪心解决不了就用动态规划,一般贪心算法的时间复杂度为O(nlgn),动态规划为O(n^2),能用贪心解决就不用动态规划。
(2)贪心得到的结果不一定是最优解。
(3)动态规划在分析子问题的时候,会使用前面子问题的最优结果,并且前面子问题的最后结果不受后面的影响,最后一个子问题即最优解。