算法进阶——贪心算法、动态规划算法

贪心算法

贪心算法主要适用于:局部最优策略能导致产生全局最优解。也就是当算法终止的时候,局部最优等于全局最优。它不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。

实现

/**
 * 会议类,需实现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)动态规划在分析子问题的时候,会使用前面子问题的最优结果,并且前面子问题的最后结果不受后面的影响,最后一个子问题即最优解。

发布了117 篇原创文章 · 获赞 17 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/Jack__iT/article/details/100127369