zoukankan      html  css  js  c++  java
  • 算法分析习题集 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
    ", 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,起是否选择n作用
            printf("%s	", 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("
    ");
        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
    ", tree.key);
                else
                    System.out.printf("%2d is %2d's %6s child
    ", 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("
    前序遍历");
            tree.preOrder();
    
            System.out.println("
    中序遍历");
            tree.InOrder();
    
            System.out.println("
    后序遍历");
            tree.postOrder();
    
            System.out.println("
    高度 : " + tree.height());
            System.out.println("最小值: " + tree.minNode().key);
            System.out.println("最大值: " + tree.maxNode().key);
            System.out.println("
    树的详细信息:");
            tree.print();
    
            i = 5;
            System.out.printf("
    删除节点 : %d", i);
            tree.remove(i);
    
            System.out.println("树的高度 : " + tree.height());
            System.out.print("中序遍历: ");
            tree.InOrder();
            System.out.println("
    树的详细信息: ");
            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);
     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("
    ");
    57     for (int i = 0; i < N;i++){
    58         for (int j = 0; j < M;j++)
    59             printf("%g 	", aItem[i][j]);
    60         printf("
    ");
    61     }
    62 
    63     printf("
    ");
    64     for (int i = 0; i < N;i++){
    65         for (int j = 0; j < M;j++)
    66             printf("%g 	", Fsum[i][j]);
    67         printf("
    ");
    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
    ", 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

  • 相关阅读:
    [原创]SQL经验
    DotNetBar技巧经验集合
    正则表达式的那些小角落
    [转]验证数字的正则表达式集
    项目受源代码管理。向源代码管理注册此项目时出错。建议不要对此项目进行任何更改
    DateGridView的一些技巧
    个人的CodeSmith和.NetTiers的学习心得及经验总结
    常用代码
    mysql 数据库常用命令
    XP2防火墙拒绝网上邻居访问的解决
  • 原文地址:https://www.cnblogs.com/ymzm204/p/12802159.html
Copyright © 2011-2022 走看看