算法分析习题集 Java版

目录

4.n元素幂集

5.插入排序

6.俄式乘法

7.AVL树

8.数学三角形

9.最长上升子序

10.投资分配

11.活动安排——贪心算法

12.一般背包问题——贪心算法

 

4.n元素幂集

Java代码:

思路:减一法 ——>利用递推式:p(n) = p(n-1) + IPN (IPN为前项和后项的一种关系)

import java.util.ArrayList;

public class PowerSet {
    public static void main(String[] args) {
        String[] a = { "1", "2","3", "4" };
        ArrayList<String> pn = getSet(a); //
        System.out.println("Set size is = " + pn.size());
        for (int i = 0; i < a.length; i++) {
            String string = a[i];
        }
        System.out.println(pn.toString());
    }

    public static ArrayList<String> getSet(String[] a) {
        ArrayList<String> pn = new ArrayList<String>(); // creat a list to save set
        pn.add("");
        for (int i = 0; i < a.length; i++) {
            pn.addAll(IPN(pn, a[i])); // 递推式:p(n) = p(n-1) + IPN p(0) = {"","1"}; p(1) = p{"","1","2","1,2"}...
            // System.out.println("pn.addAll = " + pn.toString());
            // System.out.println("--------------------");
        }
        return pn;
    }

    public static ArrayList<String> IPN(ArrayList<String> pn, String i) {
        ArrayList<String> tmp = new ArrayList<String>();
        for (int k = 0; k < pn.size(); k++) {
            // System.out.println("pn.get[k] = " + pn.get(k));
            tmp.add(pn.get(k) + i); // 临时list存储元素
            // System.out.printf("tmp.get(%d) = %s\n", k, tmp.get(k));
        }
        return tmp;
    }
}

运行结果:

Set size is = 16
[, 1, 2, 12, 3, 13, 23, 123, 4, 14, 24, 124, 34, 134, 234, 1234]

 

C代码

思路:递归法——>树的先序遍历

//递归树的叶子节点
int P(char *str, int n,int index){
    static char tmp[10];
    int case1 = 0, case2 = 0;
    
    if(n==-1){
        //递归结束条件,输出叶子节点
        tmp[index] = '\0'; //最后的变换为0,起是否选择n作用
        printf("%s\t", tmp);
        return 1;  //数量+1
    }
    else{
        tmp[index] = str[strlen(str)-1 - n]; //默认选取index,反转一下正序,也可以只是n 
        case1 = P(str, n - 1, index + 1); //继续选,所以index+1
        case2 = P(str, n - 1, index); //不选,由于默认选取了,需要覆盖,所以不加1
    }
    //printf("\n");
    return case1 + case2;  //数量总和
}

int main() {
    char tmp[10];
    int cnt;
    printf("输入字符串: ");
    scanf("%s", tmp);
    cnt = P(tmp, strlen(tmp)-1, 0);
    printf("共有%d情况", cnt);
    return 0;
}

运行结果:

输入字符串: abc
abc ab ac a bc b c 共有8情况

 

5.插入排序

代码:

import java.util.Arrays;

/*
 * 应用插入排序对序列2,6,1,4,5,3,2进行排序
 */

public class InsertSort {
    public static void main(String[] args) {
        int[] a = { 2, 6, 1, 4, 5, 3, 2 };
        Insertsort(a);
        System.out.println(Arrays.toString(a));
    }

    public static void Insertsort(int[] a) {
        int i, j;
        for (i = 1; i < a.length; i++) {
            int cur = a[i]; // 待比较值
            for (j = i - 1; j >= 0 && a[j] > cur; j--) {
                a[j + 1] = a[j];
            }
            a[j + 1] = cur;

        }
    }
}

运行结果:

[1, 2, 2, 3, 4, 5, 6]

 

6.俄式乘法

代码:

import java.util.Scanner;

