• 递推与记忆化搜索


     内容参考书籍《算法竞赛入门到进阶》

    先看一道经典题:poj1163 http://poj.org/problem?id=1163

     如果此题按照从上往下的方法计算,每走一步下一步就有2种选择,其复杂度为2n

    那么我们从下往上算,下面给出dfs代码:

    int dfs(int i,int j)
    {
    	if (i == n) return a[i][j];//递归到最后一行返回
    	return dp[i][j] = max(dfs(i+1,j),dfs(i+1,j+1))+ a[i][j];
    }

    从1,1开始往下走,一直到最后一行,返回,每一次取能走到该点的最大值加上该点,继续返回,代码很好理解,只是复杂度为2n

    下面我们再来讲一下递推,代码如下:

      for (int j = 1; j <= n; ++j) dp[n][j] = a[n][j];
      for (int i = n-1; i >= 1; --i)
      {
        for (int j = 1; j <= i; ++j)     {   dp[i][j] = max(dp[i+1][j],dp[i+1][j+1]) + a[i][j];     }
      }   cout<<dp[1][1]<<endl;

    首先是第一层循环,将三角形最下面一层全部赋值给dp,然后从下往上求解,输出dp[1][1]即是最大值。这样复杂度便只有n2

    那么搜索可以做到吗?当然可以,这就是我们说的记忆化,只需要在搜索算法中加入if即可,代码如下:

    int dfs(int i,int j)
    {
    	if (i == n) return a[i][j];//递归到最后一行返回
    	if (dp[i][j] >= 0) return dp[i][j];//记忆
    	return dp[i][j] = max(dfs(i+1,j),dfs(i+1,j+1))+ a[i][j];
    }
    

     这样搜索算法的复杂度也降到了n2,为什么要加这样一句话呢?我们可以发现,当我们从第2层的“3”往下走会经过“1”,计算一次从1出发的递归;从第2层的“8”往下走也会经过“1”,又重新计算了“1”出发的递归,为了避免这样的重复,使用记忆化便能避免,从而降低复杂度。

  • 相关阅读:
    关于字符编码
    cocosbuilder中使用字体描边时,字符重叠,间距过小问题
    2dx关于js响应layer触摸消息的bug
    关于js-binding中Layer触摸事件的优化
    2dx解析cocosbuilder中使用layer时的缺陷
    关于 2dx v3.7 UIScale9Sprite的bug
    c++11 Chrono时间库
    cocos2d-x lua table数据存储
    cocos2d-x lua 使用ListView
    Oracle数据库impdp时ora-00439:未启用功能:Deferred Segment Creation
  • 原文地址:https://www.cnblogs.com/125418a/p/12943702.html
Copyright © 2020-2023  润新知