贪心算法的实际应用

来源:互联网 发布:腾讯 大数据 排行 编辑:程序博客网 时间:2024/04/30 10:30
   这次得发点干货了^_^

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

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;    }}
0 0
原创粉丝点击