不就是个贪心的算法吗?

贪心算法的步骤

  1. 将优化问题转化成这样一个问题,即先做出选择,在解决剩下的一个子问题
  2. 证明原问题总是有一个最优解是贪心算法选择得到的,从而说明贪心选择的安全
  3. 说明在做出贪心选择中,剩下的子问题具有这样的一个特性:如果将子问题的最优解和我所做的贪心选择联合起来,可以得到一个更加负责的动态规划解

剪绳子

给你一个长度为n的绳子,请把绳子剪成m段(n,m都是整数,且大于1),每段绳子的长度即为k【0】,请问k【0】*k【1】…*k【m】的最大乘积是多少?

思路

如果我们按照以下策略剪绳子,则得到的各段绳子的长度的乘积将最大;当n>5的时候,我们尽可能将绳子剪成长度为3的绳子,当剩下的绳子的长度为4时,把绳子剪成长度为2的绳子

贪心算法的核心是通过局部最优解来得到全局最优解,,对于分割问题来说,要是乘积最大,则贪心算法思想应该尽可能剪为长度为3的绳子

public class 贪心算法之剪绳子 {
    public static void main(String[] args) {
        System.out.println(greedy_cut_rope_1(8));
        System.out.println(greedy_cut_rope(8));
    }
    // 迭代法
    public static int greedy_cut_rope_1(int n)
    {
        if(n<2) {
            return 0;
        }
        if(n==2) {
            return 1;
        }
        if(n==3) {
            return 2;
        }
        //尽可能多地去减长度为3的绳子段
        int timesOf3 = n/3;
        //当绳子最后剩下的长度为4的时候,不能再去剪去长度为3的绳子段
        if(n-timesOf3*3==1) {
            timesOf3-=1;
        }
        int timesOf2 =(n-timesOf3*3)/2;
        return (int) (Math.pow(3,timesOf3)*Math.pow(2,timesOf2));
    }
    // 递归法
    public static int greedy_cut_rope(int n)
    {
        if(n==2) {
            return 2;
        }
        if(n==3) {
            return 3;
        }
        if(n<2) {
            return 1;
        }
        //int timesOf3 = n/3;
        if(n==4) {
            return 4;
        }
        return 3*greedy_cut_rope(n-3);
    }
}

背包问题

给定N个物品和容量为C的背包,物品i的重量为Wi,其价格为Vi,背包问题是如何选择装入背包的物品总价值最大,装入的物品不能重复装入

  • 选择价值最大的物品
  • 选择重量最近的物品
  • 选择单位重量下价值最大的物品

毫无疑问我们应该选择第三种

    public static int knapsackProblem(int[] w, int[] v ,int n, int c){
        //  假设物品已按单位重量降序排列
        double[] x = new double[10];
        int maxValue =0;
        int i;
        for(i=0;w[i]<c;i++)
        {
            //将物品 i 装入背包
            x[i]=1;
            maxValue+=v[i];
            // 背包剩余数量
            c=c-w[i];
        }
        //物品i装入一部分
        x[i]=(double)c/w[i];
        //返回背包获得的价值
        maxValue+=x[i]*v[i];
        return maxValue;
    }

活动选择

有一个需要是使某一资源的n个活动组成的集合S={a1,a2,a3…,an},该资源一次只能被一个活动资源占用,每个活动ai有一个开始时间Si和一个结束时间Fi,且0<=Si<=Fi<unlimited,一旦选择,活动ai就占据半开时间区间[Si,Fi),如果区间[Si,Fi)与 [Sj,Fj)互不重叠,称活动ai与aj是兼容的。活动选择问题就是要选择出一个由互相兼容的问题组成的最大集合。

image

对于任意一个非空子问题,设am是Sij中具有最早结束时间的活动
fm=min{fk:ak ∈ Sij}

  • 活动am在Sij的最大兼容活动子集中被使用
  • 子问题Sim为空,所以选择am使子问题SMij为唯一可能非空的子问题

解决子问题时,选择am是一个可被合法调度,具有最早结束时间内的活动,从直觉上来看,这种活动的选择方法是一种的贪婪的技术,他会给后面的待调度任务流下尽可能多的机会,也就是说,此处的贪心选择使得剩下的未调度的时间最大化

public static void greedy_activity_selector(int[] s,int[] f,boolean[] b)
{
    int n = s.length-1;
    b[1]=true;
    int j=1;
    for(int i =2;i<=n;i++)
    {
        if(s[i]>f[j])
        {
            b[i]=true;
            j=i;
        }else
            b[i]=false;
    }
    for(int i=1;i<b.length;i++)
        System.out.println(b[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值