public class RussianMultiplication {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入两个数字(回车符间隔)");
        int n = sc.nextInt();
        int m = sc.nextInt();
        sc.close();
        int res = Rmult(n, m);
        System.out.printf("%d * %d == %d", n, m, res);
    }

    public static int Rmult(int n, int m) {
        int sum = 0;
        while (n != 0) {
            if (n % 2 != 0) {
                n--; // 奇数情况
                sum += m;
            } else {
                n >>= 1;
                m <<= 1;
            }
        }
        return sum;
    }
}

运行结果:

请输入两个数字(回车符间隔)
50
65
50 * 65 == 3250

 

7.AVL树

public class AVLTree<Key extends Comparable<? super Key>, Value> {
    private class Node {
        Key key;// 键,相当于词典里的单词
        Value value;// 值,相当于词典里的单词解释
        int height;// 结点的高度
        Node left;
        Node right;

        public Node(Key key, Value value) {
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
            int height = 1;
        }
    }

    private Node root; // 根节点

    public AVLTree() {
        root = null;
    }

    // 获取节点高度
    private int height(Node node) {
        if (node != null) {
            return node.height;
        }
        return 0;
    }

    // 获取根高度
    public int height() {
        return height(root);
    }

    private int max(int a, int b) {
        return a > b ? a : b; // 获取较大值
    }

    // 替换节点?
    private void replaceNode(Node src, Node tar) {
        tar.key = src.key;
        tar.value = src.value;
    }

