zoukankan      html  css  js  c++  java
  • Dynamic Programming (I)

    1. Dynamic Programming

      Generally speaking, Dynamic Programming (DP) is an algorithmic paradigm where we solve an optimization problem with optimal structure in a bottom-up way to avoid overlapping sub-problems. According to CLRS, a problem exhibits optimal structure if you need to find the solution to its sub-problems before accomplishing the whole optimization problem. In this sense, every problem that can be solved by DP is based on a DAG structure, where each node is a sub-problem and a sub-problem can be solved only if its preceding sub-problems have been solved.

      We refuse to solve the DP problems in a recursive way in that we will be faced with a lot of overlapping sub-problems, which render such solution awfully inefficient. Usually, we choose to sacrifice space in order to save time when we exploit the optimal structure of an optimization problem. Moreover, there are some space compression techniques to minimize the cost of a solution. 


    2. Knapsack Problems

      About the description of Knapsack Problems, please refer to wikipedia.

      (1)  Here is my solution to Knapsack with repetition:

     1     public static int solve(int num, int vol)   {
     2         // Here we use DP to solve Unbounded Knapsack Problem
     3         // Precondition: cost[] and value[] are the weights and values
     4         //            of the num objects respectively
     5         // Postcondition: the maximum value that a knapsack with 
     6         //            capacity vol can contain is returned
     7         int[] dp = new int[vol+1];
     8         for (int i=0;i<=vol;i++){
     9             // Solve the problem in a bottom-up way, so that
    10             //        for all j<=i dp[j] will be the max value that a knapsack
    11             //        of capacity v can contain
    12             for (int j=0;j<=num;j++){
    13                 if (cost[j]<=i && dp[i-cost[j]]+value[j]>dp[i]) {
    14                     dp[i] = dp[i-cost[j]]+value[j];
    15                 }
    16             }
    17         }
    18         return dp[vol];
    19     }

      (2)  This is my solution to Knapsack without repetition:

     1     public static int solve(int num,int vol)  {
     2         // Here we use DP to solve 0 - 1 Knapsack Problem
     3         // Precondition: cost[] and value[] are the weights and values
     4         //            of the num objects respectively
     5         // Postcondition: the maximum value that a knapsack with 
     6         //            capacity vol can contain is returned
     7         int [][] dp = new int[vol+1][num+1];
     8         //     dp[i][j] will be the max value that a knapsack of capacity i
     9         //            can contain by choosing objects from 0 to j-1
    10         // Basic Cases:    dp[i][j] = 0, for all (i==0||j==0)
    11         for (int j=1;j<=num;j++) {
    12             for (int i=1;i<=vol;i++) {
    13                 dp[i][j] = dp[i][j-1];
    14                 if (cost[j-1]<=i && dp[i-cost[j-1]][j-1]+value[j-1]>dp[i][j]) {
    15                     dp[i][j] = dp[i-cost[j-1]][j-1]+value[j-1];
    16                 }
    17             }
    18         }
    19         return dp[vol][num];
    20     }

    3. Maximum Sum of Consecutive Subsequence

      Many dynamic programming problems relies on a recursive structure like sequences, such as the classical Longest Common Subsequence introduced in CLRS. In this section, I wish to offer my solution to POJ 2479, a problem that requires to calculate the maximum sum among all the consecutive sub-sequences of a given integer sequence.

     1 import java.util.*;
     2 
     3 public class Main {
     4     public static Scanner in;
     5     public static int num;
     6     public static int [][] dp;
     7     
     8     public static long maxSum()  {
     9         for (int i=1;i<num;i++) {
    10             // Invariant: for j<=i, dp[j][0] will be the max
    11             //        sum of all the sub-sequences ending at j
    12             if (dp[i-1][0]>0) {
    13                 dp[i][0]+=dp[i-1][0];
    14             }
    15         }
    16         for (int i=1;i<num;i++) {
    17             // Invariant: for j<=i, dp[j][0] will be the max
    18             //        sum of all the sub-sequences whose ending
    19             //        index is no larger than j
    20             if (dp[i-1][0]>dp[i][0]) {
    21                 dp[i][0] = dp[i-1][0];
    22             }
    23         }
    24         for (int i=num-2;i>=0;i--) {
    25             // Invariant: for j>=i, dp[j][0] will be the max
    26             //        sum of all the sub-sequences starting at j
    27             if (dp[i+1][1]>0) {
    28                 dp[i][1]+=dp[i+1][1];
    29             }
    30         }
    31         for (int i=num-2;i>=0;i--) {
    32             // Invariant: for j>=i, dp[j][0] will be the max
    33             //        sum of all the sub-sequences whose starting
    34             //        index is no less than j
    35             if (dp[i+1][1]>dp[i][1]) {
    36                 dp[i][1] = dp[i+1][1];
    37             }
    38         }
    39         int val = dp[0][0]+dp[num-1][1];
    40         for (int i=1;i<num;i++) {
    41             if (dp[i-1][0]+dp[i][1]>val) {
    42                 val = dp[i-1][0]+dp[i][1];
    43             }
    44         }
    45         return val;
    46     }
    47     public static void main(String[] args) {
    48         in = new Scanner(System.in);
    49         dp = new int [50000][2];
    50         int t = in.nextInt();
    51         String line; StringTokenizer str;
    52         for (int i=0;i<t;i++) {
    53             num = in.nextInt();
    54             in.nextLine();        // skip the newline symbol
    55             line = in.nextLine();     // nextInt() is too time-consuming
    56             str = new StringTokenizer(line);
    57             for (int j=0;j<num;j++) {
    58                 dp[j][0] = dp[j][1] = Integer.parseInt(str.nextToken());
    59             }
    60             System.out.println(maxSum());
    61         }
    62         in.close();
    63     }
    64 }

    References:

      1. Cormen, T. H. et al. Introduction to Algorithms[M].北京:机械工业出版社,2006-09
      2. Dasgupta, Sanjoy, Christos Papadimitriou, and Umesh Vazirani. Algorithms[M].北京:机械工业出版社,2009-01-01

  • 相关阅读:
    html页面模板布局内容的继承,block
    url分发
    显示年月,注册页面和后台数据交互,不涉及数据库
    static文件夹中文件引用方式,如html页面引用js
    pycharm写django之返回一个页面
    pycharm编写django第一步
    VUE清除keepalive页面缓存
    js设置html根节点的style字体【Vue动态调整全局字体大小】
    npm 依赖重新安装或更新版本
    antd 自定义表头slots.title不生效
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411444.html
Copyright © 2011-2022 走看看