zoukankan      html  css  js  c++  java
  • 动态规划(java)

    问题一:最大子组和问题
    子组中的元素可能是正负或0,思路:
    最大子组和就是所有可能的子组和中最大的,那么可能比较大的首先有一个初始值(0),然后如果有比初始值大的子组和,就用来替代当前的最大子组和,直到遍历结束再也没有比当前子组和更大的。
    当子组和为负的时候,肯定不是我们期望的最大子组和的一部分,因为负的累积值和后续的子组元素的和,肯定小于后续子组元素的和。这时可以排除该子组和的元素,从使累计子组和为正的开始重新统计。
    当遍历结束最大子组和等于初始值0时,说明数组元素都是非正的,那么遍历找出最大的负数。

    /**
     * @author Flying
     *         题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
     *         求所有子数组的和的最大值。要求时间复杂度为O(n)。 浙大数据结构课本上有 思路:
     *         求连续数字之和,当和为负值,抛弃.当和为正值,比较其与最大值,如大于,则替换之
     *         http://zhedahht.blog.163.com/blog/static/254111742007219147591/
     *         http://blog.csdn.net/v_JULY_v/article/details/6444021
     */
    public class FindMaxSumOfSubArray {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            FindMaxSumOfSubArray f = new FindMaxSumOfSubArray();
            int[] arr = { 1, -2, 3, 10, -4, 7, 2, -5 };
            System.out.println("MaxSum:" + f.findMaxSum(arr));
        }
    
        public Integer findMaxSum(int[] arr) {
            int curSum = 0;
            int maxSum = 0;
            int len = arr.length;
    
            if (arr == null || len == 0) {
                return null;
            }
    
            for (int i = 0; i < len; i++) {
                curSum += arr[i];
                if (curSum < 0) {
                    curSum = 0;
                }
                if (curSum > maxSum) {
                    maxSum = curSum;
                }
            }
    
            // all data are negative
            if (maxSum == 0) {
                for (int i = 0; i < len; i++) {
                    if (i == 0) {
                        maxSum = arr[i];
                    }
                    if (arr[i] > maxSum) {
                        maxSum = arr[i];
                    }
                }
            }
            return maxSum;
        }
    }

    问题二:背包问题
    这是我看过讲背包问题,最容易理解的帖子
    http://m.blog.csdn.net/article/details?id=7722810
    01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }
    f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。
    Pi表示第i件物品的价值。
    决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中吗 ?

    题目描述:
    有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

    这里写图片描述
    只要你能通过找规律手工填写出上面这张表就算理解了01背包的动态规划算法。
    首先要明确这张表是至底向上,从左到右生成的。
    为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了。
    对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。
    同理,c2=0,b2=3,a2=6。
    对于承重为8的背包,a8=15,是怎么得出的呢?
    根据01背包的状态转换方程,需要考察两个值,
    一个是f[i-1,j],对于这个例子来说就是b8的值9,另一个是f[i-1,j-Wi]+Pi;
    在这里,
    f[i-1,j]表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值
    f[i-1,j-Wi]表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值
    f[i-1,j-Wi]就是指单元格b6,值为9,Pi指的是a物品的价值,即6
    由于f[i-1,j-Wi]+Pi = 9 + 6 = 15 大于f[i-1,j] = 9,所以物品a应该放入承重为8的背包
    下面是java实现:
    http://blog.csdn.net/lovesqcc/article/details/5859223

    public class KnapsackProblem {
         /** 指定背包 */ 
        private Knapsack[] bags; 
    
        /** 总承重  */ 
        private int totalWeight; 
    
        /** 给定背包数量  */ 
        private int n; 
    
        /** 前 n 个背包,总承重为 totalWeight 的最优值矩阵  */ 
        private int[][] bestValues; 
    
        /** 前 n 个背包,总承重为 totalWeight 的最优值 */ 
        private int bestValue; 
    
        /** 前 n 个背包,总承重为 totalWeight 的最优解的物品组成 */ 
        private ArrayList<Knapsack> bestSolution; 
    
        public KnapsackProblem(Knapsack[] bags, int totalWeight) { 
            this.bags = bags; 
            this.totalWeight = totalWeight; 
            this.n = bags.length; 
            if (bestValues == null) { 
                bestValues = new int[n+1][totalWeight+1]; 
            } 
        } 
    
        /**
         * 求解前 n 个背包、给定总承重为 totalWeight 下的背包问题
         * 
         */ 
        public void solve() { 
    
            System.out.println("给定背包:"); 
            for(Knapsack b: bags) { 
                System.out.println(b); 
            } 
            System.out.println("给定总承重: " + totalWeight); 
    
            // 求解最优值 
            for (int j = 0; j <= totalWeight; j++) { 
                for (int i = 0; i <= n; i++) { 
    
                    if (i == 0 || j == 0) { 
                        bestValues[i][j] = 0; 
                    }    
                    else  
                    { 
                        // 如果第 i 个背包重量大于总承重,则最优解存在于前 i-1 个背包中, 
                        // 注意:第 i 个背包是 bags[i-1] 
                        if (j < bags[i-1].getWeight()) { 
                            bestValues[i][j] = bestValues[i-1][j]; 
                        }    
                        else  
                        { 
                            // 如果第 i 个背包不大于总承重,则最优解要么是包含第 i 个背包的最优解, 
                            // 要么是不包含第 i 个背包的最优解, 取两者最大值,这里采用了分类讨论法 
                            // 第 i 个背包的重量 iweight 和价值 ivalue 
                            int iweight = bags[i-1].getWeight(); 
                            int ivalue = bags[i-1].getValue(); 
                            bestValues[i][j] =  
                                Math.max(bestValues[i-1][j], ivalue + bestValues[i-1][j-iweight]);       
                        } // else 
                    } //else          
               } //for 
            } //for 
    
            // 求解背包组成 
            if (bestSolution == null) { 
                bestSolution = new ArrayList<Knapsack>(); 
            } 
            int tempWeight = totalWeight; 
            for (int i=n; i >= 1; i--) { 
               if (bestValues[i][tempWeight] > bestValues[i-1][tempWeight]) { 
                   bestSolution.add(bags[i-1]);  // bags[i-1] 表示第 i 个背包 
                   tempWeight -= bags[i-1].getWeight(); 
               } 
               if (tempWeight == 0) { break; } 
            } 
            bestValue = bestValues[n][totalWeight]; 
        } 
    
        /**
         * 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值
         * 调用条件: 必须先调用 solve 方法
         * 
         */ 
        public int getBestValue() {  
            return bestValue; 
        } 
    
        /**
         * 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵
         * 调用条件: 必须先调用 solve 方法
         * 
         */ 
        public int[][] getBestValues() { 
    
            return bestValues; 
        } 
    
        /**
         * 获得前  n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵
         * 调用条件: 必须先调用 solve 方法
         * 
         */ 
        public ArrayList<Knapsack> getBestSolution() { 
            return bestSolution; 
        } 
        public static void main(String[] args) { 
    
            Knapsack[] bags = new Knapsack[] { 
                    new Knapsack(2,13), new Knapsack(1,10), 
                    new Knapsack(3,24), new Knapsack(2,15), 
                    new Knapsack(4,28), new Knapsack(5,33), 
                    new Knapsack(3,20), new Knapsack(1, 8) 
            }; 
            int totalWeight = 12; 
            KnapsackProblem kp = new KnapsackProblem(bags, totalWeight); 
    
            kp.solve(); 
            System.out.println(" -------- 该背包问题实例的解: --------- "); 
            System.out.println("最优值:" + kp.getBestValue());  
            System.out.println("最优解【选取的背包】: "); 
            System.out.println(kp.getBestSolution()); 
            System.out.println("最优值矩阵:"); 
            int[][] bestValues = kp.getBestValues(); 
            for (int i=0; i < bestValues.length; i++) { 
                for (int j=0; j < bestValues[i].length; j++) { 
                    System.out.printf("%-5d", bestValues[i][j]); 
                } 
                System.out.println(); 
            } 
        } 
    
    }
    public class Knapsack {
        /** 背包重量  */ 
        private int weight; 
    
        /** 背包物品价值  */ 
        private int value; 
        /***
         * 构造器
         */ 
        public Knapsack(int weight, int value) { 
            this.value = value; 
            this.weight = weight; 
        } 
        public int getWeight() { 
            return weight; 
        } 
    
        public int getValue() { 
            return value; 
        } 
    
        public String toString() { 
            return "[weight: " + weight + " " + "value: " + value + "]";   
        } 
    
    }

    最长公共子串
    http://blog.csdn.net/biangren/article/details/8038605

  • 相关阅读:
    Hihocoder 1275 扫地机器人 计算几何
    CodeForces 771C Bear and Tree Jumps 树形DP
    CodeForces 778D Parquet Re-laying 构造
    CodeForces 785E Anton and Permutation 分块
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale 二分
    Hexo Next 接入 google AdSense 广告
    如何统计 Hexo 网站的访问地区和IP
    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points
    通过ODBC接口访问人大金仓数据库
  • 原文地址:https://www.cnblogs.com/zhangdebin/p/5567881.html
Copyright © 2011-2022 走看看