    // 遍历----------------------------------------------------
    // 先序遍历
    private void preOrder(Node node) {
        if (node != null) {
            System.out.print(node.key + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    public void preOrder() {
        preOrder(root);
    }

    // 中序遍历
    private void inOrder(Node node) {
        if (node != null) {
            inOrder(node.left);
            System.out.print(node.key + " ");
            inOrder(node.right);
        }
    }

    public void InOrder() {
        inOrder(root);
    }

    // 后序遍历
    private void postOrder(Node node) {
        if (node != null) {
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.key + " ");
        }
    }

    public void postOrder() {
        postOrder(root);
    }
    // -------------------------------------------------------

    // 查找key位置
    private Node search(Node node, Key key) {
        if (node == null) {
            return null;
        } else if (key.compareTo(node.key) == 0) {
            return node;
        } else if (key.compareTo(node.key) < 0) {
            return search(node.left, key); // 左子树
        } else {
            // key.compareTo(node.key) > 0
            return search(node.right, key); // 右子树
        }
    }

    public Node Search(Key key) {
        return search(root, key);
    }

    // 返回最小左节点
    private Node minNode(Node node) {
        if (node == null) {
            return null;
        } else if (node.left == null) {
            return node;
        } else {
            return minNode(node.left);
        }
    }

    public Node minNode() {
        return minNode(root);
    }

    // 返回最大右节点
    private Node maxNode(Node node) {
        if (node == null) {
            return null;
        } else if (node.right == null) {
            return node;
        } else {
            return maxNode(node.right);
        }
    }

    public Node maxNode() {
        return maxNode(root);
    }

    // 旋转----------------------------------------------------
    public Node leftLeftRotation(Node k1) {
        /*
         * LL单旋转 --- 右旋转
         */
        Node k2 = k1.left; // 失衡点左子树是k2
        k1.left = k2.right; // k2的右子树变为 失衡点k1的左子树
        k2.right = k1; // k2的右子树变为k1
        // 重新计算各子树的高度
        k1.height = max(height(k1.left), height(k1.right)) + 1;
        k2.height = max(height(k2.left), height(k2.right)) + 1;
        return k2; // 返回平衡后的点k2
    }

    public Node rightRightRotation(Node k1) {
        /*
         * RR单旋转 --- 左旋转
         */
        Node k2 = k1.right; // 失衡点左子树是k2
        k1.right = k2.left; // k2的右子树变为 失衡点k1的左子树
        k2.left = k1; // k2的右子树变为k1
        // 重新计算各子树的高度
        k1.height = max(height(k1.left), height(k1.right)) + 1;
        k2.height = max(height(k2.left), height(k2.right)) + 1;
        return k2; // 返回平衡后的点k2
    }

    public Node leftRightRotation(Node k1) {
        /*
         * LR双旋转
         */
        k1.left = rightRightRotation(k1.left); // 左旋
        return leftLeftRotation(k1); // 右旋
    }

    public Node rightLeftRotation(Node k1) {
        /*
         * RL双旋转
         */
        k1.right = leftLeftRotation(k1.right); // 左旋
        return rightRightRotation(k1); // 右旋
    }
    // -----------------------------------------------------

    // 插入并调整为平衡树
    private Node insert(Node node, Key key, Value value) {
        if (node == null)
            return new Node(key, value);

        if (key.compareTo(node.key) == 0) {// key相同,更新节点
            node.value = value;
        } else if (key.compareTo(node.key) < 0) {
            node.left = insert(node.left, key, value); // 递归找左子树
            if (height(node.left) - height(node.right) == 2) {
                // 不平衡,需要进行调整
                if (key.compareTo(node.left.key) < 0) {
                    node = leftLeftRotation(node); // 比节点的左key小,LL情况
                } else {
                    node = leftRightRotation(node); // 比节点的右key小,RR情况
                }
            }
        } else {
            node.right = insert(node.right, key, value); // 递归找右子树
            if (height(node.right) - height(node.left) == 2) {
                if (key.compareTo(node.right.key) > 0) {
                    node = rightRightRotation(node); // 比节点的右key大,RR情况
                } else {
                    node = rightLeftRotation(node);
                }
            }
        }
        node.height = max(height(node.right), height(node.left)) + 1; // 调整高度
        return node; // 返回根节点
    }

    public void insert(Key key, Value value) {
        this.root = insert(this.root, key, value);
    }

    // 删除
    public Node remove(Node node, Node target) {
        /**
         * @param node 当前子树根节点
         * @parma target 要删除的节点 return 删除后的新的子树根
         */
        if (node == null || target == null)
            return node; // 空情况
        if (target.key.compareTo(node.key) < 0) {
            node.left = remove(node.left, target); // 左子树继续找
            if (Math.abs(height(node.right) - height(node.left)) == 2) { // 失衡
                if (height(node.right.left) < height(node.right.right)) {
                    node = rightRightRotation(node); // 左旋
                } else {
                    node = leftLeftRotation(node); // 右旋
                }
            }
        } else if (target.key.compareTo(node.key) > 0) {
            node.right = remove(node.right, target); // 右子树继续找
            if (Math.abs(height(node.left) - height(node.right)) == 2) {// 失衡
                if (height(node.left.right) < height(node.left.left)) {
                    node = leftLeftRotation(node); // 右旋
                } else {
                    node = rightRightRotation(node); // 左旋
                }
            }
        } else {// node.key == target.key
            if (node.left == null) {
                return node.right; // 左子树null,那么删除后右子树变为根
            } else if (node.right == null) {
                return node.left; // 右子树null,那么删除后左子树变为根
            } else {
                // 左右子树 均存在
                if (height(node.left) > height(node.right)) {
                    // 左子树 深于 右子树
                    Node predecessor = maxNode(node.left);
                    replaceNode(predecessor, node); // 替换
                    node.left = remove(node.left, predecessor);
                } else {// 如果右子树比左子树深(一样深的话无所谓了)
                    Node successor = minNode(node.right);// 找node的后继结点successor
                    replaceNode(successor, node);// successor替换node
                    node.right = remove(node.right, successor);// 再把原来的successor删掉
                }

            }

        }
        return node;
    }

    public void remove(Key key) {
        Node z;
        if ((z = search(root, key)) != null) // 找到key位置
            root = remove(root, z);
    }

    // 销毁AVL树----------------------------------------------
    private void destroy(Node node) {
        if (node == null)
            return;
        if (node.left != null)
            destroy(node.left); // 摧毁左子树
        if (node.right != null)
            destroy(node.right); // 摧毁右子树
        node = null;
    }

    public void destroy() {
        destroy(root);
        System.out.println("销毁完毕");
    }
    // ---------------------------------------------------------

    // 递归输出AVL树的信息------------------------------------------------
    private void print(Node tree, Key key, String pos) {
        if (tree != null) {
            if (pos.equals("")) // tree是根节点
                System.out.printf("%2d is root\n", tree.key);
            else
                System.out.printf("%2d is %2d's %6s child\n", tree.key, key, pos);
            print(tree.left, tree.key, "left"); // 左子树
            print(tree.right, tree.key, "right"); // 右子树
        }
    }

    public void print() {
        if (root != null)
            print(root, root.key, "");
    }
    // -----------------------------------------------------------

    private static int arr[] = { 3, 2, 1, 4, 5, 6, 7, 16, 15, };

    public static void main(String[] args) {
        int i;
        AVLTree<Integer, Integer> tree = new AVLTree<>();

        System.out.printf("*******依次添加: ");
        for (i = 0; i < arr.length; i++) {
            System.out.printf("%d ", arr[i]);
            tree.insert(arr[i], arr[i]);
        }

        System.out.println("\n前序遍历");
        tree.preOrder();

        System.out.println("\n中序遍历");
        tree.InOrder();

        System.out.println("\n后序遍历");
        tree.postOrder();

        System.out.println("\n高度 : " + tree.height());
        System.out.println("最小值: " + tree.minNode().key);
        System.out.println("最大值: " + tree.maxNode().key);
        System.out.println("\n树的详细信息:");
        tree.print();

        i = 5;
        System.out.printf("\n删除节点 : %d", i);
        tree.remove(i);

        System.out.println("树的高度 : " + tree.height());
        System.out.print("中序遍历: ");
        tree.InOrder();
        System.out.println("\n树的详细信息: ");
        tree.print();

        tree.destroy(); // 销毁树
    }
}
View Code

 

运行结果:

*******依次添加: 3 2 1 4 5 6 7 16 15
前序遍历
5 3 2 1 4 7 6 16 15
中序遍历
1 2 3 4 5 6 7 15 16
后序遍历
1 2 4 3 6 15 16 7 5
高度 : 3
最小值: 1
最大值: 16

树的详细信息:
5 is root
3 is 5's left child
2 is 3's left child
1 is 2's left child
4 is 3's right child
7 is 5's right child
6 is 7's left child
16 is 7's right child
15 is 16's left child

删除节点 : 5树的高度 : 3
中序遍历: 1 2 3 4 6 7 15 16
树的详细信息:
6 is root
3 is 6's left child
2 is 3's left child
1 is 2's left child
4 is 3's right child
7 is 6's right child
16 is 7's right child
15 is 16's left child
销毁完毕

 

8.数学三角形

题目:

 

 

 代码:

 1 public class MathematicalTriangle {
 2 
 3     public static void main(String[] args) {
 4         int[][] a = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 , 10} };
 5 
 6         for (int i = 0; i < a.length; i++) {
 7             for (int j = 0; j < a[i].length; j++) {
 8                 System.out.printf("%4d", a[i][j]);
 9             }
10             System.out.println();
11         }
12         System.out.println();
13         int res = minimunTotal(a);
14 
15         System.out.println("min path : " + res);
16     }
17 
18     public static int minimunTotal(int[][] triangle) {
19         int row = triangle.length; //
20         int column = triangle[row - 1].length; //
21 
22         int[][] dp = new int[row][column]; // 辅助矩阵
23         dp[0][0] = triangle[0][0];
24 
25         for (int i = 1; i < row; i++) {
26             // 每一行元素进行推导
27             for (int j = 0; j <= i; j++) {
28                 if (j == 0) {
29                     // 最左端处理
30                     dp[i][j] = dp[i - 1][j] + triangle[i][j];
31                 } else if (j == i) {
32                     // 最右端处理 没有上面
33                     dp[i][j] = dp[i - 1][j - 1] + triangle[i][j];
34                 } else {
35                     dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j];
36                 }
37             }
38         }
39 
40         int res = Integer.MAX_VALUE;
41         for (int i = 0; i < column; i++) {
42             res = Math.min(res, dp[row - 1][i]);
43         }
44 
45         for (int i = 0; i < dp.length; i++) {
46             for (int j = 0; j < dp[i].length; j++) {
47                 System.out.printf("%4d", dp[i][j]);
48             }
49             System.out.println();
50         }
51         return res;
52     }
53 }
View Code

