《趣学算法》的java实践(1)贪心算法

最优装载问题

问题描述

海盗船载重量为c,每件古董载重量为 w i w_i wi,海盗要怎样才能把尽可能多的宝物装上船?

Java实现

import java.util.Arrays;
import java.util.Scanner;

public class BestLoadingProblem {
   

    public static void main(String[] args) {
   
        double[] w;
        double c;
        int n;
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入载重量c及古董个数n:");
        c = scanner.nextDouble();
        n = scanner.nextInt();
        w = new double[n];
        System.out.print("请输入每个古董的质量,用空格分开:");
        for (int i = 0; i < n; i++) {
   
            w[i] = scanner.nextDouble();
        }
        Arrays.sort(w);
        double tmp = 0.0;
        int ans = 0;
        for (int i = 0; i < n; i++) {
   
            tmp += w[i];
            if (tmp <= c) {
   
                ans++;
            } else {
   
                break;
            }
        }
        System.out.println("能装载的古董最大数量为Ans="+ans);
    }
}

注:Java中数组的排序可以通过调用Arrays类的sort函数来执行。

背包问题

问题描述

假设山洞中有n种宝物,每种宝物有一定重量w和响应的价值v,宝物可以分割。毛驴的运载能力为m,怎样才能使毛驴运走的宝物价值更大?

Java实现

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class KnapsackProblem {
   
    static class Treasure {
   
        public Treasure(double w, double v) {
   
            this.w = w;
            this.v = v;
            this.p = v / w;
        }

        double w;
        double v;
        double p;
    }

    public static void main(String[] args) {
   
        int n;
        double m;
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入宝物数量n及毛驴载重量m:");
        n = scanner.nextInt();
        m = scanner.nextDouble();
        Treasure[] treasures = new Treasure[n];
        System.out.print("请输入每个宝物的重量和价值,用空格分开:");
        for (int i = 0; i < n; i++) {
   
            treasures[i] = new Treasure(scanner.nextDouble(), scanner.nextDouble());
        }
        Arrays.sort(treasures, new Comparator<Treasure>() {
   
            @Override
            public int compare(Treasure o1, Treasure o2) {
   
                double difference = o2.p - o1.p;
                if (difference > 0.001) {
      
                    return 1;
                } else if (difference < -0.001) {
   
                    return -1;
                } else {
   
                    return 0;
                }
            }
        });
        double sum = 0.0;
        for (int i = 0; i < n; i++) {
   
            Treasure treasure = treasures[i];
            if (m > treasure.w) {
   
                m -= treasure.w;
                sum += treasure.v;
            } else {
   
                sum += m * treasure.p;
                break;
            }
        }
        System.out.println("能装载的宝物的最大价值Maximum value=" + sum);
    }
}

注:

  1. 为了更简单便捷地定义宝物的数据结构,这里使用了静态内部类的语法,静态内部类和外部类相对独立,不用实例化外部类即可使用。LinkedList的源码中就是用静态内部类Node来储存链表中的每个节点。
  2. 自定义对象数组无法直接调用Arrays类的sort函数进行排序,常见的解决方法是让自定义对象实现Comparable接口或者调用需要传入一个Comparator对象作为参数的sort函数,这里选用的是后者。
  3. Comparator是泛型接口,里面的compare函数实现了对泛型对象的比较。compare函数返回整数,正数、0、负数分别代表前一个参数的对象大于、等于、小于后一个参数的对象。因为sort函数是升序排序,所以要调换比较的顺序。
  4. 因为浮点数的精度问题,这里选择了一种常见的利用差值的比较办法,差值的绝对值在指定范围内则可以近似认为两个浮点数相等。
  5. 为了简化代码,在给sort函数传入Comparator对象时使用了匿名类的语法。匿名类实现了一种不需要提供任何的类名直接实例化内部类的语法。

会议安排问题

问题描述

有n个会议,每个会议都有开始时间和结束时间,如何安排会议才能尽可能在有限的时间内召开更多的会议?

Java实现

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class MeetingArrangementProblem {
   

    static class Meet {
   
        int begin;
        int end;
        int num;

        public Meet(int begin, int end, int num) {
   
            this.begin = begin;
            this.end = end;
            this.num = num;
        }
    }

    private int n, ans;
    private Meet[] meets;

    public void init() {
   
        int s, e;
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入会议总数n:");
        this.n = scanner.nextInt();
        this.meets = new Meet[n];
        System.out.println("请输入每个会议的开始时间和结束时间,用空格分开:");
        for (</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八云黧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值