关闭

dp总结

99人阅读 评论(0) 收藏 举报
分类:

      首先动态规划是解决多阶段决策问题的一种方法。。


     动态规划本质上就是一种排除重复计算的算法,更具体的说,动态规划就是用空间换取时间。

   

   多阶段决策问题:如果一类问题的求解过程可以分为若干个互相联系的阶段,在每一个阶段都需作出决策,并影响到下一个阶段的决策。多阶段决策问题,就是要在可以选择的那些策略中间,选取一个最优策略,使在预定的标准下达到最好的效果.


    而最优性原理即不论初始状态和第一步决策是什么,余下的决策相对于前一次决策所产生的新状态,构成一个最优决策序列。最优决策序列的子序列,一定是局部最优决策子序列。包含有非局部最优的决策子序列,一定不是最优决策序列。。


    使用动态规划普遍比其他方法代码短,所以说如果一道题可以用dp解和遍历解,这时候一定要选dp。。


     那么如何判断选不选用dp呢?

      1:问题具有多阶段决策的特征。
      2:每一阶段都有相应的“状态”与之对应,描述状态的量称为“状态变量”。
      3:每一阶段都面临一个决策,选择不同的决策将会导致下一阶段不同的状态。
      4:每一阶段的最优解问题可以递归地归结为下一阶段各个可能状态的最优解问题,各子问题与原问题具有完全相同的结构

   

     而dp的一般解题思路分为下面几个步骤:

      1、判断问题是否具有最优子结构性质,若不具备则不能用动态规划。
      2、把问题分成若干个子问题(分阶段)。
      3、建立状态转移方程(递推公式)。
      4、找出边界条件。
      5、将已知边界值带入方程。
      6、递推求解。


    举几个经典例子。。

   最经典的莫过于最优子序列了,好多问题都是他的变形。。。


输入数据
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N 个整数,这些整数的取值范围都在0 到10000。
输出要求
最长上升子序列的长度。
输入样例
7
1 7 3 5 9 4 8
输出样例
4


如何把这个问题分解成子问题呢?经过分析,发现 “求以ak(k=1, 2, 3…N)为终点的最长上升子序列的长度”是个好的子问题。
 由上所述的子问题只和一个变量相关,就是数字的位置。因此序列中数的位置k 就是“状态”,而状态 k 对应的“值”,就是以ak 做为“终点”的最长上升子序列的长度。这个问题的状态一共有N 个。状态定义出来后,转移方程就不难想了。 

假定MaxLen (k)表示以ak 做为“终点”的最长上升子序列的长度,那么:
MaxLen (1) = 1
MaxLen (k) = Max { MaxLen (i):1<i < k 且 ai < ak 且 k≠1 } + 1
实际实现的时候,可以不必编写递归函数,因为从 MaxLen(1)就能推算出MaxLen(2),有了MaxLen(1)和MaxLen(2)就能推算出MaxLen(3)……

代码:

int b[MAX_N + 10];
int aMaxLen[MAX_N + 10];
int main()
{
    int i, j, N;
    scanf("%d", & N);
    for( i = 1;i <= N;i ++ )
        scanf("%d", & b[i]);
    aMaxLen[1] = 1;

 for( i = 2; i <= N; i ++ ) 
    { //求以第i 个数为终点的最长上升子序列的长度
        int nTmp = 0; //记录第i 个数左边子序列最大长度
        for( j = 1; j < i; j ++ ) 
        { //搜索以第i 个数左边数为终点的最长上升子序列长度
            if( b[i] > b[j] ) 
            {
                if( nTmp < aMaxLen[j] )
                    nTmp = aMaxLen[j];
            }
        }
        aMaxLen[i] = nTmp + 1;
    }

int nMax = -1;
    for( i = 1;i <= N;i ++ )
        if( nMax < aMaxLen[i])
            nMax = aMaxLen[i];
    printf("%d\n", nMax);
    return 0;
}


————————————————————————————————————————————————————————————————


然后还有的经典题就是斐波那契数列问题或是这类的变形。。。。f(n)=f(n-1)+f(n-2)。。

这种题我的博客里也有好多。。

不举例子了。。



————————————————————————————————————————————————————————————————


       7
      3 8
    8 1 0
   2 7 4 4 
  4 5 2 6 5

第三类经典的就是数塔类了。。。这种题的解题思路就是往上递推,不断的用max函数就可求出来了。。


————————————————————————————————————————————————————————————————

1  2  3  4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

然后还有一类我把它定位格子类,大概的就是从某一个点到另一个点求最大数。。


————————————————————————————————————————————————————————————————


先这些,以后想起来再补充。。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7427次
    • 积分:511
    • 等级:
    • 排名:千里之外
    • 原创:46篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类