运行结果:

 

 

 

9.最长上升子序

题目:

 

 

代码:

 1 import java.util.Arrays;
 2 
 3 public class LongestSubsequence {
 4     public static void main(String[] args) {
 5         int[] nums = { 5, 8, 9, 2, 3, 1, 7, 4, 6 };
 6         int n = Solution.lengthOfLIS(nums);
 7         System.out.println("\n最长子序长度:" + n);
 8     }
 9 }
10 
11 class Solution {
12 
13     public static int lengthOfLIS(int[] nums) {
14         int len = nums.length, max = 0;
15         int[] dp = new int[len];
16         Arrays.fill(dp, 1); // 初始化为1
17 
18         for (int i = 1; i < len; i++) {
19             for (int j = 0; j < i; j++) {
20                 if (nums[j] < nums[i] && dp[i] < dp[j] + 1) { // 前面有比我小的吗?
21                     dp[i] = dp[j] + 1; // 有的,那就取当前比较大的状态
22                 }
23             }
24             if (max < dp[i]) {
25                 max = dp[i];
26             }
27         }
28 
29         int[] arr = new int[max];
30         System.out.print("最长子序:");
31         for (int i = nums.length - 1; i >= 0; i--) {
32             if (dp[i] == max) {
33                 arr[max - 1] = nums[i];
34                 max--;
35             }
36         }
37         for (int i : arr) {
38             System.out.print(i + " ");
39         }
40 
41         int res = 0;
42         for (int i = 0; i < len; i++) {
43             res = Math.max(res, dp[i]);
44         }
45         return res;
46     }
47 }
View Code

