記憶化搜索

通常說來,動態規劃總要遍歷全部的狀態,而搜索能夠排除一些無效狀態。更重要的是搜索還能夠剪枝,可能剪去大量沒必要要的狀態,所以在空間開銷上每每比動態規劃要低不少。記憶化算法在求解的時候仍是按着自頂向下的順序,可是每求解一個狀態,就將它的解保存下來,之後再次遇到這個狀態的時候,就沒必要從新求解了。這種方法綜合了搜索和動態規劃兩方面的優勢,於是仍是頗有實用價值的。記憶化搜索就至關於以搜索的形式加上動態規劃的思想。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 ;
}
相關文章
相關標籤/搜索