记忆化搜索

通常说来,动态规划总要遍历全部的状态,而搜索能够排除一些无效状态。更重要的是搜索还能够剪枝,可能剪去大量没必要要的状态,所以在空间开销上每每比动态规划要低不少。记忆化算法在求解的时候仍是按着自顶向下的顺序,可是每求解一个状态,就将它的解保存下来,之后再次遇到这个状态的时候,就没必要从新求解了。这种方法综合了搜索和动态规划两方面的优势,于是仍是颇有实用价值的。记忆化搜索就至关于以搜索的形式加上动态规划的思想。ios

通常遇到一个动态规划类型的问题,都先要肯定最优子结构,还有重叠子问题,这两个是动态规划最大的特征,而后就是要写 动态规划的状态方程,这个步骤十分十分的重要的,写动归方程是须要必定的经验的,这能够经过训练来达到目的。接着就是要自底向上的求解问题的,先将最小规模的子问题的最优解求出,通常都用一张表来记录下求得的解,到后来遇到一样的子问题的时候就能够直接查表获得答案,最后就是经过一步一步的迭代得出最后问题的答案了。
个人理解最重要的东西就是必定会要一个数组或者其余的存储结构存储获得的子问题的解。这样就能够省不少时间,也就是典型的空间换时间
动态规划的一种变形就是记忆化搜索,就是根据动归方程写出递归式,而后在函数的开头直接返回之前计算过的结果,固然这样作也须要一个存储结构记下前面计算过的结果,因此又称为记忆化搜索。算法

例题:pku1088滑雪数组

Michael喜欢滑雪百这并不奇怪, 由于滑雪的确很刺激。但是为了得到速度,滑的区域必须向下倾斜,并且当你滑到坡底,你不得再也不次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每一个数字表明点的高度。下面是一个例子 
 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

一我的能够从某个点滑向上下左右相邻四个点之一,当且仅当高度减少。在上面的例子中,一条可滑行的滑坡为24-17-16-1。固然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
 

Input

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,表明高度h,0<=h<=10000。
 

Output

输出最长区域的长度。
 

Sample Input

5 5
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

Sample Output

25

 

#include < algorithm >
#include < cstdio >
#include < cmath >
#include < cstring >
#include < iostream >
#include < cstdlib >
#include < set >
#include < vector >
#include < cctype >
#include < iomanip >
#include < sstream >
#include < climits >
#include < queue >
#include < stack >
using namespace std;
typedef long long ll ;
#define INF 0X3f3f3f3f
const ll MAXN = 1e3 + 7 ;
const ll MOD = 1e9 + 7 ;
int r , c ;
int mp [MAXN ][MAXN ];
int dp [MAXN ][MAXN ];
int dir [ 4 ][ 2 ] = { 0 , 1 , 0 , - 1 , 1 , 0 , - 1 , 0 };
/* 好比在这个题目中咱们的dfs函数是一个倒着递归的过程,
每次的递归都能将前面的结果记录下来,这就是一个记忆化的过程 */
bool check ( int x , int y )
{
  return (x >= 1 && x <= r && y >= 1 && y <= c );
}
int dfs ( int x , int y )
{
  if (dp [x ][y ]) //记住了就不用再次dfs搜索了
  return dp [x ][y ];
  for ( int i = 0 ; i < 4 ; i ++ )
  {
    int tx = x + dir [i ][ 0 ];
    int ty = y + dir [i ][ 1 ];
    if ( check ( tx , ty ) && mp [tx ][ty ] < mp [x ][y ])
      dp [x ][y ] = max ( dfs ( tx , ty ) + 1 , dp [ x ][ y ]);
  }
  return dp [x ][y ];
}
int main ()
{
  ios::sync_with_stdio ( false );
  memset (dp , 0 , sizeof (dp ));
  cin >> r >> c ;
  for ( int i = 1 ; i <= r ; i ++ )
    for ( int j = 1 ; j <= c ; j ++ )
      cin >> mp [i ][j ];
  int ans = - 1 ;
  for ( int i = 1 ; i <= r ; i ++ )
    for ( int j = 1 ; j <= c ; j ++ )
      ans = max ( ans , dfs ( i , j ));
    cout << ans + 1 << endl ;
  // system("pause");
  return 0 ;
}
相关文章
相关标签/搜索