貪心算法
貪心算法主要適用於:局部最優策略能導致產生全局最優解。也就是當算法終止的時候,局部最優等於全局最優。它不是對所有問題都能得到整體最優解,選擇的貪心策略必須具備無後效性,即某個狀態以後的過程不會影響以前的狀態,只與當前狀態有關。所以對所採用的貪心策略一定要仔細分析其是否滿足無後效性。
實現
/**
* 會議類,需實現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)動態規劃在分析子問題的時候,會使用前面子問題的最優結果,並且前面子問題的最後結果不受後面的影響,最後一個子問題即最優解。