运行结果:

最长子序:2 3 4 6
最长子序长度:4

 

 

 

10.投资分配

题目:

 

 代码:

 1 public class ResourceAllocation {
 2 
 3     public static void main(String[] args) {
 4         int[][] f = { { 0, 0, 0, 0, 0 }, // 没有第0个项目
 5                 { 0, 15, 28, 40, 51 }, { 0, 13, 29, 43, 55 }, { 0, 11, 30, 45, 58 }, };
 6 
 7         System.out.println("最大利润:" + SolutionInvest.investMax(f));
 8     }
 9 }
10 
11 class SolutionInvest {
12     static int M = 4 + 1; // 投资总数+1,4万元, 因为多了一列0向量
13     static int N = 3 + 1; // 项目数+1,3项目, 因为多了一行0向量
14 
15     public static int investMax(int[][] f) {
16         /*
17          * 返回最大利润
18          * 
19          * @param f:投资矩阵
20          */
21 
22         int[][] Fsum = new int[N][M]; // 前N个项目共投资M万元的最大收益
23         int[][] aItem = new int[N][M]; // 共投资M万元时第N个项目的投资金额,用于追溯路径
24 
25         // 初始化表格的情况,即边界情况,具体情况看可表格
26         for (int i = 0; i < M - 1; i++) {
27             Fsum[1][i] = f[1][i];
28             aItem[1][i] = i;
29         }
30 
31         // 第 k 个项目的投资
32         for (int k = 2; k <= N - 1; k++) {
33             // 第一行一列是0,第一行即只投资一个项目的情况已经初始化,故从2开始
34             for (int m = 1; m <= M - 1; m++) { // M是投资数+1,所以此处循环到M-1
35                 // 前 K 个项目共分配 m 万元,计算出当投资m万元时候的最好方案
36                 int max = -1, temp = 0; // 初始化利润为-1
37                 for (int a = 0; a <= m; a++) {
38                     // 第 k 个项目分配 a 万元, 计算对比当投资额为m万元时候,第K个项目的最好投资数
39                     if (f[k][a] + Fsum[k - 1][m - a] > max) {
40                         // fk(x) = d 表示:x 万元投给第 k 个项目的效益为 d.
41                         // 对比 f2(1)+F1(0), f2(0)+F1(1) 得出好的投资方案
42                         max = f[k][a] + Fsum[k - 1][m - a];
43                         temp = a; // 记录总投资为m万元时第k个项目的投资金额
44                     }
45                 }
46                 Fsum[k][m] = max; // 前K个项目共投资m万元时候的最大收益
47                 aItem[k][m] = temp; // 记录投资m万元时候第k个项目的投资金额
48             }
49         }
50         printArray(Fsum);
51         printArray(aItem);
52         printInfo(aItem); // 输出投资信息
53         return Fsum[N - 1][M - 1];
54     }
55 
56     private static void printInfo(int[][] aItem) {
57         int index = M - 1;
58         for (int k = N - 1; k > 0; k--) {
59             System.out.println("第" + k + "个项目,投资" + aItem[k][index] + "万元");
60             index -= aItem[k][index];
61         }
62     }
63 
64     private static void printArray(int[][] a) {
65         for (int i = 0; i < a.length; i++) {
66             for (int j = 0; j < a[i].length; j++) {
67                 System.out.printf("%4d", a[i][j]);
68             }
69             System.out.println();
70         }
71         System.out.println();
72     }
73 }
View Code

