算法進階——貪心算法、動態規劃算法

貪心算法

貪心算法主要適用於:局部最優策略能導致產生全局最優解。也就是當算法終止的時候,局部最優等於全局最優。它不是對所有問題都能得到整體最優解,選擇的貪心策略必須具備無後效性,即某個狀態以後的過程不會影響以前的狀態,只與當前狀態有關。所以對所採用的貪心策略一定要仔細分析其是否滿足無後效性。

實現

/**
 * 會議類,需實現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)動態規劃在分析子問題的時候,會使用前面子問題的最優結果,並且前面子問題的最後結果不受後面的影響,最後一個子問題即最優解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章