贪心算法及其简单习题

算法不能得到整体最优解,其最终结果却是最优解的很好近似。

1.活动安排问题:

    设有n个活动的集合E={1,2,,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fjsj≥fi时,活动i与活动j相容。

  例:设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下:

i

1

2

3

4

5

6

7

8

9

10

11

S[i]

1

3

0

5

3

5

6

8

8

2

12

f[i]

4

5

6

7

8

9

10

11

12

13

14

 

public class 活动安排问题 {
    public static int greedySelector(int [] s,int [] f,boolean a[])
    {
        int m=s.length;//长度
        a[1]=true;//默认第一个执行
        int count=1;//初始化为1
        int j=1;
        for (int i=2;i<m;i++)
        {
            if (s[i]>=f[j])//下一个事件的开始时间与下一个时间的结束时间作比较
            {//满足的话
                a[i]=true;//标记
                j=i;//重新赋值
                count++;//次数相加
            }
            else
            {
                a[i]=false;//不满足的话
            }
        }
        return count;
    }
    public static void main(String[] args) {
        int s[]={-1,1,3,0,5,3,5,6,8,8,2,12};
        int f[]={-1,4,5,6,7,8,9,10,11,12,13,14};
        boolean a[]=new boolean[s.length];
        System.out.println(greedySelector(s,f,a));
        for(int i=1;i<a.length;i++) {
            if(a[i]) {

                System.out.println(i+"开始"+s[i]+"结束"+f[i]);
            }
        }

    }
}

输出结果:

2.0-1背包问题:

给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

 在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i

 

import java.util.Arrays;

public class 背包问题 {
    public static void main(String[] args) {
        int MAX_WEIGHT=150;//最大重量
        int[] weights = new int[]{35,30,60,50,40,10,25};//重量
        int[] values = new int[]{10,40,30,50,35,40,30};//价值
        GoGreedyPackage(MAX_WEIGHT, weights, values);
    }

    private static void GoGreedyPackage(int max_weight, int[] weights, int[] values) {
        int n=weights.length;
        double [] value=new double[n];//性价比数组
        int [] index=new int[n];//索引数组
        for (int i=0;i<n;i++)
        {
            value[i]=(double)values[i] /weights[i];
            index[i]=i;
        }

        for (int i=0;i<n-1;i++)//冒泡排序处理性价比数组,索引数组
        {
            for (int j=i+1;j<n;j++)
            {
                if (value[i]<value[j])
                {
                    double temp=value[i];
                    value[i]=value[j];
                    value[j]=temp;
                    int t=index[i];
                    index[i]=index[j];
                    index[j]=t;
                }
            }
        }
        索引是保存性价比排序的下标
        System.out.println("性价比排序"+Arrays.toString(value));
        int [] valuelast=new int[n];//性价比排序后的价值排序
        int [] weightlast=new int[n];//性价比排序后重量数组
        for (int i=0;i<n;i++)
        {
            valuelast[i]=values[index[i]];
            weightlast[i]=weights[index[i]];//按最佳性价比重新排序
        }
        System.out.println(Arrays.toString(weightlast));
        //int x[]=new int[n];//是否
        int maxval=0;//总价值
        int max=max_weight;//剩余重量
        for (int i=0;i<n;i++)
        {
            if (weightlast[i]<max)
            {
                //x[i]=1;
                max-=weightlast[i];
                maxval+=valuelast[i];
            }

        }
       // System.out.println(Arrays.toString(x));
        System.out.println(maxval);
        System.out.println(max);
    }
}

结果:

 这里没保存ID不好分辨,自己推一边应该没问题

3.多机调度:

多机调度问题要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。

  这个问题是NP完全问题,到目前为止还没有有效的解法。对于这一类问题,贪心选择策略有时可以设计出较好的近似算法。


import java.util.*;

public class 多机调度 {
    public static class jobNode implements Comparable{//实现了一个比较的接口
        int id;
        int time;
        public jobNode(int id, int time) {//构造方法
            this.id = id;
            this.time = time;
        }
        @Override
        public int compareTo(Object o) {//重写比较函数,时间多的放前面
            int times=((jobNode)o).time;
            if (times<this.time)
            {
                return  -1;//时间少的排前面
            }
            else if (times==this.time)
            {
                return 0;
            }
            else return 1;
        }
    }
    public static class MachineNode implements Comparable//与上面一样
    {
        int id;
        int ava;

        public MachineNode(int id, int ava) {
            this.id = id;
            this.ava = ava;
        }

        @Override
        public int compareTo(Object o) {//工作时间时间少的排前面
            int times=((MachineNode)o).ava;
            if (times<ava)
            {
                return 1;
            }
            else if (times==ava) {
                return 0;
            }
            else
            {
                return -1;
            }
        }
    }
    public static int greed( int [] n,int a) {
        int P = n.length - 1;//记录长度
        int sum = 0;//记录时间
        if (P < a) {//加入任务数量少于机器数量的情况
            for (int i = 0; i < n.length - 1; i++) {
                sum += n[i];
            }
            return sum;
        } else {//任务多于机器数
            List<jobNode> jb = new ArrayList<jobNode>();//造一个jobnode链表保存
            for (int i = 0; i < P; i++) {
                jobNode T = new jobNode(i + 1, n[i + 1]);
                jb.add(T);
            }
            Collections.sort(jb);//调用系统的排序,时间多的放前面

            LinkedList<MachineNode> MN = new LinkedList<>();
            for (int i = 1; i <=a; i++) {
                MachineNode M = new MachineNode(i , 0);
                MN.add(M);
            }
            for (int i = 0; i < P; i++) {
                Collections.sort(MN);//持续按时间排序
                MachineNode mc = MN.peek();//取出机器
                mc.ava += jb.get(i).time;//累计时间
                sum = mc.ava;
            }
            return sum;
        }

    }

    public static void main(String[] args) {
        int[] a={0,2,14,4,16,6,5,3};
        int m=3;
        int sum=greed(a,m);
        System.out.println("时间用了"+sum);
    }
}

结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值