動態規劃是自底向上的,先處理子問題,然後再處理更大的問題。這樣就需要知道子問題和更大的問題之間的聯繫。我們能夠確定出子問題並且能夠正確的求解它,從而從子問題推出要解決的問題的解。
但是,如果當我們比較難確定出子問題是哪一個,比較困難的求出子問題的答案時,可以使用記憶化搜索
以洛谷上的滑雪題爲例
對於這道題,我們沒辦法馬上求得到達某個點的最長長度
因此我們需要使用遞歸方法,並且使用記憶化搜索來進行優化
思路
使用遞歸計算出,到x,y點的最長滑坡長度
遍歷點(x,y)的上下左右四個點,如果一個點的值是小於點(x,y),說明這個點可以滑到點(x,y)
答案爲,四個點中最長滑坡長度的最大值+1
res = max(res,getMax(newx,newy)+1);
使用循環更新數組的值,直到數組所有的值都被更新,找到數組中最大的那個值
代碼
#include <iostream>
#include <vector>
using namespace std;
/**
輸入
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
輸出
25
*/
int memo[105][105];
int quyu[105][105];
int R,C;
bool inArea(int x, int y )
{
return x>=1 && y>=1 && x<=R && y<=C;
}
//到x,y點的最長滑坡長度
int d[4][2] ={0,-1,1,0,-1,0,0,1};
int getMax(int x,int y)
{
//上下左右四個點中可達該點的數
if(memo[x][y]!=-1) return memo[x][y];
int res = 1;
for(int i=0; i<4; i++)
{
int newx = x+d[i][0];
int newy = y+d[i][1];
if(inArea(newx,newy) && quyu[x][y]>quyu[newx][newy])
{
res = max(res,getMax(newx,newy)+1);
}
}
memo[x][y] = res;
return res;
}
int main()
{
cin>>R>>C;
for(int i=1; i<=R; i++)
{
for(int j=1; j<=C; j++)
cin>>quyu[i][j];
}
int res = 0;
for(int i=0; i<105; i++)
for(int j=0; j<105; j++)
memo[i][j]=-1;
for(int i=1; i<=R; i++)
{
for(int j=1; j<=C; j++)
{
if(memo[i][j]==-1)
res=max(res,getMax(i,j));
else
res=max(res,memo[i][j]);
}
}
cout<<res<<endl;
return 0;
}