zoukankan      html  css  js  c++  java
  • 15.Dynamic Programming(1)

    DP is a kind of tabular method, like divide-and-conquer method, applying when subproblems overlap.(sharing subsubproblems).

    A DP algorithm solves each subsubproblems only once and then saves its answer in a table.

    A divide-and-conquer algorithm does more work than necessary. It repeatedly solves the subsubproblems.

    15.1 Rod cutting problem

    lenght i 1 2 3 4 5 6 7 8 9 10
    price  pi 1 5 8 9 10 17 17 20 24 30

    For the table above, the optimal solution is:

                                                  image

    Suppose we divide a rod into n pieces, we should have n-1 cuts at the rod. There is 2^(n-1) different cut ways of length n.

    Optimal revenue values of rod n,can be caculated by

                                                                                         

    where .

    We can view ,saying that the first piece has size of i = n, and the remainder has the size n-i=n-n=0 with corresponding revenue .

    As the following arithmetics,we can rewrite the formula above as

                                       

    Algorithms as follows:

    1.naive recursive top-down implementation

    View Code
     1 #include <iostream>
     2  using namespace std;
     3  #include <ctime>
     4  //naive recursive method
     5  int RotCut(int* p, int n)
     6  {
     7      if (n==0)
     8      {
     9          return 0;
    10      }
    11      int i;
    12      int q = INT_MIN;
    13  
    14  
    15      // q=max(p[i]+r[n-i]), p为数组,从0开始
    16      for( i=1; i<=n; i++)
    17      {
    18          int k = p[i-1] + RotCut(p,n-i);
    19          if (q < k)
    20          {
    21              q = k;
    22          }        
    23      }
    24      return q;
    25  }
    26  int main()
    27  {
    28      // p[] = {1,5,8,9,10,17,17,20,24,30}
    29      int p[100] ={1,5,8,9,10,17,17,20,24};
    30      time_t tic = time(NULL);
    31      int k = RotCut(p,25);
    32      time_t toc = time(NULL);
    33      cout<<"optimal value:"<<k<<"  "<<"time: "<<(toc-tic)*1000<<"ms"<<endl;
    34      return 0;
    35  }

        The results run by this program is listed as follows:

    n 4 8 20 25 30
    optimal val 10 22 56 69 85
    run time 0 0 0 1s 27s

        This recursive CUT_ROD is very inefficient, cause it calls itself over and over with the same parameter values, that is ,it solve the same subproblems repeatedly.For example, figure follows illustrates what happens when n is 4.The running time of CUT-ROD is exponential in n.

                                                           image

    2.DP for optimal rod cutting

           Using DP can convert CUT-ROD into an efficient algorithm, making

           DP solves each subproblems only once by using additional memory to improve efficiency.There are two equivalent ways to implement DP algorithm: (1)top-down with memoization and (2)bottom-up method.

    (1) Top-down with memoization

    Recursively anyway, but save the result of each subproblem ( n subproblems ) in an array  r[] initial with 0s or a hash table. The array is used for check wether a subproblem was solved, if the ith subproblem was solved, its value was stored in r[i] > 0.

    View Code
     1 #include <iostream>
     2 using namespace std;
     3 #include <ctime>
     4 const int MAXiSIZE=2000;
     5 //Top-down with memoization method
     6 int MemoizedCutRodAux(int *p, int n, int *r)
     7 {     //using an addition array r[] to store optimal subproblems value
     8     if ( r[n] >= 0)
     9         return r[n];
    10     int q,i,k;
    11     if ( n == 0)
    12     {
    13         q = 0;
    14     }
    15     else 
    16     {
    17         q = INT_MIN;// iter method
    18         for ( i=1; i<=n; i++)
    19         {
    20             k = p[i-1] + MemoizedCutRodAux(p,n-i,r);
    21             if ( q<k )
    22                 q =k;                    
    23         }
    24     }
    25     r[n] = q;
    26     return q;    
    27 }
    28 
    29 int MemoizedCutRod(int *p, int n)
    30 {
    31     int i;
    32     int r[MAXiSIZE];//auxiliary array initialized with minimum
    33     for ( i=0; i<=n; i++)
    34     {
    35         r[i] = INT_MIN;    
    36     }
    37     return MemoizedCutRodAux(p,n,r);
    38 }
    39 int main()
    40 {
    41     // p[] = {1,5,8,9,10,17,17,20,24,30}
    42     int p[MAXISIZE] ={1,5,8,9,10,17,17,20,24};
    43     /*time_t tic = time(NULL);
    44     int k = RotCut(p,25);
    45     time_t toc = time(NULL);
    46     cout<<"optimal value:"<<k<<"  "<<"time: "<<(toc-tic)*1000<<"ms"<<endl;*/
    47     
    48     clock_t start = clock();
    49     int k = MemoizedCutRod(p,1000);
    50     clock_t end = clock();
    51     cout<<"optimal value:"<<k<<"  "<<"time: "<<double(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
    52     //int k = BottomUpCutRod(p,40);
    53     //cout<<k<<endl;
    54 
    55     //SolutionOfCutRod(p,40);
    56     return 0;
    57 }
    n 4 20 30 1000 1999
    optimal val 10 56 85 2832 INT_MAX
    run time 0 0 0 0.015s 0.047s

    (2)bottom-up method

      Not recursively, but iteratively.  Solve the subproblems by size and solve them in size order, smallest first.

    View Code
     1 #include <iostream>
     2 using namespace std;
     3 #include <ctime>
     4 const int MAXiSIZE=2000;
     5 int BottomUpCutRod(int *p, int n)
     6 {
     7     int r[MAXiSIZE];//auxiliary array initialized with minimum
     8     r[0] = 0;
     9     
    10     int i,j,k;
    11     for ( j=1; j<=n; j++)
    12     {
    13         int q = INT_MIN;
    14         for ( i=1; i<=j; i++)
    15         {
    16             k = p[i-1] + r[j-i];
    17             if ( q < k )
    18                 q = k;
    19             r[j] = q;
    20         }
    21     }
    22     return r[n];
    23 }
    24 int main()
    25 {
    26     // p[] = {1,5,8,9,10,17,17,20,24,30}
    27     int p[MAXISIZE] ={1,5,8,9,10,17,17,20,24};
    28 
    29     clock_t start = clock();
    30     //int k = MemoizedCutRod(p,1999);
    31     int k = BottomUpCutRod(p,40);
    32     clock_t end = clock();
    33     cout<<"optimal value:"<<k<<"  "<<"time: "<<double(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
    34 
    35     return 0;
    36 }
    n 4 20 30 1000 1999
    optimal val 10 56 85 2832 INT_MAX
    run time 0 0 0 0 0.016s

      

    3.Solution

    Easy part for this example, only need a list store every piece size.

    Solution
     1 #include <iostream>
     2 using namespace std;
     3 #include <ctime>
     4 const int MAXiSIZE=2000;
     5 int ExtendedBottomUpCutRod(int *p, int n, int* r, int *s)
     6 {
     7     
     8     int i,j,k;
     9     for ( j=1; j<=n; j++)
    10     {
    11         int q = INT_MIN;
    12         for ( i=1; i<=j; i++)
    13         {
    14             k = p[i-1] + r[j-i];
    15             if ( q < k )
    16             {
    17                 q = k;
    18                 s[j] = i;// here is the add item
    19             }
    20             r[j] = q;
    21             
    22         }
    23     }
    24     return r[n];
    25     
    26 }
    27 
    28 int SolutionOfCutRod(int *p, int n)
    29 {
    30     int s[MAXiSIZE],r[MAXiSIZE];
    31     r[0] = 0;
    32 
    33     ExtendedBottomUpCutRod(p,n,r,s);
    34     cout<<"value of solution: "<<r[n]<<endl<<"solution:";
    35     while ( n>0 )
    36     {
    37         cout<<s[n]<<" ";
    38         n = n - s[n];
    39     }
    40     cout<<endl;
    41     return r[n];
    42 
    43 }
    44 
    45 int main()
    46 {
    47     // p[] = {1,5,8,9,10,17,17,20,24,30}
    48     int p[MAXISIZE] ={1,5,8,9,10,17,17,20,24};
    49     
    50     SolutionOfCutRod(p,40);
    51     return 0;
    52 }

     image

  • 相关阅读:
    Android自启动
    Eclipse导出Javadoc文件
    MAC 下Java Android 环境配置
    MAC 下如何切换Android模拟器的横竖屏
    程序员 需要掌握得600个英语单词
    网络编程 套接字socket 及 粘包
    网络编程 文件传输 基于UDP的socket serversocket
    网络编程 之 网络协议
    面向对象之:反射, 双下方法
    面向对象之 类的成员与异常处理
  • 原文地址:https://www.cnblogs.com/baiweiguo/p/2841055.html
Copyright © 2011-2022 走看看