• 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

  • 相关阅读:
    51nod 1574 排列转换(猜结论)
    百度之星资格赛 1005 寻找母串(分块打表+组合数计算)
    百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)
    百度之星资格赛 1003 度度熊与邪恶大魔王(二维dp)
    HDU 4542 小明系列故事——未知剩余系 (数论|反素数)
    51nod 1060 最复杂的数(反素数)
    eclipse hadoop环境搭建 查看HDFS文件内容
    Windows jdk安装以及版本切换
    WIN10配置MongoDB
    Oracle 11g R2 for Win10(64位)的安装步骤
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411444.html
Copyright © 2020-2023  润新知