zoukankan      html  css  js  c++  java
  • 动态规划入门理解

    自己刚刚学习了一下动态规划的思想,属入门级,总结如下:

    Dynamic  动态规划算法通常基于一个或多个初始状态及一个递推公式(状态转移方程)。当前子问题的解将由上一次子问题(或前面某一次)的解推出。使用动态规划来解题只需要多项式时间复杂度, 因此它比回溯法、暴力法等要快许多。


     
     动态规划中,我们要找到某个状态的最优解,然后在它的帮助下,找到下一个状态的最优解。

      举例:
        问题描述:如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
        问题分析:我们思考,如何用最少的硬币凑够i元(i<11)。原因:大问题变小,好分析;但小问题的性质必须和大问题一致。
        分析步骤:
              i=0: d[0] = 0;
              i=1:只能使用1元的硬币:d[1] = d[1-1]+1 = d[0]+1 = 1; d[1] = 1;
              i=2:只能使用1元的硬币:d[2] = d[2-1]+1 = d[1]+1 = 2; d[2] = 2;
              i=3:     使用1元的硬币:d[3] = d[3-1]+1 = d[2]+1 = 3;
                   使用3元的硬币:d[3] = d[3-3]+1 = d[0]+1 = 1;
                          so, d[3] = min{d[3-1]+1, d[3-3]+1};d[3] = 1;
             i=4:        使用1元的硬币:d[4] = d[4-1]+1 = d[3]+1 = 2;
                     使用3元的硬币:d[4] = d[4-3]+1 = d[3]+1 = 2;
                         so, d[4] = min{d[4-1]+1, d[4-3]+1};d[4] = 2;

        
    小结:状态: 凑够i元 所需的硬币数量;
                状态只与它前面出现的状态有关,独立于后面的状态。
        状态转移方程:描述状态之间是如何转移的,d[i] = min{d[i-Vj]+1},其中 i-Vj >= 0;Vj是下一个可取的决策值。

        

    int MaxValue(int **A, int row, int col)
    {
        int **s = new int*[row];
        for (int i =0 ; i < row; i++)
        {
            s[i] = new int[col];
        }
        int temp=0;
        
        for (i = 0; i<row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                temp = 0;
                s[i][j] = A[i][j];
                if (j>0)
                {
                    temp = A[i][j-1];
                }
                if (i>0 && A[i-1][j] > temp )
                {
                    temp = A[i-1][j];
                }
            }
        }
        temp = s[row-1][col-1];
        
        for (i  = 0; i < row; i++)
        {
            delete s[i];
        }
        delete [] s;
        s=NULL;
    
        return temp;
    }


      举例:
        问题描述:LIS:longest increasing subsequence(最长非降序子序列), A[1], A[2]....A[N]
        问题分析:
        找状态:求A[1], A[2]....A[i](i<N) 中的最长非降序子序列。
        状态转移方程:d[i] = max{1, d[j]+1}, j<i, A[j]<=A[i];

        

    int LIS(int *arr, int n)
    {
        int *d = new int[n];
        int len = 1;;
        memset( d, 0, n);
        for (int i = 0; i < n; i++)
        {    
            d[i] = 1;
            for (int j = 0; j <i; j++)
            {
                if(arr[j] <= arr[i] && d[i] < d[j] + 1)
                {
                    d[i] = d[j] + 1;
                }
            }
            if (d[i] > len)
            {
                len = d[i];
            }
        }
        delete[] d;
        d = NULL;
        
        return len;
    }
    LIS

      举例:
        问题描述:平面上有N*M个格子(A[N][M]),每个格子中放着一定数量的苹果。你从左上角的格子开始, 每一步只能向下走或是向右走,
              每次走到一个格子上就把格子里的苹果收集起来, 这样下去,你最多能收集到多少个苹果。
        问题分析:
        找状态:s[i][j],走到 i,j 时收集到的苹果数量
        状态转移方程:s[i][j] = A[i][j] + max(S[i-1][j], if i>0 ; S[i][j-1], if j>0)

        代码如下:

    int MaxValue(int **A, int row, int col)
    {
        int **s = new int*[row];
        for (int i =0 ; i < row; i++)
        {
            s[i] = new int[col];
        }
        int temp=0;
        
        for (i = 0; i<row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                temp = 0;
                s[i][j] = A[i][j];
                if (j>0)
                {
                    temp = A[i][j-1];
                }
                if (i>0 && A[i-1][j] > temp )
                {
                    temp = A[i-1][j];
                }
            }
        }
        temp = s[row-1][col-1];
        
        for (i  = 0; i < row; i++)
        {
            delete s[i];
        }
        delete [] s;
        s=NULL;
    
        return temp;
    }
    代码
  • 相关阅读:
    hdu 5475(打破固定思维OR线段树)
    hdu 2521 反素数(打表)
    hdu 4540(dp)
    hdu 4535(排列组合之错排公式)
    hdu 4530(数学)
    hdu 4528(搜索好题)
    hdu 4522(图论,构图)
    kalinux 换源
    用python进行wifi密码生成
    hashcat 中文文档
  • 原文地址:https://www.cnblogs.com/OrdinaryMiracle/p/4823065.html
Copyright © 2011-2022 走看看