运行结果:

0 0 0 0 0
0 15 28 40 0
0 15 29 44 58
0 15 30 45 60

0 0 0 0 0
0 1 2 3 0
0 0 2 2 3
0 0 2 2 3

第3个项目,投资3万元
第2个项目,投资0万元
第1个项目,投资1万元
最大利润:60

 

代码(C语言版):

 1 #include<iostream>
 2 #define N 4//项目数+1  多了一行0矩阵
 3 #define M 5//投资总额+1 多了一列0矩阵
 4 
 5 using namespace std;
 6 
 7 //aItem[3][2]表示共投资2万元第3个项目的投资金额,用于追溯路径
 8 double aItem[N][M] = {0};
 9 //Fsum[3][2]表示前3个项目共投资2万元的最大收益
10 double Fsum[N][M] = { 0 };
11 
12 double investMax(double f[N][M]){
13     // 前一个项目的情况
14     for (int i = 0; i <= M - 1;i++){
15         Fsum[1][i] = f[1][i];
16         aItem[1][i] = i;
17     }
18     // 第 k 个项目
19     for (int k = 2; k <= N - 1;k++){
20         // 前 k 个项目 共 分配 m 万元
21         for (int m = 1; m <= M - 1; m++){
22             double max = -1, temp = 0;
23             // 第 k 个项目分配 a 万元
24             for (int a = 0; a <= m; a++){
25                 if(f[k][a] + Fsum[k-1][m-a] > max){
26                     max = f[k][a] + Fsum[k - 1][m - a];
27                     temp = a;
28                 }
29             }
30             Fsum[k][m] = max; // 前 k 个项目共投资 m 万元的最大收益
31             aItem[k][m] = temp; // 投资 m 万元第 k 个项目的投资金额
32         }
33     }
34     return Fsum[N - 1][M - 1];
35 }
36 
37 void printInfo(){
38     int index = M - 1;
39     for (int k = N - 1; k > 0;k--){
40         cout << "" << k << "个项目,投资" << aItem[k][index] << "万元"<<endl;
41         index -= aItem[k][index]; // 剩余钱数
42     }
43 }
44 
45 int main() {
46 
47     double f[N][M] = {//f[1][2]表示投第1个项目2万元所产生的效益
48         {0, 0, 0, 0, 0},//没有第0个项目
49         {0,15,28,40,51},
50         {0, 13, 29,43,55},
51         {0, 11,30,45,58},
52     };
53     cout << M-1 <<"万元投资"<<N-1<<"项目最大收益为:" << investMax(f) << endl;
54     printInfo();
55 
56     printf("\n");
57     for (int i = 0; i < N;i++){
58         for (int j = 0; j < M;j++)
59             printf("%g \t", aItem[i][j]);
60         printf("\n");
61     }
62 
63     printf("\n");
64     for (int i = 0; i < N;i++){
65         for (int j = 0; j < M;j++)
66             printf("%g \t", Fsum[i][j]);
67         printf("\n");
68     }
69         return 0;
70 }
View Code

运行结果:

