贪心算法的实际应用

   这次得发点干货了^_^

贪心算法的实际应用解决:背包问题、线段覆盖问题

1.背包问题:
有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
物品 A B C D E F G
重量 35 30 60 50 40 10 25
价值 10 40 30 50 35 40 30

实现代码( Java ):

package com.kiddingboy_wjj.home;

import java.util.Scanner;
/** * 背包问题 * @author kiddingboy_wjj * */
public class Bage {

    private static float[] V;

    public static void main(String args[]) {
        int wu_num = 0;
        float bg_content = 0;
        float now_content = 0;
        System.out.println("请输入背包容量:");

        bg_content = Integer.parseInt(new Scanner(System.in).next());
        System.out.println("请输入物品个数:");
        wu_num = Integer.parseInt(new Scanner(System.in).next());
        int[] W = new int[wu_num];
        V = new float[wu_num];
        for (int i = 0; i < wu_num; i++) {
            System.out.println("请输入第个物品的重量/价值:" + (i + 1));

            W[i] = Integer.parseInt(new Scanner(System.in).next());
            V[i] = Integer.parseInt(new Scanner(System.in).next());
        }

        float[] Q = new float[wu_num];
        for (int i = 0; i < wu_num; i++) {
            Q[i] = V[i] / W[i];
        }
        // 排序
        Q = sort(Q);
        int k = 0;
        for (k = 0; k < wu_num; k++) {
            if (now_content > bg_content)
                break;
            now_content += V[k];
        }
        // now_content -= V[k - 1];
        System.out.println("当前最大利益是:" + now_content);

    }

    /** * 执行排序的功能 * * @param Q1 * @return */
    private static float[] sort(float[] Q1) {
        float temp, temp2;
        float[] Q = Q1;
        for (int i = 0; i < Q.length - 1; i++)
            for (int j = 0; j < Q.length - 1 - i; j++) {
                if (Q[j] < Q[j + 1]) {
                    temp = Q[j];
                    Q[j] = Q[j + 1];
                    Q[j + 1] = temp;

                    temp2 = V[j];
                    V[j] = V[j + 1];
                    V[j + 1] = temp2;
                }
            }
        return Q;
    }
}

2、线段覆盖问题
1.线段覆盖(lines cover)
题目大意:
在一维空间中告诉你N条线段的起始坐标与终止坐标,要求求出这些线段一共覆盖了多大的长度。

解题思路:
将线段按其坐标进行排序(排序的具体方法:按起始坐标排,起始坐标相同的按终止坐标排,都是小在前大在后),使之依次递增,并按顺序分别编号为X(i),X(i).a代表其起始坐标,X(i).b代表其终止坐标。
然后按排好的顺序依次处理:定义一个变量last记录考虑到当前线段之时被线段覆盖的最大的坐标值,再定义一个变量length记录当前线段覆盖的长度。对于后面的线段,我们把它看成由两个部分组成,即把它分成last之前的线段和last之后的线段。(如果线段全部处在last之后,其last之前的部分不存在。)由于我们排过序,我们可以肯定当前考虑的线段X(i)其处在last之前的部分不会对length造成影响(因为X(i-1).b=last,X(i).a>=X(i-1).a,即X(i)在last之前的部分所处位置肯定被线段X(i-1)覆盖过),所以会对length产生影响的即是X(i)处在last之后的部分。
所以我们可以依次对每条线段做如下处理:(初始化length为零,last为负无穷)
length+=X(i).b-last (X(i).a<=last 且 X(i).b>=last)
length+=X(i).b-X(i).a (X(i).a>last)
last=X(i).b;
最后length就为我们所需要的答案。
实现代码( Java ):

package com.kiddingboy_wjj.home;

import java.util.Scanner;
/** * 线段覆盖问题 * @author kiddingboy_wjj * */
public class Line {

    public static void main(String[] args) {
        int n, length = 0, last;// length是当前总长度,last是当前总长度的末尾坐标
        // Demo *d = new Demo;
        System.out.println("输入线段数:");
        n = Integer.parseInt(new Scanner(System.in).next());
        float[] s_x = new float[n];// 线段起点坐标
        float[] e_x = new float[n];// 线段终点坐标
        for (int i = 0; i < n; i++) {
            System.out.println("请输入第" + (i + 1) + "条线段的起点及终点:");
            s_x[i] = Integer.parseInt(new Scanner(System.in).next());
            e_x[i] = Integer.parseInt(new Scanner(System.in).next());
        }
        sort(s_x, e_x, n);// 按递增排序
        length = (int) getLength(s_x, e_x, n);
        System.out.println("一共覆盖的长度为:" + length);

    }

    /** * 排序 * * @param s_x * @param e_x * @param n */
    static void sort(float s_x[], float e_x[], int n) {
        float temp;
        // float temp_s[] = new float[n];
        // float temp_e[] = new float[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (s_x[i] > s_x[j]) {// 起点大于后者则直接对换
                    temp = s_x[i];
                    s_x[i] = s_x[j];
                    s_x[j] = temp;

                    temp = e_x[i];
                    e_x[i] = e_x[j];
                    e_x[j] = temp;
                }
                if (s_x[i] == s_x[j]) {// 起点相同,判断终点
                    if (e_x[i] > e_x[j]) {
                        temp = s_x[i];
                        s_x[i] = s_x[j];
                        s_x[j] = temp;

                        temp = e_x[i];
                        e_x[i] = e_x[j];
                        e_x[j] = temp;
                    }

                }
            }
        }

    }

    static float getLength(float s_x[], float e_x[], int n) {
        float length = 0, last = e_x[0];
        length = e_x[0] - s_x[0];
        for (int i = 0; i < n; i++) {
            if (s_x[i] >= last) {// 起点大于last则直接加上线段长
                length += (e_x[i] - s_x[i]);
            } else if (e_x[i] > last) {// 起点小于last,终点大于last,加上多出部分
                length += (e_x[i] - last);
            }

        }
        return length;
    }
}
    原文作者:贪心算法
    原文地址: https://blog.csdn.net/kiddingboy_wjj/article/details/46630065
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