4万元投资3项目最大收益为:60
第3个项目,投资3万元
第2个项目,投资0万元
第1个项目,投资1万元

0 0 0 0 0
0 1 2 3 4
0 0 2 2 3
0 0 2 2 3

0 0 0 0 0
0 15 28 40 51
0 15 29 44 58
0 15 30 45 60

 

11.活动安排——贪心算法

 1 public class ActivityArrangement {
 2     public static void main(String[] args) {
 3         int[] s = { 0, 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 };
 4         int[] f = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
 5         int n = 11;
 6         boolean[] a = new boolean[12];
 7         int count = Greedy.ActiveManage(s, f, a, n);
 8         System.out.println("可安排的活动总数:" + count);
 9         System.out.print("选择活动如下:");
10         for (int i = 0; i < a.length; i++) {
11             if (a[i] == true) {
12                 System.out.print(i + " ");
13             }
14         }
15     }
16 }
17 
18 class Greedy {
19     public static int ActiveManage(int[] s, int[] f, boolean a[], int n) {
20         /**
21          * 贪心策略:取当前活动集合中结束时间最早的相容活动,这样可以为未安排的活动留下心网能多的时间,
22          * 也就是说,这种贪心选择的目的是使剩余时间段极大化,以便安排尽可能多的相容活动。
23          * 
24          * @param s  : 活动起始时间
25          * @param f: 活动结束时间
26          * @param a: 是否选择活动
27          * @param n  : 活动总数
28          * @return count: 安排的活动数
29          */
30         a[1] = true; // 默认选择第一个活动
31         int j = 1, count = 1; // count 记录选取到的活动总数
32         for (int i = 2; i <= n; i++) { // 候选集合C
33             if (s[i] >= f[j]) { // 选择函数(贪心策略)
34                 a[i] = true; // 解集合S
35                 j = i;
36                 count++;
37             } else {
38                 a[i] = false;
39             }
40         }
41         return count;
42     }
43 }
View Code

运行结果:

可安排的活动总数:4
选择活动如下:1 4 8 11

 

12.一般背包问题——贪心算法

 1 public class GeneralBackpack {
 2     public static void main(String[] args) {
 3         float[] w = { 0, 10, 30, 20 };
 4         float[] v = { 0, 50, 120, 60 };
 5         float[] x = new float[4];
 6         float C = 50;
 7         int n = 4;
 8         float total = bag.Knapsack(w, v, x, C, n);
 9         System.out.println("总价值:" + total);
10         for (int i = 1; i < x.length; i++) {
11             System.out.printf("第%d个物品数量为:%f,价值为%f\n", i, x[i], x[i] * v[i]);
12         }
13     }
14 }
15 
16 class bag {
17     public static float Knapsack(float[] w, float[] v, float[] x, float C, int n) {
18         /**
19          * n个物品已经按照V/W 由大到小 贪心策略:考虑价值增长和容量消耗二者的综合效果的方法,即每次选择价值与重量比u:/w
20          * 
21          * @param w: 重量
22          * @param v: 价值
23          * @param x: 解
24          * @param C: 背包重量
25          * @param n: 物品数量
26          * @return total 总价值
27          */
28         for (int i = 0; i < n; i++) {
29             x[i] = 0; // 初始化解向量
30         }
31         int i = 1; // 由于从1开始 所以w和v前面都要加0
32         float total = 0; // 总重量
33         while (w[i] < C) { // 可行函数feasible / 解决函数solution
34             x[i] = 1;
35             total = total + v[i]; // 解集合 —— 总价值
36             C = C - w[i]; // 剩余背包重量
37             i++; // 下一个物品
38         }
39         x[i] = C / w[i]; // 使用完剩余的一点空间
40         total = total + v[i] * x[i];
41         return total;
42     }
43 }
View Code

运行结果:

总价值:200.0
第1个物品数量为:1.000000,价值为50.000000
第2个物品数量为:1.000000,价值为120.000000
第3个物品数量为:0.500000,价值为30.000000

 

posted @ 2020-04-29 14:50  EAo  阅读(304)  评论(0编辑  收藏  举报